Skip to content

Instantly share code, notes, and snippets.

@jitomesky
Created April 11, 2014 07:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jitomesky/10446095 to your computer and use it in GitHub Desktop.
Save jitomesky/10446095 to your computer and use it in GitHub Desktop.
fetch Intel Galileo kernel source
define KMACHINE clanton
define KTYPE standard
define KARCH i386
kconf hardware clanton.cfg
#
# Automatically generated file; DO NOT EDIT.
# Linux/i386 3.8.7 Kernel Configuration
#
# CONFIG_64BIT is not set
CONFIG_X86_32=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf32-i386"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_MMU=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_GPIO=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HAS_DEFAULT_IDLE=y
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_ARCH_HAS_CPU_AUTOPROBE=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_ZONE_DMA32 is not set
# CONFIG_AUDIT_ARCH is not set
CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_X86_32_LAZY_GS=y
CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_HAVE_IRQ_WORK=y
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_EXTABLE_SORT=y
#
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_CROSS_COMPILE=""
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y
# CONFIG_KERNEL_GZIP is not set
# CONFIG_KERNEL_BZIP2 is not set
CONFIG_KERNEL_LZMA=y
# CONFIG_KERNEL_XZ is not set
# CONFIG_KERNEL_LZO is not set
CONFIG_DEFAULT_HOSTNAME="(none)"
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_FHANDLE is not set
# CONFIG_AUDIT is not set
CONFIG_HAVE_GENERIC_HARDIRQS=y
#
# IRQ subsystem
#
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_IRQ_DOMAIN=y
# CONFIG_IRQ_DOMAIN_DEBUG is not set
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_KTIME_SCALAR=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CMOS_UPDATE=y
#
# Timers subsystem
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
#
# CPU/Task time and stats accounting
#
CONFIG_TICK_CPU_ACCOUNTING=y
# CONFIG_IRQ_TIME_ACCOUNTING is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
#
# RCU Subsystem
#
CONFIG_TINY_RCU=y
# CONFIG_PREEMPT_RCU is not set
# CONFIG_TREE_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
CONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
# CONFIG_CGROUP_DEVICE is not set
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
# CONFIG_MEMCG is not set
# CONFIG_CGROUP_HUGETLB is not set
# CONFIG_CGROUP_PERF is not set
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_CFS_BANDWIDTH is not set
# CONFIG_RT_GROUP_SCHED is not set
# CONFIG_BLK_CGROUP is not set
# CONFIG_CHECKPOINT_RESTORE is not set
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
# CONFIG_USER_NS is not set
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_UIDGID_CONVERTED=y
# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
# CONFIG_SCHED_AUTOGROUP is not set
# CONFIG_SYSFS_DEPRECATED is not set
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_EXPERT=y
CONFIG_HAVE_UID16=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
# CONFIG_PCSPKR_PLATFORM is not set
CONFIG_HAVE_PCSPKR_PLATFORM=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_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y
# CONFIG_KPROBES is not set
CONFIG_JUMP_LABEL=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_GENERIC_SIGALTSTACK=y
CONFIG_CLONE_BACKWARDS=y
#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
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 is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_MODULE_SIG is not set
CONFIG_BLOCK=y
# CONFIG_LBDAF is not set
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_BSGLIB is not set
# CONFIG_BLK_DEV_INTEGRITY 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=y
# 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 is not set
# CONFIG_SYSV68_PARTITION 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_UNINLINE_SPIN_UNLOCK=y
CONFIG_FREEZER=y
#
# Processor type and features
#
# CONFIG_ZONE_DMA is not set
# CONFIG_SMP is not set
CONFIG_X86_MPPARSE=y
CONFIG_X86_EXTENDED_PLATFORM=y
CONFIG_INTEL_CLN_SOC=y
# CONFIG_INTEL_CLN_SOC_FPGAEMU is not set
CONFIG_INTEL_CLN_SOC_SVP=y
# CONFIG_X86_WANT_INTEL_MID is not set
# CONFIG_X86_RDC321X is not set
CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
#
# Intel Media SOC Gen3 support
#
CONFIG_ARCH_GEN3=y
# CONFIG_X86_32_IRIS is not set
CONFIG_SCHED_OMIT_FRAME_POINTER=y
# CONFIG_PARAVIRT_GUEST is not set
CONFIG_NO_BOOTMEM=y
# CONFIG_MEMTEST is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
CONFIG_M586TSC=y
# CONFIG_M586MMX is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MELAN is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MCORE2 is not set
# CONFIG_MATOM is not set
CONFIG_X86_GENERIC=y
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_L1_CACHE_SHIFT=6
# CONFIG_X86_PPRO_FENCE is not set
CONFIG_X86_F00F_BUG=y
CONFIG_X86_ALIGNMENT_16=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_MINIMUM_CPU_FAMILY=5
# CONFIG_PROCESSOR_SELECT is not set
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_CYRIX_32=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_CPU_SUP_TRANSMETA_32=y
CONFIG_CPU_SUP_UMC_32=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
# CONFIG_DMI is not set
CONFIG_NR_CPUS=1
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
CONFIG_X86_UP_APIC=y
CONFIG_X86_UP_IOAPIC=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
CONFIG_X86_MCE=y
CONFIG_X86_MCE_INTEL=y
# CONFIG_X86_MCE_AMD is not set
# CONFIG_X86_ANCIENT_MCE is not set
CONFIG_X86_MCE_THRESHOLD=y
# CONFIG_X86_MCE_INJECT is not set
CONFIG_X86_THERMAL_VECTOR=y
CONFIG_VM86=y
# CONFIG_TOSHIBA is not set
# CONFIG_I8K is not set
CONFIG_X86_REBOOTFIXUPS=y
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y
# CONFIG_MICROCODE_AMD is not set
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
# CONFIG_NOHIGHMEM is not set
# CONFIG_HIGHMEM4G is not set
CONFIG_HIGHMEM64G=y
CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_HIGHMEM=y
CONFIG_X86_PAE=y
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ILLEGAL_POINTER_VALUE=0
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=999999
# CONFIG_COMPACTION is not set
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
# CONFIG_MEMORY_FAILURE is not set
# CONFIG_TRANSPARENT_HUGEPAGE is not set
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_NEED_PER_CPU_KM=y
# CONFIG_CLEANCACHE is not set
# CONFIG_HIGHPTE is not set
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
CONFIG_X86_RESERVE_LOW=64
# CONFIG_MATH_EMULATION is not set
# CONFIG_MTRR is not set
# CONFIG_ARCH_RANDOM is not set
CONFIG_X86_SMAP=y
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_EFI_CAPSULE=y
CONFIG_SECCOMP=y
# CONFIG_CC_STACKPROTECTOR is not set
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
CONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x400000
# CONFIG_RELOCATABLE is not set
CONFIG_PHYSICAL_ALIGN=0x1000000
# CONFIG_COMPAT_VDSO is not set
# CONFIG_CMDLINE_BOOL is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
#
# Power management and ACPI options
#
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_PM_SLEEP=y
# CONFIG_PM_AUTOSLEEP is not set
# CONFIG_PM_WAKELOCKS is not set
CONFIG_PM_RUNTIME=y
CONFIG_PM=y
CONFIG_PM_DEBUG=y
# CONFIG_PM_ADVANCED_DEBUG is not set
CONFIG_PM_SLEEP_DEBUG=y
CONFIG_PM_TRACE=y
CONFIG_PM_TRACE_RTC=y
CONFIG_ACPI=y
CONFIG_ACPI_SLEEP=y
CONFIG_ACPI_PROCFS=y
CONFIG_ACPI_PROCFS_POWER=y
CONFIG_ACPI_EC_DEBUGFS=y
# CONFIG_ACPI_PROC_EVENT is not set
CONFIG_ACPI_AC=y
# CONFIG_ACPI_BATTERY is not set
CONFIG_ACPI_BUTTON=y
# CONFIG_ACPI_FAN is not set
# CONFIG_ACPI_DOCK is not set
CONFIG_ACPI_I2C=m
CONFIG_ACPI_PROCESSOR=y
# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
CONFIG_ACPI_THERMAL=y
# CONFIG_ACPI_CUSTOM_DSDT is not set
# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
CONFIG_ACPI_PCI_SLOT=y
CONFIG_X86_PM_TIMER=y
# CONFIG_ACPI_CONTAINER is not set
# CONFIG_ACPI_SBS is not set
# CONFIG_ACPI_HED is not set
# CONFIG_ACPI_CUSTOM_METHOD is not set
# CONFIG_ACPI_BGRT is not set
# CONFIG_ACPI_APEI is not set
# CONFIG_SFI is not set
# CONFIG_APM is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
# CONFIG_INTEL_IDLE is not set
#
# Bus options (PCI etc.)
#
CONFIG_PCI=y
# CONFIG_PCI_GOBIOS is not set
# CONFIG_PCI_GOMMCONFIG is not set
# CONFIG_PCI_GODIRECT is not set
CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_CNB20LE_QUIRK is not set
CONFIG_PCIEPORTBUS=y
CONFIG_PCIEAER=y
# CONFIG_PCIE_ECRC is not set
# CONFIG_PCIEAER_INJECT is not set
CONFIG_PCIEASPM=y
# CONFIG_PCIEASPM_DEBUG is not set
CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_PCIE_PME=y
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
CONFIG_PCI_DEBUG=y
# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
# CONFIG_PCI_STUB is not set
CONFIG_HT_IRQ=y
# CONFIG_PCI_IOV is not set
# CONFIG_PCI_PRI is not set
# CONFIG_PCI_PASID is not set
CONFIG_PCI_IOAPIC=y
CONFIG_PCI_LABEL=y
CONFIG_ISA_DMA_API=y
# CONFIG_ISA is not set
# CONFIG_SCx200 is not set
# CONFIG_ALIX is not set
# CONFIG_NET5501 is not set
CONFIG_AMD_NB=y
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_RAPIDIO is not set
#
# Executable file formats / Emulations
#
CONFIG_BINFMT_ELF=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_COREDUMP=y
CONFIG_HAVE_ATOMIC_IOMAP=y
CONFIG_HAVE_TEXT_POKE_SMP=y
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_DIAG is not set
CONFIG_UNIX=y
# CONFIG_UNIX_DIAG is not set
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 is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE_DEMUX is not set
# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
# CONFIG_NET_IPVTI 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=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_INET_UDP_DIAG is not set
# 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=m
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
# CONFIG_IPV6_SIT is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_GRE is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_IPV6_MROUTE is not set
# CONFIG_NETLABEL 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_STP=m
CONFIG_GARP=m
# CONFIG_BRIDGE is not set
CONFIG_HAVE_NET_DSA=y
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
# CONFIG_DECNET is not set
CONFIG_LLC=m
# 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_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_DNS_RESOLVER is not set
# CONFIG_BATMAN_ADV is not set
# CONFIG_OPENVSWITCH is not set
# CONFIG_NETPRIO_CGROUP is not set
CONFIG_BQL=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
CONFIG_BT=m
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
#
# Bluetooth device drivers
#
CONFIG_BT_HCIBTUSB=m
# CONFIG_BT_HCIBTSDIO is not set
# CONFIG_BT_HCIUART is not set
# CONFIG_BT_HCIBCM203X is not set
# CONFIG_BT_HCIBPA10X is not set
# CONFIG_BT_HCIBFUSB is not set
CONFIG_BT_HCIVHCI=m
# CONFIG_BT_MRVL is not set
# CONFIG_BT_ATH3K is not set
# CONFIG_AF_RXRPC is not set
CONFIG_WIRELESS=y
CONFIG_WEXT_CORE=y
CONFIG_WEXT_PROC=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_CERTIFICATION_ONUS is not set
CONFIG_CFG80211_DEFAULT_PS=y
# CONFIG_CFG80211_DEBUGFS is not set
# CONFIG_CFG80211_INTERNAL_REGDB is not set
CONFIG_CFG80211_WEXT=y
# CONFIG_LIB80211 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=y
# CONFIG_MAC80211_DEBUGFS is not set
# CONFIG_MAC80211_MESSAGE_TRACING is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
# CONFIG_WIMAX is not set
CONFIG_RFKILL=m
CONFIG_RFKILL_LEDS=y
CONFIG_RFKILL_INPUT=y
# CONFIG_NET_9P is not set
# CONFIG_CAIF is not set
# CONFIG_CEPH_LIB is not set
# CONFIG_NFC is not set
#
# Device Drivers
#
#
# Generic Driver Options
#
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
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=y
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_GENERIC_CPU_DEVICES is not set
CONFIG_DMA_SHARED_BUFFER=y
# CONFIG_CMA is not set
#
# Bus devices
#
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=m
CONFIG_MTD_BLKDEVS=m
CONFIG_MTD_BLOCK=m
# 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_TS5500 is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_PMC551 is not set
# CONFIG_MTD_DATAFLASH is not set
CONFIG_MTD_M25P80=m
CONFIG_M25PXX_USE_FAST_READ=y
# 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_MTD_CLN_ROM is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOCG3 is not set
# CONFIG_MTD_NAND is not set
# CONFIG_MTD_ONENAND is not set
#
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
CONFIG_PNP=y
# CONFIG_PNP_DEBUG_MESSAGES is not set
#
# Protocols
#
CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_DRBD is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_NVME is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_BLK_DEV_RAM_SIZE=81920
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
# CONFIG_BLK_DEV_HD is not set
# CONFIG_BLK_DEV_RBD is not set
#
# Misc devices
#
# CONFIG_SENSORS_LIS3LV02D is not set
# CONFIG_AD525X_DPOT is not set
# CONFIG_IBM_ASM is not set
# CONFIG_PHANTOM is not set
# CONFIG_INTEL_MID_PTI is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO 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_VMWARE_BALLOON is not set
# CONFIG_BMP085_I2C is not set
# CONFIG_BMP085_SPI is not set
# CONFIG_PCH_PHUB is not set
# CONFIG_USB_SWITCH_FSA9480 is not set
# CONFIG_C2PORT is not set
#
# EEPROM support
#
CONFIG_EEPROM_AT24=m
# 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_EEPROM_93XX46 is not set
# CONFIG_CB710_CORE is not set
#
# Texas Instruments shared transport line discipline
#
# CONFIG_TI_ST is not set
# CONFIG_SENSORS_LIS3_I2C is not set
#
# Altera FPGA firmware download module
#
# CONFIG_ALTERA_STAPL 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=y
# CONFIG_CHR_DEV_SCH is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# 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 is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_TARGET_CORE is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
# CONFIG_FIREWIRE is not set
# CONFIG_FIREWIRE_NOSY is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y
# CONFIG_BONDING is not set
# CONFIG_DUMMY is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_FC is not set
CONFIG_MII=y
# CONFIG_NET_TEAM is not set
# CONFIG_MACVLAN is not set
# CONFIG_VXLAN is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
#
# CAIF transport drivers
#
#
# Distributed Switch Architecture drivers
#
# CONFIG_NET_DSA_MV88E6XXX is not set
# CONFIG_NET_DSA_MV88E6060 is not set
# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
# CONFIG_NET_DSA_MV88E6131 is not set
# CONFIG_NET_DSA_MV88E6123_61_65 is not set
CONFIG_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
# CONFIG_NET_VENDOR_ALTEON is not set
# CONFIG_NET_VENDOR_AMD is not set
# CONFIG_NET_VENDOR_ATHEROS is not set
CONFIG_NET_CADENCE=y
# CONFIG_ARM_AT91_ETHER is not set
# CONFIG_MACB is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_BROCADE is not set
# CONFIG_NET_CALXEDA_XGMAC is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
# CONFIG_NET_VENDOR_CISCO is not set
# CONFIG_DNET is not set
# CONFIG_NET_VENDOR_DEC is not set
# CONFIG_NET_VENDOR_DLINK is not set
# CONFIG_NET_VENDOR_EMULEX is not set
# CONFIG_NET_VENDOR_EXAR is not set
# CONFIG_NET_VENDOR_HP is not set
CONFIG_NET_VENDOR_INTEL=y
# CONFIG_E100 is not set
CONFIG_E1000=m
# CONFIG_E1000E is not set
# CONFIG_IGB is not set
# CONFIG_IGBVF is not set
# CONFIG_IXGB is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGBEVF is not set
# CONFIG_NET_VENDOR_I825XX is not set
# CONFIG_IP1000 is not set
# CONFIG_JME is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MELLANOX is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MYRI is not set
# CONFIG_FEALNX is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NVIDIA is not set
# CONFIG_NET_VENDOR_OKI is not set
# CONFIG_ETHOC is not set
# CONFIG_NET_PACKET_ENGINE is not set
# CONFIG_NET_VENDOR_QLOGIC is not set
# CONFIG_NET_VENDOR_REALTEK is not set
# CONFIG_NET_VENDOR_RDC is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SILAN is not set
# CONFIG_NET_VENDOR_SIS is not set
# CONFIG_SFC is not set
# CONFIG_NET_VENDOR_SMSC is not set
CONFIG_NET_VENDOR_STMICRO=y
CONFIG_STMMAC_ETH=m
# CONFIG_STMMAC_PLATFORM is not set
CONFIG_STMMAC_PCI=y
# CONFIG_STMMAC_DEBUG_FS is not set
CONFIG_STMMAC_DA=y
# CONFIG_STMMAC_PTP is not set
CONFIG_STMMAC_RING=y
# CONFIG_STMMAC_CHAINED is not set
# CONFIG_NET_VENDOR_SUN is not set
# CONFIG_NET_VENDOR_TEHUTI is not set
# CONFIG_NET_VENDOR_TI is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_NET_SB1000 is not set
CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
# CONFIG_AT803X_PHY is not set
# CONFIG_AMD_PHY is not set
# 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_BCM87XX_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_MICREL_KS8995MA is not set
CONFIG_PPP=m
# CONFIG_PPP_BSDCOMP is not set
CONFIG_PPP_DEFLATE=m
# CONFIG_PPP_FILTER is not set
# CONFIG_PPP_MPPE is not set
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPPOE is not set
CONFIG_PPP_ASYNC=m
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_SLIP is not set
CONFIG_SLHC=m
#
# 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 is not set
# CONFIG_USB_HSO is not set
# CONFIG_USB_IPHETH is not set
CONFIG_WLAN=y
# CONFIG_LIBERTAS_THINFIRM is not set
# CONFIG_AIRO is not set
# CONFIG_ATMEL is not set
# CONFIG_AT76C50X_USB is not set
# CONFIG_PRISM54 is not set
# CONFIG_USB_ZD1201 is not set
# CONFIG_USB_NET_RNDIS_WLAN is not set
# CONFIG_RTL8180 is not set
# CONFIG_RTL8187 is not set
# CONFIG_ADM8211 is not set
# CONFIG_MAC80211_HWSIM is not set
# CONFIG_MWL8K is not set
# CONFIG_ATH_CARDS is not set
# CONFIG_B43 is not set
# CONFIG_B43LEGACY is not set
# CONFIG_BRCMFMAC is not set
# CONFIG_HOSTAP is not set
# CONFIG_IPW2100 is not set
# CONFIG_IPW2200 is not set
CONFIG_IWLWIFI=m
CONFIG_IWLDVM=m
#
# Debugging Options
#
# CONFIG_IWLWIFI_DEBUG is not set
# CONFIG_IWLWIFI_P2P is not set
# CONFIG_IWL4965 is not set
# CONFIG_IWL3945 is not set
# CONFIG_LIBERTAS is not set
# CONFIG_HERMES is not set
# CONFIG_P54_COMMON is not set
# CONFIG_RT2X00 is not set
# CONFIG_RTL8192CE is not set
# CONFIG_RTL8192SE is not set
# CONFIG_RTL8192DE is not set
# CONFIG_RTL8723AE is not set
# CONFIG_RTL8192CU is not set
# CONFIG_WL_TI is not set
# CONFIG_ZD1211RW is not set
# CONFIG_MWIFIEX is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# CONFIG_WAN is not set
# CONFIG_VMXNET3 is not set
# CONFIG_ISDN is not set
#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
# CONFIG_INPUT_POLLDEV is not set
# CONFIG_INPUT_SPARSEKMAP is not set
# CONFIG_INPUT_MATRIXKMAP is not set
#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC 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_VT_CONSOLE_SLEEP=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=32
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_SYNCLINK_GT is not set
# CONFIG_NOZOMI is not set
# CONFIG_ISI is not set
# CONFIG_N_HDLC is not set
# CONFIG_N_GSM is not set
# CONFIG_TRACE_SINK is not set
CONFIG_DEVKMEM=y
# CONFIG_STALDRV is not set
#
# Serial drivers
#
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_PNP is not set
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=8
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX310X is not set
# CONFIG_SERIAL_MFD_HSU is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_SCCNXP is not set
# 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_SERIAL_CLN_UART is not set
# CONFIG_SERIAL_PCH_UART is not set
# CONFIG_SERIAL_ARC is not set
# CONFIG_TTY_PRINTK is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
CONFIG_RTC=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_SONYPI is not set
# CONFIG_MWAVE is not set
# CONFIG_PC8736x_GPIO is not set
# CONFIG_NSC_GPIO is not set
# CONFIG_RAW_DRIVER is not set
CONFIG_HPET=y
# CONFIG_HPET_MMAP is not set
# CONFIG_HANGCHECK_TIMER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_TELCLOCK is not set
CONFIG_DEVPORT=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
# CONFIG_I2C_MUX is not set
CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
#
# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
#
# ACPI drivers
#
# CONFIG_I2C_SCMI is not set
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
# CONFIG_I2C_CBUS_GPIO is not set
# CONFIG_I2C_EG20T is not set
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_INTEL_MID is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_PXA_PCI is not set
# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_XILINX is not set
#
# External I2C/SMBus adapter drivers
#
# CONFIG_I2C_DIOLAN_U2C is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TINY_USB is not set
#
# Other I2C/SMBus bus drivers
#
# CONFIG_SCx200_ACB is not set
# 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=y
CONFIG_GEN3_SPI=y
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
# CONFIG_SPI_ALTERA is not set
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
# CONFIG_SPI_OC_TINY is not set
CONFIG_SPI_PXA2XX=m
CONFIG_SPI_PXA2XX_PCI=m
# CONFIG_SPI_CE5XX_SPI_SLAVE is not set
# CONFIG_SPI_SC18IS602 is not set
# CONFIG_SPI_TOPCLIFF_PCH is not set
# CONFIG_SPI_XCOMM is not set
# CONFIG_SPI_XILINX is not set
# CONFIG_SPI_DESIGNWARE is not set
# CONFIG_SPI_LPC_SCH is not set
#
# SPI Protocol Masters
#
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_HSI is not set
#
# PPS support
#
CONFIG_PPS=m
# CONFIG_PPS_DEBUG is not set
#
# PPS clients support
#
# CONFIG_PPS_CLIENT_KTIMER is not set
# CONFIG_PPS_CLIENT_LDISC is not set
# CONFIG_PPS_CLIENT_GPIO is not set
#
# PPS generators support
#
#
# PTP clock support
#
CONFIG_PTP_1588_CLOCK=m
#
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
#
CONFIG_PTP_1588_CLOCK_PCH=m
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_ACPI=y
# CONFIG_DEBUG_GPIO is not set
CONFIG_GPIO_SYSFS=y
#
# Memory mapped GPIO drivers:
#
# CONFIG_GPIO_GENERIC_PLATFORM is not set
# CONFIG_GPIO_IT8761E is not set
# CONFIG_GPIO_TS5500 is not set
CONFIG_GPIO_SCH=m
# CONFIG_GPIO_ICH is not set
# CONFIG_GPIO_VX855 is not set
#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX7300 is not set
# CONFIG_GPIO_MAX732X is not set
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set
# CONFIG_GPIO_ADP5588 is not set
#
# PCI GPIO expanders:
#
# CONFIG_GPIO_BT8XX is not set
# CONFIG_GPIO_AMD8111 is not set
# CONFIG_GPIO_LANGWELL is not set
# CONFIG_GPIO_PCH is not set
# CONFIG_GPIO_ML_IOH is not set
# CONFIG_GPIO_RDC321X is not set
#
# 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:
#
#
# USB 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_GENERIC_ADC_BATTERY is not set
# CONFIG_TEST_POWER is not set
# CONFIG_BATTERY_DS2780 is not set
# CONFIG_BATTERY_DS2781 is not set
# CONFIG_BATTERY_DS2782 is not set
# CONFIG_BATTERY_SBS is not set
# CONFIG_BATTERY_BQ27x00 is not set
# CONFIG_BATTERY_MAX17040 is not set
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_CHARGER_MAX8903 is not set
# CONFIG_CHARGER_LP8727 is not set
# CONFIG_CHARGER_GPIO is not set
# CONFIG_CHARGER_BQ2415X is not set
# CONFIG_CHARGER_SMB347 is not set
# CONFIG_POWER_RESET is not set
# CONFIG_POWER_AVS is not set
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
# CONFIG_FAIR_SHARE is not set
CONFIG_STEP_WISE=y
# CONFIG_USER_SPACE is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set
CONFIG_BCMA_POSSIBLE=y
#
# Broadcom specific AMBA
#
# CONFIG_BCMA is not set
#
# Multifunction device drivers
#
CONFIG_MFD_CORE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_RTSX_PCI is not set
# CONFIG_MFD_TI_AM335X_TSCADC is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_LM3533 is not set
# CONFIG_TPS6105X is not set
# CONFIG_TPS65010 is not set
# CONFIG_TPS6507X is not set
# CONFIG_MFD_TPS65217 is not set
# CONFIG_MFD_TPS65912_SPI is not set
# CONFIG_MFD_STMPE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_ARIZONA_I2C is not set
# CONFIG_MFD_ARIZONA_SPI is not set
# CONFIG_MFD_WM831X_SPI is not set
# CONFIG_MFD_PCF50633 is not set
# CONFIG_MFD_MC13XXX_SPI is not set
# CONFIG_MFD_MC13XXX_I2C is not set
# CONFIG_ABX500_CORE is not set
# CONFIG_EZX_PCAP is not set
# CONFIG_MFD_CS5535 is not set
# CONFIG_MFD_TIMBERDALE is not set
CONFIG_CY8C9540A=m
CONFIG_INTEL_CLN_GIP=m
# CONFIG_INTEL_CLN_GIP_TEST is not set
CONFIG_LPC_SCH=y
# CONFIG_LPC_ICH is not set
# CONFIG_MFD_RDC321X is not set
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_VX855 is not set
# CONFIG_MFD_WL1273_CORE is not set
# CONFIG_MFD_VIPERBOARD is not set
# CONFIG_MFD_RETU is not set
# CONFIG_REGULATOR is not set
CONFIG_MEDIA_SUPPORT=m
#
# Multimedia core support
#
CONFIG_MEDIA_CAMERA_SUPPORT=y
# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
# CONFIG_MEDIA_RADIO_SUPPORT is not set
# CONFIG_MEDIA_RC_SUPPORT is not set
# CONFIG_MEDIA_CONTROLLER is not set
CONFIG_VIDEO_DEV=m
CONFIG_VIDEO_V4L2=m
# CONFIG_VIDEO_ADV_DEBUG is not set
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEOBUF2_CORE=m
CONFIG_VIDEOBUF2_MEMOPS=m
CONFIG_VIDEOBUF2_VMALLOC=m
#
# Media drivers
#
CONFIG_MEDIA_USB_SUPPORT=y
#
# Webcam devices
#
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_GSPCA is not set
# CONFIG_USB_PWC is not set
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
# CONFIG_USB_SN9C102 is not set
#
# Webcam, TV (analog/digital) USB devices
#
# CONFIG_VIDEO_EM28XX is not set
# CONFIG_MEDIA_PCI_SUPPORT is not set
# CONFIG_V4L_PLATFORM_DRIVERS is not set
# CONFIG_V4L_MEM2MEM_DRIVERS is not set
# CONFIG_V4L_TEST_DRIVERS is not set
#
# Supported MMC/SDIO adapters
#
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
#
# Media ancillary drivers (tuners, sensors, i2c, frontends)
#
#
# Encoders, decoders, sensors and other helper chips
#
#
# Audio decoders, processors and mixers
#
# 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_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_ADV7183 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_SAA7110 is not set
# CONFIG_VIDEO_SAA711X 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_SAA717X is not set
# 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_ADV7343 is not set
# CONFIG_VIDEO_ADV7393 is not set
# CONFIG_VIDEO_AK881X is not set
#
# Camera sensor devices
#
# CONFIG_VIDEO_OV7670 is not set
# CONFIG_VIDEO_VS6624 is not set
# CONFIG_VIDEO_MT9V011 is not set
# CONFIG_VIDEO_TCM825X is not set
# CONFIG_VIDEO_SR030PC30 is not set
#
# Flash devices
#
#
# Video improvement chips
#
# CONFIG_VIDEO_UPD64031A is not set
# CONFIG_VIDEO_UPD64083 is not set
#
# Miscelaneous helper chips
#
# CONFIG_VIDEO_THS7303 is not set
# CONFIG_VIDEO_M52790 is not set
#
# Sensors used on soc_camera driver
#
#
# Customise DVB Frontends
#
# CONFIG_DVB_AU8522_V4L is not set
# CONFIG_DVB_TUNER_DIB0070 is not set
# CONFIG_DVB_TUNER_DIB0090 is not set
#
# Tools to develop new frontends
#
# CONFIG_DVB_DUMMY_FE is not set
#
# Graphics support
#
# CONFIG_AGP is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
# CONFIG_VGA_SWITCHEROO is not set
# CONFIG_DRM is not set
# CONFIG_STUB_POULSBO is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
# CONFIG_EXYNOS_VIDEO 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 is not set
# CONFIG_BACKLIGHT_APPLE is not set
# CONFIG_BACKLIGHT_SAHARA is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
# CONFIG_BACKLIGHT_LM3630 is not set
# CONFIG_BACKLIGHT_LM3639 is not set
# CONFIG_BACKLIGHT_LP855X is not set
#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
CONFIG_VGACON_SOFT_SCROLLBACK=y
CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
# HID support
#
CONFIG_HID=y
# CONFIG_HID_BATTERY_STRENGTH is not set
# CONFIG_HIDRAW is not set
# CONFIG_UHID is not set
CONFIG_HID_GENERIC=y
#
# Special HID drivers
#
# CONFIG_HID_A4TECH is not set
# CONFIG_HID_ACRUX is not set
# CONFIG_HID_APPLE is not set
# CONFIG_HID_AUREAL is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CHICONY is not set
# CONFIG_HID_CYPRESS is not set
# CONFIG_HID_DRAGONRISE is not set
# CONFIG_HID_EMS_FF is not set
# CONFIG_HID_ELECOM is not set
# CONFIG_HID_EZKEY is not set
# CONFIG_HID_HOLTEK is not set
# CONFIG_HID_KEYTOUCH is not set
# CONFIG_HID_KYE is not set
# CONFIG_HID_UCLOGIC is not set
# CONFIG_HID_WALTOP is not set
# CONFIG_HID_GYRATION is not set
# CONFIG_HID_ICADE is not set
# CONFIG_HID_TWINHAN is not set
# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_LCPOWER is not set
# CONFIG_HID_LENOVO_TPKBD is not set
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_MAGICMOUSE is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
# CONFIG_HID_MULTITOUCH is not set
# CONFIG_HID_NTRIG is not set
# CONFIG_HID_ORTEK is not set
# CONFIG_HID_PANTHERLORD is not set
# CONFIG_HID_PETALYNX is not set
# CONFIG_HID_PICOLCD is not set
# CONFIG_HID_PRIMAX is not set
# CONFIG_HID_PS3REMOTE is not set
# CONFIG_HID_ROCCAT is not set
# CONFIG_HID_SAITEK is not set
# CONFIG_HID_SAMSUNG is not set
# CONFIG_HID_SONY is not set
# CONFIG_HID_SPEEDLINK is not set
# CONFIG_HID_SUNPLUS is not set
# CONFIG_HID_GREENASIA is not set
# CONFIG_HID_SMARTJOYPLUS is not set
# CONFIG_HID_TIVO is not set
# CONFIG_HID_TOPSEED is not set
# CONFIG_HID_THRUSTMASTER is not set
# CONFIG_HID_WACOM is not set
# CONFIG_HID_WIIMOTE is not set
# CONFIG_HID_ZEROPLUS is not set
# CONFIG_HID_ZYDACRON is not set
# CONFIG_HID_SENSOR_HUB is not set
#
# USB HID support
#
CONFIG_USB_HID=m
# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
#
# USB HID Boot Protocol drivers
#
# CONFIG_USB_KBD is not set
# CONFIG_USB_MOUSE is not set
#
# I2C HID support
#
# CONFIG_I2C_HID is not set
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_COMMON=m
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
#
# 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_DWC3 is not set
# CONFIG_USB_MON is not set
# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_XHCI_HCD is not set
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_EHCI_TT_NEWSCHED=y
CONFIG_USB_EHCI_PCI=m
# 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_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_PLATFORM is not set
# CONFIG_USB_EHCI_HCD_PLATFORM is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
# CONFIG_USB_MUSB_HDRC is not set
# CONFIG_USB_CHIPIDEA is not set
# CONFIG_USB_RENESAS_USBHS is not set
#
# USB Device Class drivers
#
CONFIG_USB_ACM=m
# 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=m
# 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
# 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_STORAGE_ENE_UB6250 is not set
#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
#
# USB port drivers
#
CONFIG_USB_SERIAL=m
# 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_F81232 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_METRO 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=m
# 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_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_ZTE is not set
# CONFIG_USB_SERIAL_SSU100 is not set
# CONFIG_USB_SERIAL_QT2 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_EZUSB_FX2 is not set
#
# USB Physical Layer drivers
#
# CONFIG_USB_ISP1301 is not set
# CONFIG_USB_RCAR_PHY is not set
CONFIG_USB_GADGET=m
# CONFIG_USB_GADGET_DEBUG is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
# CONFIG_USB_GADGET_DEBUG_FS is not set
CONFIG_USB_GADGET_VBUS_DRAW=2
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
#
# USB Peripheral Controller
#
# CONFIG_USB_R8A66597 is not set
# CONFIG_USB_MV_UDC is not set
# CONFIG_USB_M66592 is not set
# CONFIG_USB_AMD5536UDC is not set
# CONFIG_USB_NET2272 is not set
# CONFIG_USB_NET2280 is not set
# CONFIG_USB_GOKU is not set
CONFIG_USB_EG20T=m
# CONFIG_USB_DUMMY_HCD is not set
CONFIG_USB_LIBCOMPOSITE=m
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_ETH_EEM is not set
# CONFIG_USB_G_NCM is not set
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_FUNCTIONFS is not set
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
# CONFIG_USB_G_ACM_MS 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_GPIO_VBUS is not set
# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
# CONFIG_MMC_UNSAFE_RESUME is not set
# 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_PCI=y
# CONFIG_MMC_RICOH_MMC is not set
# CONFIG_MMC_SDHCI_ACPI is not set
CONFIG_MMC_SDHCI_PLTFM=y
# CONFIG_MMC_WBSD is not set
# CONFIG_MMC_TIFM_SD is not set
# CONFIG_MMC_CB710 is not set
# CONFIG_MMC_VIA_SDMMC is not set
# CONFIG_MMC_VUB300 is not set
# CONFIG_MMC_USHC is not set
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=m
#
# LED drivers
#
# CONFIG_LEDS_LM3530 is not set
# CONFIG_LEDS_LM3642 is not set
# 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_PCA9633 is not set
# CONFIG_LEDS_DAC124S085 is not set
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_LT3593 is not set
# CONFIG_LEDS_TCA6507 is not set
# CONFIG_LEDS_LM355x is not set
# CONFIG_LEDS_OT200 is not set
# CONFIG_LEDS_BLINKM is not set
CONFIG_LEDS_TRIGGERS=y
#
# LED Triggers
#
# CONFIG_LEDS_TRIGGER_TIMER is not set
# CONFIG_LEDS_TRIGGER_ONESHOT is not set
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_CPU is not set
# CONFIG_LEDS_TRIGGER_GPIO is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
#
# iptables trigger is under Netfilter config (LED target)
#
# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
CONFIG_DMADEVICES=y
# CONFIG_DMADEVICES_DEBUG is not set
#
# DMA Devices
#
CONFIG_INTEL_MID_DMAC=m
CONFIG_INTEL_MID_PCI=m
CONFIG_INTEL_CLN_DMAC=m
# CONFIG_INTEL_IOATDMA is not set
# CONFIG_TIMB_DMA is not set
# CONFIG_PCH_DMA is not set
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=m
# CONFIG_UIO_CIF is not set
# CONFIG_UIO_PDRV is not set
# CONFIG_UIO_PDRV_GENIRQ is not set
# CONFIG_UIO_DMEM_GENIRQ is not set
# CONFIG_UIO_AEC is not set
# CONFIG_UIO_SERCOS3 is not set
# CONFIG_UIO_PCI_GENERIC is not set
# CONFIG_UIO_NETX is not set
#
# Virtio drivers
#
# CONFIG_VIRTIO_PCI is not set
# CONFIG_VIRTIO_MMIO is not set
#
# Microsoft Hyper-V guest support
#
# CONFIG_HYPERV is not set
CONFIG_STAGING=y
# CONFIG_ET131X is not set
# CONFIG_SLICOSS is not set
# CONFIG_USBIP_CORE is not set
# CONFIG_W35UND is not set
# CONFIG_PRISM2_USB is not set
# CONFIG_ECHO is not set
# CONFIG_COMEDI is not set
# CONFIG_ASUS_OLED is not set
# CONFIG_R8187SE is not set
# CONFIG_RTL8192U is not set
# CONFIG_RTLLIB is not set
# CONFIG_R8712U is not set
# CONFIG_RTS5139 is not set
# CONFIG_TRANZPORT is not set
# CONFIG_USB_SERIAL_QUATECH2 is not set
# CONFIG_VT6655 is not set
# CONFIG_VT6656 is not set
# CONFIG_DX_SEP is not set
#
# IIO staging drivers
#
# CONFIG_IIO_SW_RING is not set
#
# Accelerometers
#
# CONFIG_ADIS16201 is not set
# CONFIG_ADIS16203 is not set
# CONFIG_ADIS16204 is not set
# CONFIG_ADIS16209 is not set
# CONFIG_ADIS16220 is not set
# CONFIG_ADIS16240 is not set
# CONFIG_KXSD9 is not set
# CONFIG_LIS3L02DQ is not set
# CONFIG_SCA3000 is not set
#
# Analog to digital converters
#
# CONFIG_AD7291 is not set
# CONFIG_AD7606 is not set
# CONFIG_AD799X is not set
# CONFIG_AD7780 is not set
# CONFIG_AD7816 is not set
# CONFIG_AD7192 is not set
# CONFIG_ADT7410 is not set
# CONFIG_AD7280 is not set
#
# Analog digital bi-direction converters
#
# CONFIG_ADT7316 is not set
#
# Capacitance to digital converters
#
# CONFIG_AD7150 is not set
# CONFIG_AD7152 is not set
# CONFIG_AD7746 is not set
#
# Direct Digital Synthesis
#
# CONFIG_AD5930 is not set
# CONFIG_AD9832 is not set
# CONFIG_AD9834 is not set
# CONFIG_AD9850 is not set
# CONFIG_AD9852 is not set
# CONFIG_AD9910 is not set
# CONFIG_AD9951 is not set
#
# Digital gyroscope sensors
#
# CONFIG_ADIS16060 is not set
# CONFIG_ADIS16080 is not set
# CONFIG_ADIS16130 is not set
# CONFIG_ADIS16260 is not set
# CONFIG_ADXRS450 is not set
#
# Network Analyzer, Impedance Converters
#
# CONFIG_AD5933 is not set
#
# Inertial measurement units
#
# CONFIG_ADIS16400 is not set
#
# Light sensors
#
# CONFIG_SENSORS_ISL29018 is not set
# CONFIG_SENSORS_ISL29028 is not set
# CONFIG_SENSORS_TSL2563 is not set
# CONFIG_TSL2583 is not set
# CONFIG_TSL2x7x is not set
#
# Magnetometer sensors
#
# CONFIG_SENSORS_AK8975 is not set
# CONFIG_SENSORS_HMC5843 is not set
#
# Active energy metering IC
#
# CONFIG_ADE7753 is not set
# CONFIG_ADE7754 is not set
# CONFIG_ADE7758 is not set
# CONFIG_ADE7759 is not set
# CONFIG_ADE7854 is not set
#
# Resolver to digital converters
#
# CONFIG_AD2S90 is not set
# CONFIG_AD2S1200 is not set
# CONFIG_AD2S1210 is not set
#
# Triggers - standalone
#
# CONFIG_IIO_GPIO_TRIGGER is not set
CONFIG_IIO_SYSFS_TRIGGER=m
# CONFIG_IIO_SIMPLE_DUMMY is not set
# CONFIG_ZSMALLOC is not set
# CONFIG_CRYSTALHD is not set
# CONFIG_ACPI_QUICKSTART is not set
# 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_STAGING_MEDIA is not set
#
# Android
#
# CONFIG_ANDROID is not set
# CONFIG_USB_WPAN_HCD is not set
# CONFIG_WIMAX_GDM72XX is not set
# CONFIG_CSR_WIFI is not set
CONFIG_NET_VENDOR_SILICOM=y
# CONFIG_SBYPASS is not set
# CONFIG_BPCTL is not set
# CONFIG_CED1401 is not set
# CONFIG_DGRP is not set
# CONFIG_SB105X is not set
CONFIG_X86_PLATFORM_DEVICES=y
# CONFIG_ACERHDF is not set
# CONFIG_ASUS_LAPTOP is not set
# CONFIG_FUJITSU_LAPTOP is not set
# CONFIG_FUJITSU_TABLET is not set
# CONFIG_AMILO_RFKILL is not set
# CONFIG_HP_ACCEL is not set
# CONFIG_PANASONIC_LAPTOP is not set
# CONFIG_SONY_LAPTOP is not set
# CONFIG_THINKPAD_ACPI is not set
# CONFIG_SENSORS_HDAPS is not set
# CONFIG_INTEL_MENLOW is not set
# CONFIG_ACPI_WMI is not set
# CONFIG_TOPSTAR_LAPTOP is not set
# CONFIG_TOSHIBA_BT_RFKILL is not set
# CONFIG_ACPI_CMPC is not set
CONFIG_INTEL_CLN_ESRAM=y
CONFIG_INTEL_CLN_ECC_REFRESH_PERIOD=24
CONFIG_INTEL_CLN_ECC_SCRUB=y
# CONFIG_INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG is not set
# CONFIG_INTEL_CLN_ECC_SCRUB_S3_CONFIG is not set
CONFIG_INTEL_CLN_THERMAL=y
# CONFIG_INTEL_IPS is not set
# CONFIG_IBM_RTL is not set
# CONFIG_XO15_EBOOK is not set
# CONFIG_SAMSUNG_LAPTOP is not set
# CONFIG_INTEL_OAKTRAIL is not set
# CONFIG_APPLE_GMUX is not set
#
# Hardware Spinlock drivers
#
CONFIG_CLKSRC_I8253=y
CONFIG_CLKEVT_I8253=y
CONFIG_CLKBLD_I8253=y
# CONFIG_IOMMU_SUPPORT is not set
#
# Remoteproc drivers (EXPERIMENTAL)
#
# CONFIG_STE_MODEM_RPROC is not set
#
# Rpmsg drivers (EXPERIMENTAL)
#
# CONFIG_VIRT_DRIVERS is not set
# CONFIG_PM_DEVFREQ is not set
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
CONFIG_IIO=m
CONFIG_IIO_BUFFER=y
CONFIG_IIO_BUFFER_CB=y
CONFIG_IIO_KFIFO_BUF=m
CONFIG_IIO_TRIGGERED_BUFFER=m
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
#
# Accelerometers
#
#
# Analog to digital converters
#
# CONFIG_AD7266 is not set
CONFIG_AD7298=m
# CONFIG_AD7791 is not set
# CONFIG_AD7793 is not set
# CONFIG_AD7476 is not set
# CONFIG_AD7887 is not set
# CONFIG_MAX1363 is not set
# CONFIG_TI_ADC081C is not set
#
# Amplifiers
#
# CONFIG_AD8366 is not set
#
# Hid Sensor IIO Common
#
#
# Digital to analog converters
#
# CONFIG_AD5064 is not set
# CONFIG_AD5360 is not set
# CONFIG_AD5380 is not set
# CONFIG_AD5421 is not set
# CONFIG_AD5624R_SPI is not set
# CONFIG_AD5446 is not set
# CONFIG_AD5449 is not set
# CONFIG_AD5504 is not set
# CONFIG_AD5755 is not set
# CONFIG_AD5764 is not set
# CONFIG_AD5791 is not set
# CONFIG_AD5686 is not set
# CONFIG_MAX517 is not set
# CONFIG_MCP4725 is not set
#
# Frequency Synthesizers DDS/PLL
#
#
# Clock Generator/Distribution
#
# CONFIG_AD9523 is not set
#
# Phase-Locked Loop (PLL) frequency synthesizers
#
# CONFIG_ADF4350 is not set
#
# Digital gyroscope sensors
#
# CONFIG_ADIS16136 is not set
#
# Inertial measurement units
#
# CONFIG_ADIS16480 is not set
#
# Light sensors
#
# CONFIG_ADJD_S311 is not set
# CONFIG_VCNL4000 is not set
#
# Magnetometer sensors
#
# CONFIG_VME_BUS is not set
CONFIG_PWM=y
CONFIG_PWM_SYSFS=y
# CONFIG_IPACK_BUS is not set
#
# Firmware Drivers
#
# CONFIG_EDD is not set
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_EFI_VARS=m
# CONFIG_DELL_RBU is not set
# CONFIG_DCDBAS is not set
# CONFIG_ISCSI_IBFT_FIND is not set
# CONFIG_GOOGLE_FIRMWARE is not set
#
# File systems
#
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_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 is not set
# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
#
# 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 is not set
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_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TMPFS_XATTR=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# 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
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
CONFIG_NLS_CODEPAGE_850=y
# 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=y
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_MAC_ROMAN is not set
# CONFIG_NLS_MAC_CELTIC is not set
# CONFIG_NLS_MAC_CENTEURO is not set
# CONFIG_NLS_MAC_CROATIAN is not set
# CONFIG_NLS_MAC_CYRILLIC is not set
# CONFIG_NLS_MAC_GAELIC is not set
# CONFIG_NLS_MAC_GREEK is not set
# CONFIG_NLS_MAC_ICELAND is not set
# CONFIG_NLS_MAC_INUIT is not set
# CONFIG_NLS_MAC_ROMANIAN is not set
# CONFIG_NLS_MAC_TURKISH is not set
# CONFIG_NLS_UTF8 is not set
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_READABLE_ASM is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
CONFIG_HEADERS_CHECK=y
# CONFIG_DEBUG_SECTION_MISMATCH is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_LOCKUP_DETECTOR is not set
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_PI_LIST=y
# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
# CONFIG_PROVE_RCU is not set
# CONFIG_SPARSE_RCU_POINTER is not set
CONFIG_LOCKDEP=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_LOCKDEP is not set
CONFIG_TRACE_IRQFLAGS=y
# CONFIG_DEBUG_ATOMIC_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_STACK_USAGE 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_VIRTUAL is not set
# CONFIG_DEBUG_WRITECOUNT is not set
CONFIG_DEBUG_MEMORY_INIT=y
# 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_ARCH_WANT_FRAME_POINTERS=y
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_TRACE is not set
# 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_LKDTM is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_INTERVAL_TREE_TEST is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_BUILD_DOCSRC is not set
# CONFIG_DYNAMIC_DEBUG 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_HAVE_ARCH_KMEMCHECK=y
# CONFIG_KMEMCHECK is not set
# CONFIG_TEST_KSTRTOX is not set
# CONFIG_STRICT_DEVMEM is not set
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
# CONFIG_EARLY_PRINTK_DBGP is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_X86_PTDUMP=y
CONFIG_DEBUG_RODATA=y
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_DEBUG_SET_MODULE_RONX=y
# CONFIG_DEBUG_NX_TEST is not set
# CONFIG_DOUBLEFAULT is not set
# CONFIG_IOMMU_STRESS is not set
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_UDELAY=2
CONFIG_IO_DELAY_TYPE_NONE=3
CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
CONFIG_DEFAULT_IO_DELAY_TYPE=0
CONFIG_DEBUG_BOOT_PARAMS=y
# CONFIG_CPA_DEBUG is not set
CONFIG_OPTIMIZE_INLINING=y
# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
# CONFIG_DEBUG_NMI_SELFTEST is not set
#
# Security options
#
CONFIG_KEYS=y
# CONFIG_ENCRYPTED_KEYS is not set
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY_DMESG_RESTRICT is not set
CONFIG_SECURITY=y
# CONFIG_SECURITYFS is not set
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
# CONFIG_SECURITY_PATH is not set
# CONFIG_SECURITY_SMACK is not set
# CONFIG_SECURITY_TOMOYO is not set
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_SECURITY_YAMA is not set
# CONFIG_IMA is not set
# CONFIG_EVM 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=m
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP2=y
CONFIG_CRYPTO_MANAGER=m
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_USER is not set
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 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 is not set
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
CONFIG_CRYPTO_ECB=m
# 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=y
# CONFIG_CRYPTO_CRC32C_INTEL is not set
# CONFIG_CRYPTO_GHASH is not set
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# 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=m
# 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_AES_586 is not set
# CONFIG_CRYPTO_AES_NI_INTEL is not set
# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_ARC4=m
# 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 is not set
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SALSA20_586 is not set
# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_SERPENT_SSE2_586 is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_TWOFISH_586 is not set
#
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
# Random Number Generation
#
CONFIG_CRYPTO_ANSI_CPRNG=m
# CONFIG_CRYPTO_USER_API_HASH is not set
# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_PADLOCK is not set
# CONFIG_CRYPTO_DEV_GEODE is not set
# CONFIG_ASYMMETRIC_KEY_TYPE is not set
CONFIG_HAVE_KVM=y
# CONFIG_VIRTUALIZATION is not set
# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IO=y
CONFIG_PERCPU_RWSEM=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_SLICEBY4 is not set
# CONFIG_CRC32_SARWATE is not set
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
# CONFIG_CRC8 is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_DQL=y
CONFIG_NLATTR=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_AVERAGE=y
# CONFIG_CORDIC is not set
# CONFIG_DDR is not set
diff --git a/.gitignore b/.gitignore
index 3b8b9b3..3557999 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,11 +64,11 @@ include/generated
arch/*/include/generated
# stgit generated dirs
-patches-*
+#patches-*
# quilt's files
-patches
-series
+#patches
+#series
# cscope files
cscope.*
diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm
new file mode 100644
index 0000000..c479d77
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-pwm
@@ -0,0 +1,79 @@
+What: /sys/class/pwm/
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ The pwm/ class sub-directory belongs to the Generic PWM
+ Framework and provides a sysfs interface for using PWM
+ channels.
+
+What: /sys/class/pwm/pwmchipN/
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ A /sys/class/pwm/pwmchipN directory is created for each
+ probed PWM controller/chip where N is the base of the
+ PWM chip.
+
+What: /sys/class/pwm/pwmchipN/npwm
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ The number of PWM channels supported by the PWM chip.
+
+What: /sys/class/pwm/pwmchipN/export
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ Exports a PWM channel from the PWM chip for sysfs control.
+ Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1.
+
+What: /sys/class/pwm/pwmchipN/unexport
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ Unexports a PWM channel.
+
+What: /sys/class/pwm/pwmchipN/pwmX
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ A /sys/class/pwm/pwmchipN/pwmX directory is created for
+ each exported PWM channel where X is the exported PWM
+ channel number.
+
+What: /sys/class/pwm/pwmchipN/pwmX/period
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ Sets the PWM signal period in nanoseconds.
+
+What: /sys/class/pwm/pwmchipN/pwmX/duty_cycle
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ Sets the PWM signal duty cycle in nanoseconds.
+
+What: /sys/class/pwm/pwmchipN/pwmX/polarity
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ Sets the output polarity of the PWM signal to "normal" or
+ "inversed".
+
+What: /sys/class/pwm/pwmchipN/pwmX/enable
+Date: May 2013
+KernelVersion: 3.11
+Contact: H Hartley Sweeten <hsweeten@visionengravers.com>
+Description:
+ Enable/disable the PWM signal.
+ 0 is disabled
+ 1 is enabled
diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
index 7d2b4c9..1039b68 100644
--- a/Documentation/pwm.txt
+++ b/Documentation/pwm.txt
@@ -45,6 +45,43 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
To start/stop toggling the PWM output use pwm_enable()/pwm_disable().
+Using PWMs with the sysfs interface
+-----------------------------------
+
+If CONFIG_SYSFS is enabled in your kernel configuration a simple sysfs
+interface is provided to use the PWMs from userspace. It is exposed at
+/sys/class/pwm/. Each probed PWM controller/chip will be exported as
+pwmchipN, where N is the base of the PWM chip. Inside the directory you
+will find:
+
+npwm - The number of PWM channels this chip supports (read-only).
+
+export - Exports a PWM channel for use with sysfs (write-only).
+
+unexport - Unexports a PWM channel from sysfs (write-only).
+
+The PWM channels are numbered using a per-chip index from 0 to npwm-1.
+
+When a PWM channel is exported a pwmX directory will be created in the
+pwmchipN directory it is associated with, where X is the number of the
+channel that was exported. The following properties will then be available:
+
+period - The total period of the PWM signal (read/write).
+ Value is in nanoseconds and is the sum of the active and inactive
+ time of the PWM.
+
+duty_cycle - The active time of the PWM signal (read/write).
+ Value is in nanoseconds and must be less than the period.
+
+polarity - Changes the polarity of the PWM signal (read/write).
+ Writes to this property only work if the PWM chip supports changing
+ the polarity. The polarity can only be changed if the PWM is not
+ enabled. Value is the string "normal" or "inversed".
+
+enable - Enable/disable the PWM signal (read/write).
+ 0 - disabled
+ 1 - enabled
+
Implementing a PWM driver
-------------------------
diff --git a/Documentation/usb/linux-cdc-acm.inf b/Documentation/usb/linux-cdc-acm.inf
index f0ffc27..e56f074 100644
--- a/Documentation/usb/linux-cdc-acm.inf
+++ b/Documentation/usb/linux-cdc-acm.inf
@@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys
[SourceDisksFiles]
[SourceDisksNames]
[DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00, USB\VID_8086&PID_BABE
[DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00, USB\VID_8086&PID_BABE
;------------------------------------------------------------------------------
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0694d09..b0bdd36 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -417,6 +417,34 @@ config X86_INTEL_CE
This option compiles in support for the CE4100 SOC for settop
boxes and media devices.
+config INTEL_CLN_SOC
+ bool "Intel Clanton platform support"
+ depends on M586TSC
+ select ARCH_REQUIRE_GPIOLIB
+ ---help---
+ Clanton is a Lakemore based system on chip. This option enables
+ probing for various PCI-IDs of several on-chip devices. This flag
+ serves as the high-level dependency for both north-cluster and
+ south-cluster dependencies associated with Clanton.
+
+choice
+ prompt "Clanton board type"
+ depends on INTEL_CLN_SOC
+ help
+ There are different Clanton SoC boards, ranging from test boards
+ (FPGA emulation, Silicon Verification Platform) to reference
+ boards.
+
+ If unsure, select FPGA emulation.
+
+config INTEL_CLN_SOC_FPGAEMU
+ bool "FPGA emulation"
+
+config INTEL_CLN_SOC_SVP
+ bool "SVP - Silicon Verification Platform"
+
+endchoice
+
config X86_WANT_INTEL_MID
bool "Intel MID platform support"
depends on X86_32
@@ -500,6 +528,13 @@ config X86_SUPPORTS_MEMORY_FAILURE
depends on X86_64 || !SPARSEMEM
select ARCH_SUPPORTS_MEMORY_FAILURE
+menu "Intel Media SOC Gen3 support"
+
+config ARCH_GEN3
+ bool "Enable Intel Media SOC Gen3 support"
+ default y
+
+endmenu
config X86_VISWS
bool "SGI 320/540 (Visual Workstation)"
depends on X86_32 && PCI && X86_MPPARSE && PCI_GODIRECT
@@ -1524,6 +1559,13 @@ config EFI_STUB
See Documentation/x86/efi-stub.txt for more information.
+config EFI_CAPSULE
+ bool "EFI capsule update support"
+ depends on EFI
+ ---help---
+ This kernel feature allows for loading of EFI capsule code
+ with callbacks into the EDK firmware to execute update
+
config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 5ef205c..696ec6a 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -26,7 +26,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
$(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
- $(obj)/piggy.o
+ $(obj)/piggy.o $(obj)/early_imr.o
$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
diff --git a/arch/x86/boot/compressed/early_imr.c b/arch/x86/boot/compressed/early_imr.c
new file mode 100644
index 0000000..b5e9ab1
--- /dev/null
+++ b/arch/x86/boot/compressed/early_imr.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * This file implements a simple binding to provide early isolated memory region
+ * support (IMR) - with the primary goal of encapsulating kernel decompress
+ * target area inside of an IMR before decompression takes place. To that end we
+ * do some very very early PCI accesses here - required in order to waggle the
+ * side-band bits associated with IMR support
+ */
+#include <linux/io.h>
+
+#include "misc.h"
+
+#define INTEL_CLN_SB_CMD_ADDR (0x000000D0)
+#define INTEL_CLN_SB_DATA_ADDR (0x000000D4)
+
+#define INTEL_CLN_SB_MCR_SHIFT (24)
+#define INTEL_CLN_SB_PORT_SHIFT (16)
+#define INTEL_CLN_SB_REG_SHIFT (8)
+#define INTEL_CLN_SB_BYTEEN (0xF0) /* enable all 32 bits */
+
+/* PCI config space reg definitions */
+#define PCI_VENDOR_ID (0x00)
+#define PCI_DEVICE_ID (0x02)
+#define PCI_CLASS_DEVICE (0x0A)
+
+/* IMR related reg address */
+#define CFG_READ_OPCODE (0x10) /* Control Read */
+#define CFG_WRITE_OPCODE (0x11) /* Control write */
+#define DRAM_IMR0L (0x40) /* IMR0RL address */
+#define DRAM_IMR0H (0x41) /* IMR0RL address */
+#define DRAM_IMR0RM (0x42) /* IMR0RM address */
+#define DRAM_IMR0WM (0x43) /* IMR0WM address */
+#define DRAM_IMR1L (0x44) /* IMR1L address */
+#define DRAM_IMR1H (0x45) /* IMR1H address */
+#define DRAM_IMR1RM (0x46) /* IMR1RM address */
+#define DRAM_IMR1WM (0x47) /* IMR1WM address */
+#define DRAM_IMR3L (0x4C) /* IMR3L address */
+#define DRAM_IMR3H (0x4D) /* IMR3H address */
+#define DRAM_IMR3RM (0x4E) /* IMR3RM address */
+#define DRAM_IMR3WM (0x4F) /* IMR3WM address */
+#define DRAM_IMR7L (0x5C) /* IMR7RM address */
+#define DRAM_IMR7H (0x5D) /* IMR7RM address */
+#define DRAM_IMR7RM (0x5E) /* IMR7RM address */
+#define DRAM_IMR7WM (0x5F) /* IMR7WM address */
+
+#define IMR_WRITE_ENABLE_ALL (0xFFFFFFFF)
+#define IMR_READ_ENABLE_ALL (0xBFFFFFFF)
+#define IMR_BASE_ADDR (0x0000)
+#define IMR_LOCK_BIT (0x80000000)
+
+/* Mask of the last 2 bit of IMR address [23:2] */
+#define IMR_MASK (0xFFFFFC)
+
+/* Mask that enables IMR access for Non-SMM Core, Core Snoops Only.*/
+#define IMR_SNOOP_NON_SMM_ENABLE (0x40000001)
+
+/* Mask that enables IMR access for Non-SMM Core Only.*/
+#define IMR_NON_SMM_ENABLE (0x00000001)
+
+/* Max Memory Address */
+#define MAX_MEM_ADDR (0xFFFFFFFF)
+
+enum {
+ SB_ID_HUNIT = 0x03,
+ SB_ID_THERMAL = 0x04,
+ SB_ID_IMRID = 0x05,
+} cln_sb_id;
+
+struct sb_pci_dev {
+ unsigned int bus;
+ unsigned int dev_fn;
+};
+
+static struct sb_pci_dev sb_pcidev;
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+#define CONFIG_CMD(bus, dev_fn, where)\
+ (0x80000000 | (bus << 16) | (dev_fn << 8) | (where & ~3))
+/**
+ * pci_read_config_word
+ *
+ * @param db_pcidev: Pointer to side-band PCI device
+ * @param where: Register offset to read
+ * @param value: Pointer to output parameter
+ * @return nothing
+ *
+ * Utility function to allow simple PCI read of configuration space 16 bit field
+ * via legacy PCI access mechanism.
+ */
+static void pci_read_config_word(struct sb_pci_dev *sb_pcidev,
+ unsigned int where, unsigned short *value)
+{
+ outl(CONFIG_CMD(sb_pcidev->bus, sb_pcidev->dev_fn, where), 0xCF8);
+ *value = inw(0xCFC + (where&2));
+}
+
+/**
+ * pci_read_config_dword
+ *
+ * @param db_pcidev: Pointer to side-band PCI device
+ * @param where: Register offset to read
+ * @param value: Pointer to output parameter
+ * @return nothing
+ *
+ * Utility function to allow simple PCI read of configuration space 32 bit field
+ * via legacy PCI access mechanism.
+ */
+static void pci_read_config_dword(struct sb_pci_dev *sb_pcidev,
+ unsigned int where, unsigned int *value)
+{
+ outl(CONFIG_CMD(sb_pcidev->bus, sb_pcidev->dev_fn, where), 0xCF8);
+ *value = inl(0xCFC);
+}
+
+/**
+ * pci_write_config_word
+ *
+ * @param db_pcidev: Pointer to side-band PCI device
+ * @param where: Register offset to read
+ * @param value: Value to stuff into destination register
+ * @return nothing
+ *
+ * Utility function to allow simple PCI write of configuration space 16 bit
+ * field via legacy PCI access mechanism.
+ */
+static void pci_write_config_word(struct sb_pci_dev *sb_pcidev,
+ unsigned int where, unsigned short value)
+{
+ outl(CONFIG_CMD(sb_pcidev->bus, sb_pcidev->dev_fn, where), 0xCF8);
+ outw(value, 0xCFC + (where&2));
+}
+
+/**
+ * pci_write_config_dword
+ *
+ * @param db_pcidev: Pointer to side-band PCI device
+ * @param where: Register offset to read
+ * @param value: Value to stuff into destination register
+ * @return nothing
+ *
+ * Utility function to allow simple PCI write of configuration space 32 bit
+ * field via legacy PCI access mechanism.
+ */
+static void pci_write_config_dword(struct sb_pci_dev *sb_pcidev,
+ unsigned int where, unsigned int value)
+{
+ outl(CONFIG_CMD(sb_pcidev->bus, sb_pcidev->dev_fn, where), 0xCF8);
+ outl(value, 0xCFC);
+}
+
+/**
+ * intel_cln_early_sb_read_reg
+ *
+ * @param cln_sb_id: Sideband identifier
+ * @param command: Command to send to destination identifier
+ * @param reg: Target register w/r to cln_sb_id
+ * @return nothing
+ *
+ * Utility function to allow thread-safe read of side-band
+ * command - can be different read op-code types - which is why we don't
+ * hard-code this value directly into msg
+ */
+static void intel_cln_early_sb_read_reg(int id, uint8_t cmd, uint8_t reg,
+ uint32_t *data)
+{
+ uint32_t msg = (cmd << INTEL_CLN_SB_MCR_SHIFT) |
+ ((id << INTEL_CLN_SB_PORT_SHIFT) & 0xFF0000) |
+ ((reg << INTEL_CLN_SB_REG_SHIFT) & 0xFF00) |
+ INTEL_CLN_SB_BYTEEN;
+
+ if (data == NULL)
+ return;
+
+ pci_write_config_dword(&sb_pcidev, INTEL_CLN_SB_CMD_ADDR, msg);
+ pci_read_config_dword(&sb_pcidev, INTEL_CLN_SB_DATA_ADDR, data);
+}
+
+/**
+ * intel_cln_early_sb_write_reg
+ *
+ * @param cln_sb_id: Sideband identifier
+ * @param command: Command to send to destination identifier
+ * @param reg: Target register w/r to cln_sb_id
+ * @return nothing
+ *
+ * Utility function to allow thread-safe write of side-band
+ */
+static void intel_cln_early_sb_write_reg(int id, uint8_t cmd, uint8_t reg,
+ uint32_t data)
+{
+ uint32_t msg = (cmd << INTEL_CLN_SB_MCR_SHIFT) |
+ ((id << INTEL_CLN_SB_PORT_SHIFT) & 0xFF0000) |
+ ((reg << INTEL_CLN_SB_REG_SHIFT) & 0xFF00) |
+ INTEL_CLN_SB_BYTEEN;
+
+ pci_write_config_dword(&sb_pcidev, INTEL_CLN_SB_DATA_ADDR, data);
+ pci_write_config_dword(&sb_pcidev, INTEL_CLN_SB_CMD_ADDR, msg);
+}
+
+/* Clanton hardware */
+#define PCI_VENDOR_ID_INTEL (0x8086)
+#define PCI_DEVICE_ID_CLANTON_SB (0x0958)
+
+/**
+ * sb_probe
+ *
+ * @param dev: the PCI device matching
+ * @param id: entry in the match table
+ * @return 0
+ *
+ * Callback from PCI layer when dev/vendor ids match.
+ * Sets up necessary resources
+ */
+static int intel_cln_early_sb_probe(void)
+{
+ int found = 0;
+ uint16_t class;
+ uint16_t device, vendor;
+
+ sb_pcidev.bus = 0;
+ for (sb_pcidev.dev_fn = 0; sb_pcidev.dev_fn < 0xFF;
+ sb_pcidev.dev_fn++) {
+ /* Only probe function 0 on single fn devices */
+ pci_read_config_word(&sb_pcidev, PCI_CLASS_DEVICE, &class);
+
+ if (class == 0xffff)
+ continue;
+
+ pci_read_config_word(&sb_pcidev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word(&sb_pcidev, PCI_DEVICE_ID, &device);
+
+ /* Do early PCI UART init */
+ if (vendor == PCI_VENDOR_ID_INTEL) {
+ if (device == PCI_DEVICE_ID_CLANTON_SB) {
+ /* Found */
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (found == 0)
+ return -1;
+
+ return 0;
+}
+
+
+
+
+/**
+ * addr_hw_ready
+ *
+ * shift input address value to match HW required 1k aligned format
+ */
+static inline uint32_t addr_hw_ready(uint32_t addr)
+{
+ /* memory alignment */
+ addr &= (~((1 << 10) - 1));
+
+ /* prepare input addr in HW required format */
+ addr = (addr >> 8) & IMR_MASK;
+ return addr;
+}
+
+/**
+ * cln_remove_imr
+ *
+ * @return nothing
+ *
+ * write default values to reg to set imr free
+ */
+static void cln_remove_imr(uint8_t reg_l, uint8_t reg_h, uint8_t reg_rm,
+ uint8_t reg_wm)
+{
+ uint32_t tmp_addr;
+
+ intel_cln_early_sb_read_reg(SB_ID_IMRID, CFG_READ_OPCODE, reg_l,
+ &tmp_addr);
+ if (tmp_addr & IMR_LOCK_BIT) {
+ /* Failure to teardown an IMR means we can't guarantee DMA to
+ * the now 'IMR free' region will succeed - so we bug out
+ */
+ error_putstr("IMR LOCKED !\n");
+ while (1)
+ asm("hlt");
+ return;
+ }
+
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE, reg_rm,
+ IMR_READ_ENABLE_ALL);
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE, reg_wm,
+ IMR_WRITE_ENABLE_ALL);
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE, reg_h,
+ IMR_BASE_ADDR);
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE, reg_l,
+ IMR_BASE_ADDR);
+}
+
+/**
+ * cln_remove_imr_grub
+ *
+ * @return nothing
+ * remove imr protection from grub,
+ * set imr rw masks to default
+ */
+static void cln_remove_imr_grub(void)
+{
+ cln_remove_imr(DRAM_IMR0L, DRAM_IMR0H, DRAM_IMR0RM, DRAM_IMR0WM);
+}
+
+/**
+ * cln_remove_imr_boot_params
+ *
+ * @return nothing
+ * remove imr protection from grub,
+ * set imr rw masks to default
+ */
+static void cln_remove_imr_boot_params(void)
+{
+ cln_remove_imr(DRAM_IMR1L, DRAM_IMR1H, DRAM_IMR1RM, DRAM_IMR1WM);
+}
+
+/**
+ * cln_remove_imr_bzimage
+ *
+ * @return nothing
+ * remove imr protection from bzImage,
+ * set imr rw masks to default
+ */
+static void cln_remove_imr_bzimage(void)
+{
+ cln_remove_imr(DRAM_IMR7L, DRAM_IMR7H, DRAM_IMR7RM, DRAM_IMR7WM);
+}
+
+/**
+ * decompress_kernel_imr
+ *
+ * @param command: Command to send to destination identifier
+ * @return nothing
+ *
+ * Early in the boot process it is not possible to get the address of
+ * &__init_end, so instead we setup a temporary IMR from LOAD_PHYSICAL_ADDR to
+ * 2^32 -1. While this IMR is active DMA to this address range is invalid.
+ * Later when the address of __init_end is available (inside the decompressed
+ * kernel) we setup a new IMR for a smaller range and tear down this IMR, to
+ * ensure at all times an IMR is protecting critical sections of the .text
+ * section
+ */
+void decompress_kernel_imr(struct boot_params *boot)
+{
+ uint32_t imr_hi_addr;
+ uint32_t imr_lo_addr;
+
+ if (intel_cln_early_sb_probe() != 0) {
+ debug_putstr("NO Early SB support !\n");
+ return;
+ }
+
+ /* Set extent of initial decompress IMR */
+ imr_lo_addr = addr_hw_ready(LOAD_PHYSICAL_ADDR);
+ imr_hi_addr = addr_hw_ready(MAX_MEM_ADDR);
+
+ /* Set boundaries and access rights of new IMR */
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE,
+ DRAM_IMR3H, imr_hi_addr);
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE,
+ DRAM_IMR3L, imr_lo_addr);
+
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE,
+ DRAM_IMR3RM, IMR_NON_SMM_ENABLE);
+ intel_cln_early_sb_write_reg(SB_ID_IMRID, CFG_WRITE_OPCODE,
+ DRAM_IMR3WM, IMR_SNOOP_NON_SMM_ENABLE);
+
+ /* Teardown unused IMRs */
+ cln_remove_imr_boot_params();
+ cln_remove_imr_bzimage();
+ cln_remove_imr_grub();
+}
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 88f7ff6..31686ee 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -145,6 +145,10 @@ static int lines, cols;
#include "../../../../lib/decompress_unlzo.c"
#endif
+#ifdef CONFIG_INTEL_CLN_SOC
+extern void decompress_kernel_imr(struct boot_params * boot);
+#endif
+
static void scroll(void)
{
int i;
@@ -356,6 +360,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
error("Wrong destination address");
#endif
+#ifdef CONFIG_INTEL_CLN_SOC
+ decompress_kernel_imr(real_mode);
+#endif
+
debug_putstr("\nDecompressing Linux... ");
decompress(input_data, input_len, NULL, NULL, output, NULL, error);
parse_elf(output);
diff --git a/arch/x86/include/asm/cln.h b/arch/x86/include/asm/cln.h
new file mode 100644
index 0000000..b172613
--- /dev/null
+++ b/arch/x86/include/asm/cln.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+#ifndef _ASM_X86_CLN_H
+#define _ASM_X86_CLN_H
+
+#include <linux/pci.h>
+#include <linux/msi.h>
+
+/**
+ * cln_pci_pvm_mask
+ *
+ * Mask PVM bit on a per function basis. Clanton SC components have but one
+ * vector each - so we mask for what we need
+ */
+static inline void cln_pci_pvm_mask(struct pci_dev * dev)
+{
+ struct msi_desc *entry;
+ int mask_bits = 1;
+
+ if(unlikely(dev->msi_enabled == 0))
+ return;
+
+ entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+
+ if(unlikely(entry == NULL))
+ return;
+
+ pci_write_config_dword(dev, entry->mask_pos, mask_bits);
+}
+
+/**
+ * cln_pci_pvm_mask
+ *
+ * UnMask PVM bit on a per function basis. Clanton SC components have but one
+ * vector each - so we unmask for what we need
+ */
+static inline void cln_pci_pvm_unmask(struct pci_dev * dev)
+{
+ struct msi_desc *entry;
+ int mask_bits = 0;
+
+ if(unlikely(dev->msi_enabled == 0))
+ return;
+
+ entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+
+ if(unlikely(entry == NULL))
+ return;
+
+ pci_write_config_dword(dev, entry->mask_pos, mask_bits);
+}
+
+/* Convienence macros */
+#if defined(CONFIG_INTEL_CLN_SOC)
+ #define mask_pvm(x) cln_pci_pvm_mask(x)
+ #define unmask_pvm(x) cln_pci_pvm_unmask(x)
+#else
+ #define mask_pvm(x)
+ #define unmask_pvm(x)
+#endif
+
+/* Serial */
+#if defined(CONFIG_INTEL_CLN_SOC)
+ #define SERIAL_PORT_DFNS
+ #define BASE_BAUD 2764800
+#endif
+
+#endif /* _ASM_X86_CLN_H */
diff --git a/arch/x86/include/asm/imr.h b/arch/x86/include/asm/imr.h
new file mode 100644
index 0000000..b22012b
--- /dev/null
+++ b/arch/x86/include/asm/imr.h
@@ -0,0 +1,22 @@
+/*
+ * imr.h: Intel Clanton platform imr setup code
+ *
+ * (C) Copyright 2012 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _ASM_X86_IMR_H
+#define _ASM_X86_IMR_H
+
+#if defined(CONFIG_INTEL_CLN_SOC)
+ extern int intel_cln_imr_runt_setparams(void);
+ extern int intel_cln_imr_lockall(void);
+#else
+ static void intel_cln_imr_runt_setparams(void){}
+ static void intel_cln_imr_lockall(void){}
+#endif
+
+#endif /* _ASM_X86_IMR_H */
diff --git a/arch/x86/include/asm/serial.h b/arch/x86/include/asm/serial.h
index 628c801..3965f86 100644
--- a/arch/x86/include/asm/serial.h
+++ b/arch/x86/include/asm/serial.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_SERIAL_H
#define _ASM_X86_SERIAL_H
+#include <asm/cln.h>
+
/*
* This assumes you have a 1.8432 MHz clock for your UART.
*
@@ -8,7 +10,9 @@
* clock, since the 16550A is capable of handling a top speed of 1.5
* megabits/second; but this requires the faster clock.
*/
+#ifndef BASE_BAUD
#define BASE_BAUD ( 1843200 / 16 )
+#endif
/* Standard COM flags (except for COM4, because of the 8514 problem) */
#ifdef CONFIG_SERIAL_DETECT_IRQ
@@ -19,11 +23,13 @@
#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
#endif
+#ifndef SERIAL_PORT_DFNS
#define SERIAL_PORT_DFNS \
/* UART CLK PORT IRQ FLAGS */ \
{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
+#endif
#endif /* _ASM_X86_SERIAL_H */
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 8d87439..9892ddb 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -1,6 +1,7 @@
# Platform specific code goes here
obj-y += ce4100/
obj-y += efi/
+obj-y += cln/
obj-y += geode/
obj-y += iris/
obj-y += mrst/
diff --git a/arch/x86/platform/cln/Makefile b/arch/x86/platform/cln/Makefile
new file mode 100644
index 0000000..a60e30d
--- /dev/null
+++ b/arch/x86/platform/cln/Makefile
@@ -0,0 +1,16 @@
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_board_data.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_layout_data.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_plat_data.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_plat_clanton_hill.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_plat_clanton_peak.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_plat_cross_hill.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_plat_kips_bay.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_plat_izmir.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_sb.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_imr.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_imr_kernel.o
+obj-$(CONFIG_INTEL_CLN_ESRAM) += intel_cln_esram.o
+obj-$(CONFIG_INTEL_CLN_SOC) += intel_cln_imr_test.o
+obj-$(CONFIG_INTEL_CLN_ESRAM) += intel_cln_esram_test.o
+#obj-$(CONFIG_INTEL_CLN_ESRAM) += intel_cln_smep_test.o
+
diff --git a/arch/x86/platform/cln/intel_cln_board_data.c b/arch/x86/platform/cln/intel_cln_board_data.c
new file mode 100644
index 0000000..180ec5e
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_board_data.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data accessor layer
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define DRIVER_NAME "board_data"
+#define PFX "MFH: "
+#define SPIFLASH_BASEADDR 0xFFF00000
+#define MFH_OFFSET 0x00008000
+#define PLATFORM_DATA_OFFSET 0x00010000
+#define MTD_PART_OFFSET 0x00050000
+#define MTD_PART_LEN 0x00040000
+#define MFH_PADDING 0x1E8
+#define MFH_MAGIC 0x5F4D4648
+#define FLASH_SIZE 0x00400000
+
+/* MFH types supported @ version #1 */
+#define MFH_ITEM_FW_STAGE1 0x00000000
+#define MFH_ITEM_FW_STAGE1_SIGNED 0x00000001
+#define MFH_ITEM_FW_STAGE2 0x00000003
+#define MFH_ITEM_FW_STAGE2_SIGNED 0x00000004
+#define MFH_ITEM_FW_STAGE2_CONFIG 0x00000005
+#define MFH_ITEM_FW_STAGE2_CONFIG_SIGNED 0x00000006
+#define MFH_ITEM_FW_PARAMS 0x00000007
+#define MFH_ITEM_FW_RECOVERY 0x00000008
+#define MFH_ITEM_FW_RECOVERY_SIGNED 0x00000009
+#define MFH_ITEM_BOOTLOADER 0x0000000B
+#define MFH_ITEM_BOOTLOADER_SIGNED 0x0000000C
+#define MFH_ITEM_BOOTLOADER_CONFIG 0x0000000D
+#define MFH_ITEM_BOOTLOADER_CONFIG_SIGNED 0x0000000E
+#define MFH_ITEM_KERNEL 0x00000010
+#define MFH_ITEM_KERNEL_SIGNED 0x00000011
+#define MFH_ITEM_RAMDISK 0x00000012
+#define MFH_ITEM_RAMDISK_SIGNED 0x00000013
+#define MFH_ITEM_LOADABLE_PROGRAM 0x00000015
+#define MFH_ITEM_LOADABLE_PROGRAM_SIGNED 0x00000016
+#define MFH_ITEM_BUILD_INFO 0x00000018
+#define MFH_ITEM_VERSION 0x00000019
+
+struct intel_cln_mfh {
+ u32 id;
+ u32 ver;
+ u32 flags;
+ u32 next_block;
+ u32 item_count;
+ u32 boot_priority_list;
+ u8 padding[MFH_PADDING];
+};
+
+struct intel_cln_mfh_item {
+ u32 type;
+ u32 addr;
+ u32 len;
+ u32 res0;
+};
+
+static struct resource conf_res __initdata = {
+ .flags = IORESOURCE_MEM,
+ .start = 0,
+ .end = 0,
+};
+
+static struct resource plat_res __initdata = {
+ .flags = IORESOURCE_MEM,
+ .start = 0,
+ .end = 0,
+};
+
+static struct resource mtd_res __initdata = {
+ .flags = IORESOURCE_MEM,
+ .start = SPIFLASH_BASEADDR + MTD_PART_OFFSET,
+ .end = SPIFLASH_BASEADDR + MTD_PART_OFFSET + MTD_PART_LEN,
+};
+
+static struct platform_device conf_pdev = {
+ .name = "cln-layout-conf",
+ .id = -1,
+ .resource = &conf_res,
+};
+
+static struct platform_device plat_pdev = {
+ .name = "cln-plat",
+ .id = -1,
+ .resource = &plat_res,
+};
+
+struct kobject * board_data_kobj;
+EXPORT_SYMBOL_GPL(board_data_kobj);
+
+static bool mfh_plat_found = false;
+
+static long unsigned int flash_version_data;
+static ssize_t flash_version_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 12, "%#010lx\n", flash_version_data);
+}
+
+static struct kobj_attribute flash_version_attr =
+ __ATTR(flash_version, 0644, flash_version_show, NULL);
+
+/**
+ * intel_cln_board_data_init
+ *
+ * Module entry point
+ */
+static int __init intel_cln_board_data_init(void)
+{
+ extern struct kobject * firmware_kobj;
+ struct intel_cln_mfh __iomem * mfh;
+ struct intel_cln_mfh_item __iomem * item;
+ struct platform_device * pdev;
+ u32 count;
+ void __iomem * spi_data;
+
+ spi_data = ioremap(SPIFLASH_BASEADDR, FLASH_SIZE);
+ if (!spi_data)
+ return -ENODEV;
+
+ /* get mfh and first item pointer */
+ mfh = spi_data + MFH_OFFSET;
+ if (mfh->id != MFH_MAGIC){
+ pr_err(PFX"Bad MFH magic want 0x%08x found 0x%08x @ 0x%p\n",
+ MFH_MAGIC, mfh->id, &mfh->id);
+ return -ENODEV;
+ }
+
+ pr_info(PFX"mfh @ 0x%p: id 0x%08lx ver 0x%08lx entries 0x%08lx\n",
+ mfh, (unsigned long)mfh->id, (unsigned long)mfh->ver,
+ (unsigned long)mfh->item_count);
+ item = (struct intel_cln_mfh_item __iomem *)
+ &mfh->padding [sizeof(u32) * mfh->boot_priority_list];
+
+ /* board_data_kobj subordinate of firmware @ /sys/firmware/board_data */
+ board_data_kobj = kobject_create_and_add("board_data", firmware_kobj);
+ if (!board_data_kobj) {
+ pr_err(PFX"kset create error\n");
+ return -ENODEV;
+ }
+
+ /* Register flash regions as seperate platform devices */
+ for (count = 0; count < mfh->item_count; count++, item++){
+ pdev = NULL;
+
+ switch (item->type){
+ case MFH_ITEM_BUILD_INFO:
+ conf_res.start = item->addr;
+ conf_res.end = item->addr + item->len;
+ pdev = &conf_pdev;
+ break;
+ case MFH_ITEM_VERSION:
+ flash_version_data = item->res0;
+ if(sysfs_create_file(board_data_kobj,
+ &flash_version_attr.attr)) {
+ pr_err("failed to create sysfs entry for flash version\n");
+ flash_version_data = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (pdev != NULL)
+ platform_device_register(pdev);
+ }
+
+ /* This ought to be encoded in the MFH ! */
+ if (mfh_plat_found == false){
+ pr_err(PFX"Warning platform data MFH missing - using hardcoded "
+ "offsets\n");
+
+ /* Platform data */
+ plat_res.start = SPIFLASH_BASEADDR + PLATFORM_DATA_OFFSET;
+ count = *(uint32_t*)(spi_data + PLATFORM_DATA_OFFSET + sizeof(uint32_t));
+ plat_res.end = count;
+ platform_device_register(&plat_pdev);
+ }
+
+ iounmap(spi_data);
+ return 0;
+}
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Intel Clanton SPI Data API");
+MODULE_LICENSE("Dual BSD/GPL");
+module_init(intel_cln_board_data_init);
+
diff --git a/arch/x86/platform/cln/intel_cln_esram.c b/arch/x86/platform/cln/intel_cln_esram.c
new file mode 100644
index 0000000..91eaed7
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_esram.c
@@ -0,0 +1,1188 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton eSRAM overlay driver
+ *
+ * eSRAM is an on-chip fast access SRAM.
+ *
+ * This driver provides the ability to map a kallsyms derived symbol of
+ * arbitrary length or a struct page entitiy.
+ * A proc interface is provided to allow map of kernel structures, without
+ * having to use the API from your code directly.
+ *
+ * Example:
+ * echo ehci on > /proc/driver/esram/map
+ *
+ * An API is provided to allow for mapping of a) kernel symbols or b) pages.
+ * eSRAM requires 4k physically aligned addresses to work - so a struct page
+ * fits neatly into this.
+ *
+ * intel_cln_esram_map_sym(ohci_irq);
+ * intel_cln_esram_map_page(virt_to_page(ohci_irq), "ohci_irq");
+ * Are equivalent - with the exception that map_sym() can detect if a mapping
+ * crosses a page-boundary, whereas map_page just maps one page. Generally use
+ * map_sym() for code and map_page() for data
+ *
+ * To populte eSRAM we must copy data to a temporary buffer, overlay and
+ * then copy data back to the eSRAM region.
+ *
+ * When entering S3 - we must save eSRAM state to DRAM, and similarly on restore
+ * to S0 we must repopulate eSRAM
+ * Unmap code is included for reference however the cache coherency of unmap is
+ * not guaranteed so the functionality is not exported by this code
+ *
+ */
+#include <asm/cacheflush.h>
+#include <asm/desc.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/special_insns.h>
+#include <asm-generic/uaccess.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/kallsyms.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+
+#include "intel_cln_esram.h"
+
+#define DRIVER_NAME "intel-cln-esram"
+#define INTEL_CLN_ESRAM_PROCDIR "driver/esram"
+#define STATS "stats"
+#define MAPPED "map"
+
+/* Shorten fn names to fit 80 char limit */
+#ifndef sb_read
+#define sb_read intel_cln_sb_read_reg
+#endif
+#ifndef sb_write
+#define sb_write intel_cln_sb_write_reg
+#endif
+
+/* Define size of pages, ECC scrub demark etc */
+#define MAX_PAGE_RETRIES (100)
+#define MS_PER_HOUR (3600000UL)
+#define ESRAM_PAGE_COUNT INTEL_CLN_ESRAM_PAGE_COUNT
+#define ESRAM_PAGE_MASK (0xFFFFF000)
+#define ESRAM_PAGE_SIZE INTEL_CLN_ESRAM_PAGE_SIZE
+#define ESRAM_TOTAL_SIZE (ESRAM_PAGE_COUNT * ESRAM_PAGE_SIZE)
+#define ECC_MAX_REFRESH_PERIOD (48)
+#define ECC_DEFAULT_REFRESH_PERIOD (24)
+#define ECC_DRAM_READSIZE (512) /* bytes per DRAM ECC */
+#define ECC_ESRAM_READSIZE ESRAM_PAGE_SIZE /* bytes per SRAM ECC */
+
+/* Register ID */
+#define ESRAM_PGPOOL_REG (0x80) /* PGPOOL */
+#define ESRAM_CTRL_REG (0x81) /* ESRAMCTRL */
+#define ESRAM_PGBLOCK_REG (0x82) /* Global page ctrl */
+#define ESCRM_ECCCERR_REG (0x83) /* Correctable ECC */
+#define ESRAM_ECCUCERR_REG (0x84) /* Uncorrectable ECC */
+
+/* Reg commands */
+#define ESRAM_CTRL_READ (0x10) /* Config reg */
+#define ESRAM_CTRL_WRITE (0x11) /* Config reg */
+#define ESRAM_PAGE_READ (0x12) /* Page config read */
+#define ESRAM_PAGE_WRITE (0x13) /* Page config write */
+
+/* ESRAMPGPOOL reg 0x80 - r/w opcodes 0x10/0x11 */
+#define ESRAM_PGPOOL_FLUSHING(x) ((x>>18)&0x1FF)
+#define ESRAM_PGPOOL_PGBUSY(x) ((x>>9)&0x1FF)
+
+/* ESRAMCTRL reg 0x81 - r/w opcodes 0x10/0x11 */
+#define ESRAM_CTRL_FLUSHPRI(x) ((x>>25)&0x03) /* DRAM flush priority */
+#define ESRAM_CTRL_SIZE(x) ((x>>16)&0xFF) /* # of 4k pages */
+#define ESRAM_CTRL_ECCTHRESH(x) ((x>>8)&0xFF) /* ECC threshold */
+#define ESRAM_CTRL_THRESHMSG_EN (0x00000080) /* ECC notification */
+#define ESRAM_CTRL_ISAVAIL (0x00000010) /* ESRAM on die ? */
+#define ESRAM_CTRL_BLOCK_MODE (0x00000008) /* Block mode enable */
+#define ESRAM_CTRL_GLOBAL_LOCK (0x00000004) /* Global lock status */
+#define ESRAM_CTRL_FLUSHDISABLE (0x00000002) /* Global flush/dis */
+#define ESRAM_CTRL_SECDEC (0x00000001) /* ECC enable bit */
+
+/* PGBLOCK reg 0x82 - opcode 0x10/0x11 */
+#define ESRAM_PGBLOCK_FLUSHEN (0x80000000) /* Block flush enable */
+#define ESRAM_PGBLOCK_PGFLUSH (0x40000000) /* Flush the block */
+#define ESRAM_PGBLOCK_DISABLE (0x20000000) /* Block mode disable */
+#define ESRAM_PGBLOCK_ENABLE (0x10000000) /* Block mode enable */
+#define ESRAM_PGBLOCK_LOCK (0x08000000) /* Block mode lock en */
+#define ESRAM_PGBLOCK_INIT (0x04000000) /* Block init in prog */
+#define ESRAM_PGBLOCK_BUSY (0x01000000) /* Block is enabled */
+#define ESRAM_PGBLOCK_SYSADDR(x) (x&0x000000FF)
+
+/* ESRAMPGCTRL - opcode 0x12/0x13 */
+#define ESRAM_PAGE_FLUSH_PAGE_EN (0x80000000) /* S3 autoflush */
+#define ESRAM_PAGE_FLUSH (0x40000000) /* Flush page to DRAM */
+#define ESRAM_PAGE_DISABLE (0x20000000) /* page disable bit */
+#define ESRAM_PAGE_EN (0x10000000) /* Page enable */
+#define ESRAM_PAGE_LOCK (0x08000000) /* Page lock en */
+#define ESRAM_PAGE_INITIALISING (0x04000000) /* Init in progress */
+#define ESRAM_PAGE_BUSY (0x01000000) /* Page busy */
+#define ESRAM_PAGE_MAP_SHIFT (12) /* Shift away 12 LSBs */
+
+/* Extra */
+#define ESRAM_MAP_OP (0x01)
+#define ESRAM_UNMAP_OP (0x00)
+
+/**
+ * struct esram_refname
+ *
+ * Structure to hold a linked list of names
+ */
+struct esram_refname {
+ char name[KSYM_SYMBOL_LEN]; /* Name of mapping */
+ struct list_head list;
+};
+
+/**
+ * struct esram_page
+ *
+ * Represents an eSRAM page in our linked list
+ */
+struct esram_page {
+
+ struct list_head list; /* List entry descriptor */
+ struct list_head name_list; /* Linked list for name references */
+ u32 id; /* Page ID */
+ u32 phys_addr; /* Physial address of page */
+ u32 refcount; /* Reference count */
+ u32 vaddr; /* Virtual address of page */
+
+};
+
+/**
+ * struct intel_cln_esram_dev
+ *
+ * Structre to represent module state/data/etc
+ */
+struct intel_cln_esram_dev{
+
+ /* Linux kernel structures */
+ struct list_head page_used; /* Used pages */
+ struct list_head page_free; /* Free pages */
+ spinlock_t slock; /* Spinlock */
+ struct platform_device *pldev; /* Platform device */
+ struct proc_dir_entry *pdir; /* Proc directory */
+ struct proc_dir_entry *pmap; /* /proc/drivers/esram/mapped */
+ struct proc_dir_entry *pstat; /* /proc/drivers/esram/stats */
+
+ /* Actual data */
+ struct esram_page * pages;
+ u8 cbuf[ESRAM_PAGE_SIZE];
+
+ /* Stats */
+ u32 page_count; /* As reported by silicon */
+ u32 page_disable_retries; /* Aggreate count on disable */
+ u32 page_enable_retries; /* Aggregate spin count page enable */
+ u32 page_free_ct; /* Free pages for mapping code section */
+};
+
+static struct intel_cln_esram_dev esram_dev;
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Kallsyms does not provide data addresses. To map important structures such as
+ * the idt and gdt, we need to frig the lookup with the below. Other entities
+ * can similarly be added. Note we map a page from the given address - anything
+ * larger will require additional code to handle
+ */
+struct esram_symex {
+ char * name;
+ void * vaddr;
+ u32 size;
+};
+
+static struct esram_symex esram_symex[] =
+{
+ {
+ .name = "idt_table",
+ .vaddr = &idt_table,
+ .size = ESRAM_PAGE_SIZE,
+ },
+ {
+ .name = "gdt_page",
+ .vaddr = &gdt_page,
+ .size = ESRAM_PAGE_SIZE,
+ },
+};
+
+/**
+ * intel_cln_esram_proc_stat_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Populates eSRAM state via /proc/driver/esram
+ */
+static int intel_cln_esram_proc_stat_read(char * page, char ** start, off_t off,
+ int count, int * eof, void * data)
+
+{
+ struct esram_page * epage = NULL;
+ int len = 0;
+ u32 pgpool = 0, ctrl = 0, pgblock = 0;
+ char * enabled = "enabled";
+ char * disabled = "disabled";
+
+ /* Display page-pool relevant data */
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_PGPOOL_REG, &pgpool, 1);
+ len += snprintf(page, count,
+ "esram-pgpool\t\t\t: 0x%08x\n"
+ "esram-pgpool.free\t\t: %u\n"
+ "esram-pgpool.flushing\t\t: %u\n",
+ pgpool, ESRAM_PGPOOL_PGBUSY(pgpool)+1,
+ ESRAM_PGPOOL_FLUSHING(pgpool) + 1);
+
+ /* Display ctrl reg - most of this is of interest */
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_CTRL_REG, &ctrl, 1);
+ len += snprintf(page + len, count - len,
+ "esram-ctrl\t\t\t: 0x%08x\n"
+ "esram-ctrl.ecc\t\t\t: %s\n"
+ "esram-ctrl.ecc-theshold\t\t: %u\n"
+ "esram-ctrl.pages\t\t: %u\n"
+ "esram-ctrl.dram-flush-priorityi\t: %u\n",
+ ctrl, (ctrl & ESRAM_CTRL_SECDEC) ? enabled : disabled,
+ ESRAM_CTRL_ECCTHRESH(ctrl), ESRAM_CTRL_SIZE(ctrl)+1,
+ ESRAM_CTRL_FLUSHPRI(ctrl));
+
+ /* Display block ctrl/stat - we should be !block mode */
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_PGBLOCK_REG, &pgblock, 1);
+ len += snprintf(page + len, count - len, "esram-block\t\t\t: 0x%08x\n",
+ pgblock);
+
+ /* Print ECC status regs */
+
+ /* Print per-page info */
+ len += snprintf(page + len, count - len,
+ "free page\t\t\t: %u\nused page\t\t\t: %u\n"
+ "refresh \t\t\t: %ums\npage enable retries\t\t: %u\n"
+ "page disable retries\t: %u\n",
+ esram_dev.page_free_ct,
+ esram_dev.page_count-esram_dev.page_free_ct,
+ 0,
+ esram_dev.page_enable_retries,
+ esram_dev.page_disable_retries);
+
+ spin_lock(&esram_dev.slock);
+ if(!list_empty(&esram_dev.page_free)){
+
+ epage = list_first_entry(&esram_dev.page_free, struct esram_page, list);
+ len += snprintf(page + len, count - len,
+ "ecc next page \t\t\t: %u\n",epage->id);
+
+ }
+ spin_unlock(&esram_dev.slock);
+
+ /* Return len indicate eof */
+ *eof = 1;
+ return len;
+}
+
+/**
+ * intel_cln_esram_proc_map_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Read back eSRAM mapped entries
+ */
+static int
+intel_cln_esram_proc_map_read(char * page, char ** start, off_t off,
+ int count, int * eof, void * data)
+
+{
+ struct esram_page * epage = NULL;
+ struct esram_refname * refname = NULL;
+ int len = 0;
+
+ spin_lock(&esram_dev.slock);
+ list_for_each_entry(epage, &esram_dev.page_used, list){
+ /* Print references */
+ list_for_each_entry(refname, &epage->name_list, list){
+ len += snprintf(page + len, count - len,
+ "%s ", refname->name);
+ }
+ /* Print data */
+ len += snprintf(page + len, count - len,
+ "\n\tPage virt 0x%08x phys 0x%08x\n"
+ "\tRefcount %u\n",
+ epage->vaddr, epage->phys_addr,
+ epage->refcount);
+ }
+ spin_unlock(&esram_dev.slock);
+
+ /* Return len indicate eof */
+ *eof = 1;
+ return len;
+}
+
+/**
+ * intel_cln_esram_proc_map_write
+ *
+ * @param file: File pointer
+ * @param buf: Data being sent from user-space
+ * @param count: Number of bytes being sent
+ * @param data: Statically set data in the /proc callback - unused
+ * @return number of bytes successfully written or < 0 to indicate error
+ *
+ * Function allows user-space to switch mappings on/off with a simple
+ * echo idt_table on > /proc/driver/esram/map type command
+ */
+static int
+intel_cln_esram_proc_map_write(struct file *file, const char __user *buf,
+ unsigned long count, void *data )
+{
+ ssize_t ret = 0;
+ char * cbuf = NULL;
+ char * sbuf = NULL;
+ unsigned long vaddr = 0, i = 0;
+
+ if(count <= 1){
+ return -EINVAL;
+ }
+
+ /* Get input */
+ sbuf = cbuf = kzalloc(count+1, GFP_KERNEL);
+ if(cbuf == NULL){
+ return -ENOMEM;
+ }
+
+ ret = -EFAULT;
+ if(copy_from_user(cbuf, buf, count))
+ goto done;
+
+ /* Fixup entity to scrub spaces */
+ while(sbuf < (cbuf + count)){
+ if(*sbuf == ' ' || *sbuf == '\r' || *sbuf =='\n'){
+ *sbuf = 0;
+ break;
+ }
+ sbuf++;
+ }
+
+ /* Check to see if we are being asked to map a non-kallsyms addr */
+ for(i = 0; i < sizeof(esram_symex)/sizeof(struct esram_symex); i++){
+ if(strcmp(cbuf, esram_symex[i].name) == 0){
+ ret = intel_cln_esram_map_range(
+ esram_symex[i].vaddr,
+ esram_symex[i].size,
+ esram_symex[i].name);
+ goto done;
+ }
+ }
+
+ /* This path relies on kallsyms to provide name/address data */
+ vaddr = kallsyms_lookup_name(cbuf);
+ if(vaddr == 0)
+ goto done;
+
+ ret = intel_cln_esram_map_symbol((void*)vaddr);
+done:
+ if(ret == 0)
+ ret = (ssize_t)count;
+ kfree(cbuf);
+ return ret;
+}
+
+/**
+ * intel_cln_esram_add_procfs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Adds entries to procfs
+ */
+static int intel_cln_esram_proc_add(void)
+{
+ esram_dev.pdir = proc_mkdir(INTEL_CLN_ESRAM_PROCDIR, NULL);
+ if(esram_dev.pdir == NULL){
+ return -ENOMEM;
+ }
+
+ esram_dev.pstat = create_proc_read_entry(STATS, 0, esram_dev.pdir,
+ intel_cln_esram_proc_stat_read,
+ NULL);
+ if(esram_dev.pstat == NULL){
+ return -EIO;
+ }
+
+ esram_dev.pmap = create_proc_entry(MAPPED, 0, esram_dev.pdir);
+ if(esram_dev.pmap == NULL){
+ return -EIO;
+ }
+ esram_dev.pmap->read_proc = intel_cln_esram_proc_map_read;
+ esram_dev.pmap->write_proc = intel_cln_esram_proc_map_write;
+ esram_dev.pmap->data = NULL;
+
+ return 0;
+}
+
+/**
+ * intel_cln_esram_proc_remove
+ *
+ * @return nothing
+ *
+ * Removes /proc entires
+ */
+static void intel_cln_esram_proc_remove(void)
+{
+ remove_proc_entry(MAPPED, esram_dev.pmap);
+ remove_proc_entry(STATS, esram_dev.pstat);
+ remove_proc_entry(INTEL_CLN_ESRAM_PROCDIR, NULL);
+}
+
+#else
+
+static int intel_cln_esram_proc_add(void){ return 0; }
+static void intel_cln_esram_proc_remove(void){ return; }
+
+#endif /* CONFIG_PROC_FS */
+
+/******************************************************************************
+ * eSRAM Core
+ ******************************************************************************/
+
+/**
+ * intel_cln_esram_page_busy
+ *
+ * @param epage: Pointer to the page descriptor
+ * @return boolean indicating whether or not a page is enabled
+ */
+static int intel_cln_esram_page_busy(struct esram_page * epage, u8 lock)
+{
+ u32 reg = 0;
+
+ sb_read(SB_ID_ESRAM, ESRAM_PAGE_READ, epage->id, &reg, lock);
+ return (reg&(ESRAM_PAGE_BUSY | ESRAM_PAGE_FLUSH | ESRAM_PAGE_DISABLE));
+}
+
+/**
+ * intel_cln_esram_fault
+ *
+ * Dump eSRAM registers and kernel panic
+ * Nothing else to do at this point
+ */
+void intel_cln_esram_fault(struct esram_page * epage, u32 lineno)
+{
+ u32 reg = 0, next = 0, prev = 0, prev_reg = 0;
+ u32 next_reg = 0, block = 0, ctrl = 0;
+
+ pr_err("eSRAM fault @ %s:%d\n", __FILE__, lineno);
+ sb_read(SB_ID_ESRAM, ESRAM_PAGE_READ, epage->id, &reg, 1);
+ pr_err("read page %d state 0x%08x\n", epage->id, reg);
+ if(epage->id == 0){
+ next = 1; prev = 127;
+ }else if(epage->id == 127){
+ next = 0; prev = 126;
+ }else{
+ next = epage->id+1;
+ prev = epage->id-1;
+ }
+ sb_read(SB_ID_ESRAM, ESRAM_PAGE_READ, next, &next_reg, 1);
+ sb_read(SB_ID_ESRAM, ESRAM_PAGE_READ, prev, &prev_reg, 1);
+
+ /* Get state */
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_CTRL_REG, &ctrl, 1);
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_PGBLOCK_REG, &block, 1);
+
+ pr_err("eSRAM CTRL 0x%08x block 0x%08x\n", ctrl, block);
+ pr_err("Prev page %d state 0x%08x Next page %d state 0x%08x\n"
+ , next, next_reg, prev, prev_reg);
+ BUG();
+}
+
+
+/**
+ * intel_cln_esram_page_enable
+ *
+ * @param epage: struct esram_page carries data to program to register
+ * @param lock: Indicates whether to attain sb spinlock or not
+ *
+ * Enable an eSRAM page spinning for page to become ready.
+ */
+static void intel_cln_esram_page_enable(struct esram_page *epage, u8 lock)
+{
+ u32 ret = 0;
+
+ /* Fault if we try to enable a disabled page */
+ if(intel_cln_esram_page_busy(epage, lock)){
+ intel_cln_esram_fault(epage, __LINE__);
+ }
+
+ /* Program page mapping */
+ sb_write(SB_ID_ESRAM, ESRAM_PAGE_WRITE, epage->id,
+ ESRAM_PAGE_FLUSH_PAGE_EN | ESRAM_PAGE_EN |
+ (epage->phys_addr>>ESRAM_PAGE_MAP_SHIFT), lock);
+ do {
+ /* Poll until page busy bit becomes true */
+ ret = intel_cln_esram_page_busy(epage, lock);
+
+ /* This branch should rarely if ever be true */
+ if(unlikely(ret == 0)){
+ esram_dev.page_enable_retries++;
+ }
+
+ }while(ret == 0);
+}
+
+/**
+ * intel_cln_esram_page_disable_sync
+ *
+ * @param epage: pointer to eSRAM page descriptor
+ *
+ * This function spins waiting for disable bit to clear, useful right after a
+ * disable/disable-flush command. Interrupts are enabled here, sleeping is OK
+ */
+static void intel_cln_esram_page_disable_sync(struct esram_page * epage)
+{
+ u32 ret = 0, retries = 0;
+ do {
+ /* Poll for busy bit clear */
+ ret = intel_cln_esram_page_busy(epage, 1);
+
+ /* This branch should rarely if ever be true */
+ if(unlikely(ret)){
+ esram_dev.page_disable_retries++;
+ retries++;
+ }
+
+ if(retries == MAX_PAGE_RETRIES){
+ intel_cln_esram_fault(epage, __LINE__);
+ }
+ }while(ret);
+}
+
+/**
+ * intel_cln_esram_page_disable
+ *
+ * @param epage: struct esram_page carries data to program to register
+ *
+ * Disable the eSRAM page no flush. Interrupts are enabled here, sleeping is OK
+ */
+static void intel_cln_esram_page_disable(struct esram_page *epage)
+{
+ sb_write(SB_ID_ESRAM, ESRAM_PAGE_WRITE, epage->id,
+ ESRAM_PAGE_DISABLE, 1);
+ intel_cln_esram_page_disable_sync(epage);
+}
+
+/**
+ * intel_cln_esram_page_flush_disable
+ *
+ * @param epage: struct esram_page carries data to program to register
+ *
+ * Disable the eSRAM page - with flush. Note the architecture will block access
+ * to the overlayed region until the flush has completed => irqs may be switched
+ * on during this operation.
+ */
+static void intel_cln_esram_page_flush_disable(struct esram_page *epage)
+{
+
+
+ /* Do flush */
+ sb_write(SB_ID_ESRAM, ESRAM_PAGE_WRITE, epage->id,
+ ESRAM_PAGE_FLUSH | ESRAM_PAGE_DISABLE, 1);
+
+ intel_cln_esram_page_disable_sync(epage);
+}
+
+#if 0
+/**
+ * intel_cln_esram_flush_disable_all
+ *
+ * Flushes and disables all enabled eSRAM pages
+ */
+static void intel_cln_esram_page_flush_disable_all(void)
+{
+ struct esram_page * epage = NULL;
+
+ spin_lock(&esram_dev.slock);
+ list_for_each_entry(epage, &esram_dev.page_used, list){
+ intel_cln_esram_page_flush_disable(epage);
+ }
+ spin_unlock(&esram_dev.slock);
+}
+#endif
+
+/**
+ * intel_cln_esram_page_populate_atomic
+ *
+ * @param epage: Pointer to eSRAM page desciptor.
+ * @return 0 placeholder, later versions may return error
+ *
+ * Function takes the mappings given in epage and uses the values to populate
+ * an eSRAM page. The copy/enable/copy routine must be done atomically, since we
+ * may be doing a memcpy() of an ISR for example.
+ * For this reason we wrapper this entire call into a callback provided by
+ * side-band, which does a spin_lock_irqsave calls this function and then does
+ * a spin_lock_irqrestore - thus guaranteeing atomicity of the below code and
+ * respect for the locking strategy of the side-band driver
+ */
+static int intel_cln_esram_page_populate_atomic(struct esram_page * epage)
+{
+ unsigned long crz;
+
+ /* Copy away */
+ memcpy(&esram_dev.cbuf, (void*)epage->vaddr, ESRAM_PAGE_SIZE);
+
+ /* If CR0.WP is true - flip it HSD # 4930660 */
+ crz = read_cr0();
+ if (crz & X86_CR0_WP){
+ write_cr0(crz & (~X86_CR0_WP));
+ }
+
+ /* Disable NMI */
+ outb(0x80, 0x70);
+
+ /* Enable page mapping */
+ intel_cln_esram_page_enable(epage, 0);
+
+ /* Copy back - populating memory overlay */
+ memcpy((void*)epage->vaddr, &esram_dev.cbuf, ESRAM_PAGE_SIZE);
+
+ /* Re-enable NMI */
+ outb(0x00, 0x70);
+
+ /* Restore CR0.WP if appropriate HSD # 4930660 */
+ if (crz & X86_CR0_WP){
+ write_cr0(crz);
+ }
+ return 0;
+}
+
+/**
+ * intel_cln_esram_page_populate
+ *
+ * @param epage: Pointer to eSRAM page desciptor.
+ * @return 0 on success < 0 on failure
+ *
+ * Populates the page. set_memory_rw/set_memory_ro require local irqs enabled.
+ * intel_cln_esram_page_populate_atomic - needs irqs switched off since memory
+ * can be inconsistent during the populate operation. Depopulate operations are
+ * architecturally guaranteed
+ */
+static int intel_cln_esram_page_populate(struct esram_page * epage)
+{
+ int flip_rw = 0, level = 0, ret = 0;
+ pte_t * pte = epage != NULL ? lookup_address(epage->vaddr, &level):NULL;
+
+ if(unlikely(pte == NULL)){
+ return -EINVAL;
+ }
+
+ /* Determine if we need to set writable */
+ flip_rw = !(pte_write(*pte));
+
+ /* Ensure memory is r/w - do so before spin_lock_irqsave */
+ if(flip_rw){
+ ret = set_memory_rw(epage->vaddr, 1);
+ if (ret != 0){
+ pr_err("%s error during set_memory_rw = %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ /* Force ECC update @ disable only */
+ intel_cln_esram_page_enable(epage, 1);
+ intel_cln_esram_page_disable(epage);
+
+ /* Enable and populate eSRAM page using callback in sb with irqs off */
+ ret |= intel_cln_sb_runfn_lock(
+ (int (*)(void*))intel_cln_esram_page_populate_atomic,(void*)epage);
+
+ /* If we set memory writable - restore previous state */
+ if(flip_rw){
+ ret |= set_memory_ro(epage->vaddr, 1);
+ if (ret != 0){
+ pr_err("%s error during set_memory_ro = %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+/**
+ * intel_cln_esram_page_addref
+ *
+ * @param epage: eSRAM page descriptor
+ * @param name: Name of reference to add
+ * @return zero on success negative on error
+ *
+ */
+static int intel_cln_esram_page_addref(struct esram_page * epage, char * name)
+{
+ struct esram_refname * refname = NULL;
+ if(unlikely(epage == NULL || name == NULL)){
+ return -EINVAL;
+ }
+
+ refname = kzalloc(sizeof(struct esram_refname), GFP_KERNEL);
+ if(unlikely(refname == NULL)){
+ return -ENOMEM;
+ }
+
+ /* Add to list */
+ strncpy(refname->name, name, sizeof(refname->name));
+ list_add(&refname->list, &epage->name_list);
+
+ /* Bump reference count */
+ epage->refcount++;
+ return 0;
+}
+
+
+/**
+ * __intel_cln_esram_map_page
+ *
+ * @param page: Page to map
+ * @param name: Name of the mapping
+ * @return 0 success < 0 failure
+ *
+ * Overlay a vritual address rangne eeds to be aligned to a 4k address.
+ * Since multiple items can live in a 4k range, it is possible when calling
+ * into map_page() that a previous mapping will have already covered some or all
+ * of the mapping we want. This is not an error case, if the map function finds
+ * it is being asked to map a 4k range already mapped it returns 0, to indicate
+ * the mapping has suceeded i.e. it's already been mapped. This is logical if
+ * you think about it. In contrast being asked to unmap a region not mapped is
+ * clearly an error...
+ *
+ */
+static int __intel_cln_esram_map_page(u32 vaddr, char * name)
+{
+ int ret = 0;
+ struct esram_page * epage = NULL;
+ struct esram_refname * refname = NULL;
+
+ if(unlikely(name == NULL)){
+ return -EINVAL;
+ }
+
+ if(unlikely(esram_dev.page_free_ct == 0)){
+ return -ENOMEM;
+ }
+
+ /* Verify if we have already mapped */
+ list_for_each_entry(epage, &esram_dev.page_used, list){
+ if(epage->vaddr == vaddr){
+
+ /* Page already mapped */
+ list_for_each_entry(refname, &epage->name_list, list){
+ if(strcmp(refname->name, name)==0){
+ /* Page mapped at this name */
+ return -EINVAL;
+ }
+ }
+ /* New symbol in previous mapping */
+ return intel_cln_esram_page_addref(epage, name);
+ }
+ }
+
+ /* Enumerate eSRAM page structure */
+ epage = list_first_entry(&esram_dev.page_free, struct esram_page, list);
+ epage->phys_addr = virt_to_phys((void*)vaddr);
+ epage->vaddr = vaddr;
+ ret = intel_cln_esram_page_addref(epage, name);
+ if(unlikely(ret < 0)){
+ return ret;
+ }
+
+ /* Populate page */
+ ret = intel_cln_esram_page_populate(epage);
+
+ /* Move to used list */
+ list_move(&epage->list, &esram_dev.page_used);
+ esram_dev.page_free_ct--;
+
+ return ret;
+}
+
+/**
+ * __intel_cln_esram_unmap_page
+ *
+ * @param page: Page to unmap
+ * @param name: Name of the mapping
+ * @return 0 success < 0 failure
+ *
+ * Unmap a previously mapped virutal address range.
+ * Must be 4k aligned
+ *
+ */
+static int __intel_cln_esram_unmap_page(u32 vaddr, char * name)
+{
+ u8 found = 0;
+ struct esram_page * epage = NULL;
+ struct esram_refname * refname = NULL;
+
+ /* Find physical address */
+ list_for_each_entry(epage, &esram_dev.page_used, list){
+ if(epage->vaddr == vaddr){
+ found = 1;
+ break;
+ }
+ }
+
+ /* Bail out on error */
+ if(found == 0){
+ pr_err("0x%08x not mapped\n", vaddr);
+ return -EINVAL;
+ }
+
+ /* Determine reference to delete */
+ found = 0;
+ list_for_each_entry(refname, &epage->name_list, list){
+ if(strcmp(refname->name,name)==0){
+ found = 1;
+ break;
+ }
+ }
+ if(unlikely(found == 0)){
+ pr_err("No mapping %s!\n", name);
+ return -EINVAL;
+ }
+
+ /* Remove entry decrement reference count */
+ list_del(&refname->list);
+ kfree(refname);
+ if(--epage->refcount > 0){
+ return 0;
+ }
+
+ /* Flush and disable page */
+ intel_cln_esram_page_flush_disable(epage);
+
+ /* Move to free list tail - scrub entries come from head */
+ list_move_tail(&epage->list, &esram_dev.page_free);
+ esram_dev.page_free_ct++;
+
+ return 0;
+}
+
+/**
+ *
+ * __intel_cln_esram_page_op
+ *
+ * @param vaddr: Virtual address of symbol
+ * @param size: Size/length of symbol
+ * @param name: Name of mapping
+ * @param map: Boolean indicates whether to map or unmap the page
+ * @return 0 success < 0 failure
+ *
+ * This function maps/unmaps a pages/pages given at the given vaddr. If
+ * the extent of the symbol @ vaddr crosses a page boundary, then we map
+ * multiple pages. Other stuff inside the page, gets a performance boost 'for
+ * free'. Any other data in the page that crosses the physical page boundary
+ * will be partially mapped.
+ */
+static int __intel_cln_esram_page_op(u32 vaddr, u32 size, char *name, u8 map)
+{
+ unsigned long offset = 0, page_offset = 0;
+ u32 pages = size/ESRAM_PAGE_SIZE + ((size%ESRAM_PAGE_SIZE) ? 1 : 0);
+ int ret = 0;
+
+ /* Compare required pages to available pages */
+ if(map == ESRAM_MAP_OP){
+ if(pages > esram_dev.page_free_ct)
+ return -ENOMEM;
+ }else{
+ if(pages > esram_dev.page_count - esram_dev.page_free_ct)
+ return -ENOMEM;
+ }
+
+ /* Align to 4k and iterate the mappings */
+ vaddr = vaddr&ESRAM_PAGE_MASK;
+ while(size > 0){
+
+ /* Map the page */
+ spin_lock(&esram_dev.slock);
+ if(map == ESRAM_MAP_OP){
+ ret = __intel_cln_esram_map_page(vaddr, name);
+
+ }else{
+ ret = __intel_cln_esram_unmap_page(vaddr, name);
+ }
+ spin_unlock(&esram_dev.slock);
+ if(unlikely(ret != 0)){
+ break;
+ }
+
+ /* Calc appropriate offsets */
+ page_offset = offset_in_page(vaddr);
+ if(page_offset + size > ESRAM_PAGE_SIZE){
+
+ offset = ESRAM_PAGE_SIZE - page_offset;
+ size -= offset;
+ vaddr += ESRAM_PAGE_SIZE;
+
+ }else{
+ size = 0;
+ }
+ }
+
+ return ret;
+}
+
+/******************************************************************************
+ * eSRAM API
+ ******************************************************************************/
+
+/**
+ * intel_cln_esram_map_range
+ *
+ * @param vaddr: Virtual address to start mapping (must be 4k aligned)
+ * @param size: Size to map from
+ * @param mapname: Mapping name
+ * @return 0 success < 0 failure
+ *
+ * Map 4k increments at given address to eSRAM.
+ */
+int intel_cln_esram_map_range(void * vaddr, u32 size, char * mapname)
+{
+ if(size == 0 || mapname == NULL || vaddr == NULL){
+ return -EINVAL;
+ }
+ return __intel_cln_esram_page_op((u32)vaddr, size, mapname, ESRAM_MAP_OP);
+}
+EXPORT_SYMBOL(intel_cln_esram_map_range);
+
+/**
+ * intel_cln_esram_map_symbol
+ *
+ * @param vaddr: Virtual address of the symbol
+ * @return 0 success < 0 failure
+ *
+ * Maps a series of 4k chunks starting at vaddr&0xFFFFF000. vaddr shall be a
+ * kernel text section symbol (kernel or loaded module)
+ *
+ * We get the size of the symbol from kallsyms. We guarantee to map the entire
+ * size of the symbol - plus whatever padding is necessary to get alignment to
+ * eSRAM_PAGE_SIZE
+ * Other stuff inside the mapped pages will get a performance boost 'for free'.
+ * If this free boost is not what you want then
+ *
+ * 1. Align to 4k
+ * 2. Pad to 4k
+ * 3. Call intel_cln_esram_map_range()
+ */
+int intel_cln_esram_map_symbol(void * vaddr)
+{
+ long unsigned int size = 0, offset = 0;
+ char symname[KSYM_SYMBOL_LEN];
+
+ kallsyms_lookup_size_offset((long unsigned int)vaddr, &size, &offset);
+ if(size == 0){
+ return -EINVAL;
+ }
+ sprint_symbol(symname, (u32)vaddr);
+
+ return __intel_cln_esram_page_op((u32)vaddr, size, symname, 1);
+}
+EXPORT_SYMBOL(intel_cln_esram_map_symbol);
+
+/******************************************************************************
+ * Module/PowerManagement hooks
+ ******************************************************************************/
+
+/**
+ * intel_cln_esram_suspend
+ *
+ * @param pdev: Platform device structure (unused)
+ * @param pm: Power managment descriptor
+ * @return 0 success < 0 failure
+ *
+ * For each enabled page - flush to DRAM and disable eSRAM page.
+ * For each 4k region the architecture guarantees atomicity of flush/disable.
+ * Hence any memory transactions to the affected region will stall until
+ * flush/disable completes - hence interrupts are left on.
+ */
+static int intel_cln_esram_suspend(struct device * pdev)
+{
+ /* Flush and disable of eSRAM pages is carried out automatically */
+ return 0;
+}
+
+/**
+ * intel_cln_esram_resume
+ *
+ * @param pm: Power management descriptor
+ * @return 0 success < 0 failure
+ *
+ * Runs after resume_noirq. Switches pages back to ro, if appropriate. We do
+ * this here since interrupts will be on, as required by the function
+ * set_memory_ro. If it were possible to set memory ro in resume_noirq we would
+ * do it there instead
+ */
+static int intel_cln_esram_resume(struct device * pdev)
+{
+ struct esram_page * epage = NULL;
+ int ret = 0;
+
+ list_for_each_entry(epage, &esram_dev.page_used, list){
+ ret |= intel_cln_esram_page_populate(epage);
+ }
+
+ return ret;
+}
+
+
+/**
+ * intel_cln_esram_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ *
+ * This driver manages eSRAM on a per-page basis. Therefore if we find block
+ * mode is enabled, or any global, block-level or page-level locks are in place
+ * at module initialisation time - we bail out.
+ */
+static int intel_cln_esram_probe(struct platform_device * pdev)
+{
+ int ret = 0;
+ u32 block = 0, ctrl = 0, i = 0, pgstat = 0;
+
+ memset(&esram_dev, 0x00, sizeof(esram_dev));
+ INIT_LIST_HEAD(&esram_dev.page_used);
+ INIT_LIST_HEAD(&esram_dev.page_free);
+ spin_lock_init(&esram_dev.slock);
+ esram_dev.page_free_ct = 0;
+
+ /* Ensure block mode disabled */
+ block = ESRAM_PGBLOCK_DISABLE;
+ sb_write(SB_ID_ESRAM, ESRAM_CTRL_WRITE, ESRAM_PGBLOCK_REG, block, 1);
+
+ /* Get state */
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_CTRL_REG, &ctrl, 1);
+ sb_read(SB_ID_ESRAM, ESRAM_CTRL_READ, ESRAM_PGBLOCK_REG, &block, 1);
+
+ /* Verify state is good to go */
+ if (ctrl & ESRAM_CTRL_GLOBAL_LOCK){
+ pr_err ("eSRAM global lock @ 0x%08x\n", ctrl);
+ return -ENODEV;
+ }
+
+ if (block & (ESRAM_PGBLOCK_LOCK | ESRAM_PGBLOCK_ENABLE)){
+ pr_err ("eSRAM lock @ 0x%08x\n", block);
+ return -ENODEV;
+ }
+ pr_info("eSRAM CTRL 0x%08x block 0x%08x\n", ctrl, block);
+
+ /* Calculate # of pages silicon supports */
+ esram_dev.page_count = ESRAM_CTRL_SIZE(ctrl) + 1;
+ esram_dev.page_free_ct = esram_dev.page_count;
+ pr_info("eSRAM pages %d\n", esram_dev.page_free_ct);
+
+ if(esram_dev.page_free_ct <= 1){
+ pr_err("Too few pages reported by eSRAM sub-system\n");
+ return -ENOMEM;
+ }
+
+ /* Allocate an appropriate number of pages */
+ esram_dev.pages = kzalloc(esram_dev.page_count *
+ sizeof(struct esram_page), GFP_KERNEL);
+ if (esram_dev.pages == NULL){
+ return -ENOMEM;
+ }
+
+ /* Initialise list of free pages, explicitely disable as we go */
+ for(i = 0; i < esram_dev.page_count; i++){
+ INIT_LIST_HEAD(&esram_dev.pages[i].name_list);
+ esram_dev.pages[i].id = i;
+
+ /* Read & verify page state */
+ sb_read(SB_ID_ESRAM, ESRAM_PAGE_READ, i, &pgstat, 1);
+ if(pgstat & (ESRAM_PAGE_BUSY | ESRAM_PAGE_LOCK)){
+ pr_err("eSRAM page %d state 0x%08x err\n", i, pgstat);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ list_add(&esram_dev.pages[i].list, &esram_dev.page_free);
+ }
+
+ return intel_cln_esram_proc_add();
+err:
+ kfree(esram_dev.pages);
+ return ret;
+}
+
+/**
+ * intel_cln_esram_remove
+ *
+ * @return 0 success < 0 failure
+ *
+ * Removes a platform device
+ */
+static int intel_cln_esram_remove(struct platform_device * pdev)
+{
+ intel_cln_esram_proc_remove();
+ kfree(esram_dev.pages);
+
+ return 0;
+}
+
+/*
+ * Power management operations
+ */
+static const struct dev_pm_ops intel_cln_esram_pm_ops = {
+ .suspend = intel_cln_esram_suspend,
+ .resume = intel_cln_esram_resume,
+};
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_esram_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &intel_cln_esram_pm_ops,
+ },
+ .probe = intel_cln_esram_probe,
+ .remove = intel_cln_esram_remove,
+};
+
+module_platform_driver(intel_cln_esram_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Clanton eSRAM overlay/ECC-scrub driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
diff --git a/arch/x86/platform/cln/intel_cln_esram.h b/arch/x86/platform/cln/intel_cln_esram.h
new file mode 100644
index 0000000..af6156a
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_esram.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton eSRAM overlay driver
+ *
+ * eSRAM is an on-chip fast access SRAM.
+ *
+ * This driver provides the ability to map a kallsyms derived symbol of
+ * arbitrary length or a struct page entitiy.
+ * A proc interface is provided to allow map/unmap of kernel structures, without
+ * having to use the API from your code directly.
+ *
+ * Example:
+ * echo ehci_irq on > /proc/driver/esram/map
+ * echo ehci_irq off > /proc/driver/esram/map
+ *
+ * An API is provided to allow for mapping of a) kernel symbols or b) pages.
+ * eSRAM requires 4k physically aligned addresses to work - so a struct page
+ * fits neatly into this.
+ *
+ * To populte eSRAM we must copy data to a temporary buffer, overlay and
+ * then copy data back to the eSRAM region.
+ *
+ * When entering S3 - we must save eSRAM state to DRAM, and similarly on restore
+ * to S0 we must repopulate eSRAM
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>
+ */
+#ifndef __INTEL_CLN_ESRAM_H__
+#define __INTEL_CLN_ESRAM_H__
+
+#include <linux/module.h>
+
+/* Basic size of an eSRAM page */
+#define INTEL_CLN_ESRAM_PAGE_SIZE (0x1000)
+#define INTEL_CLN_ESRAM_PAGE_COUNT (0x80)
+/**
+ * intel_cln_esram_map_range
+ *
+ * @param vaddr: Virtual address to start mapping (must be 4k aligned)
+ * @param size: Size to map from
+ * @param mapname: Mapping name
+ * @return 0 success < 0 failure
+ *
+ * Map 4k increments at given address to eSRAM.
+ */
+int intel_cln_esram_map_range(void * vaddr, u32 size, char * mapname);
+
+/**
+ * intel_cln_esram_unmap_range
+ *
+ * @param vaddr: The virtual address to unmap
+ * @return 0 success < 0 failure
+ *
+ * Logical corollary of esram_map_page
+ */
+int intel_cln_esram_unmap_range(void * vaddr, u32 size, char * mapname);
+
+/**
+ * intel_cln_esram_map_symbol
+ *
+ * @param vaddr: Virtual address of the symbol
+ * @return 0 success < 0 failure
+ *
+ * Maps a series of 4k chunks starting at vaddr&0xFFFFF000. vaddr shall be a
+ * kernel text section symbol (kernel or loaded module)
+ *
+ * We get the size of the symbol from kallsyms. We guarantee to map the entire
+ * size of the symbol - plus whatever padding is necessary to get alignment to
+ * eSRAM_PAGE_SIZE
+ * Other stuff inside the mapped pages will get a performance boost 'for free'.
+ * If this free boost is not what you want then
+ * 1. Align to 4k
+ * 2. Pad to 4k
+ * 3. Call intel_cln_esram_map_range()
+ */
+int intel_cln_esram_map_symbol(void * vaddr);
+
+/**
+ * intel_cln_esram_unmap_symbol
+ *
+ * @param vaddr: Virtual address of the symbol
+ * @return 0 success < 0 failure
+ *
+ * Logical corollary to intel_cln_esram_map_symbol
+ * Undoes any mapping of pages starting at sym for sym's size
+ */
+int intel_cln_esram_unmap_symbol(void * vaddr);
+
+#endif /* __INTEL_CLN_ESRAM_H__ */
diff --git a/arch/x86/platform/cln/intel_cln_esram_test.c b/arch/x86/platform/cln/intel_cln_esram_test.c
new file mode 100644
index 0000000..3d0573d
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_esram_test.c
@@ -0,0 +1,602 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/**
+ * intel_cln_esram_test.c
+ *
+ * Simple test module to provide test cases for ITS integration
+ *
+ */
+#include <linux/cdev.h>
+#include <linux/crc32.h>
+#include <linux/crc32c.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+
+#include "intel_cln_esram.h"
+#include "intel_cln_esram_test.h"
+
+#define DRIVER_NAME "intel_cln_esram_test"
+
+/**
+ * struct intel_cln_esram_dev
+ *
+ * Structre to represent module state/data/etc
+ */
+struct intel_cln_esram_test_dev{
+ unsigned int opened;
+ struct platform_device *pldev; /* Platform device */
+ struct cdev cdev;
+ struct mutex open_lock;
+ char * pdata;
+ u32 size;
+};
+
+static struct intel_cln_esram_test_dev esram_test_dev;
+static struct class *esram_test_class;
+static DEFINE_MUTEX(esram_test_mutex);
+static int esram_test_major;
+static char * name = "testmap";
+
+/******************************************************************************
+ * eSRAM BIST
+ ******************************************************************************/
+
+static int crc_cache = 0;
+
+unsigned long long tsc_delta(unsigned long long first, unsigned long long end)
+{
+ if (first < end)
+ return end - first;
+ else
+ return (ULLONG_MAX - first) + end;
+}
+
+
+/**
+ * intel_cln_crctest
+ *
+ * Do a CRC32 of the specified region. Return the time taken in jiffies
+ */
+static unsigned long long intel_cln_crctest(char * pdata, u32 crcsize)
+{
+ unsigned long long j1 = 0, j2 = 0;
+
+ rdtscll(j1);
+
+ /* Flush LMT cache to introduce cache miss to our test */
+ __asm__ __volatile__("wbinvd\n");
+ crc32(0, pdata, crcsize);
+
+ rdtscll(j2);
+
+ return tsc_delta(j1, j2);
+}
+
+#ifdef __DEBUG__
+#define bist_err(x){\
+ pr_err("eSRAM bist err line %d errno %d\n", (__LINE__-2), x);\
+ return x;\
+}
+#else
+#define bist_err(x){\
+ return x;\
+}
+#endif
+/**
+ * intel_cln_esram_perpage_overlay
+ *
+ * Maps to integration test spec ID CLN.F.SW.APP.eSRAM.0
+ */
+int intel_cln_esram_test_perpage_overlay(void)
+{
+
+ int ret = 0;
+ u32 idx = 0, size = INTEL_CLN_ESRAM_PAGE_SIZE;
+
+ /* Set a known state */
+ for(idx = 0; idx < size; idx += sizeof(u32)){
+ *((u32*)&esram_test_dev.pdata[idx]) = idx;
+ }
+
+
+ /* Basic test of full range of memory */
+ ret = intel_cln_esram_map_range(esram_test_dev.pdata, size, name);
+ if(ret){
+ bist_err(ret);
+ }
+ for(idx = 0; idx < size; idx += sizeof(u32)){
+ if(*((u32*)&esram_test_dev.pdata[idx]) != idx){
+ pr_err("Entry %d is 0x%08x require 0x%08x",
+ idx, esram_test_dev.pdata[idx], idx);
+ bist_err(-EIO);
+ }
+ }
+
+#if 0
+ ret = intel_cln_esram_unmap_range(esram_test_dev.pdata, size, name);
+ if(ret){
+ bist_err(ret);
+ }
+#endif
+ return 0;
+}
+
+/**
+ * intel_cln_esram_test_pageref_count
+ *
+ * Ensure page reference couting works as expected
+ */
+int intel_cln_esram_test_pagref_count(void)
+{
+ u32 size = INTEL_CLN_ESRAM_PAGE_SIZE;
+ int ret = 0;
+
+ return 0;
+ /* Map a page */
+ ret = intel_cln_esram_map_range(esram_test_dev.pdata, size, name);
+ if(ret){
+ bist_err(ret);
+ }
+
+ /* Map a second time - and verify mapping fails */
+ ret = intel_cln_esram_map_range(esram_test_dev.pdata, size, name);
+ if(ret == 0){
+ bist_err(-EFAULT);
+ }
+
+#if 0
+ /* Unmap - OK */
+ ret = intel_cln_esram_unmap_range(esram_test_dev.pdata, size, name);
+ if(ret){
+ bist_err(ret);
+ }
+
+ /* Verify second unmap operation fails */
+ ret = intel_cln_esram_unmap_range(esram_test_dev.pdata, size, name);
+ if(ret == 0){
+ bist_err(-EFAULT);
+ }
+#endif
+ return 0;
+}
+
+extern uint32_t get_crc32table_le(void);
+
+/**
+ * intel_cln_esram_test_contig_perfmetric
+ *
+ * Do a CRC16 for a contigous area of memory
+ * Map contigous area and get a CRC16
+ *
+ * Ensure overlayed data takes less time than regular unoverlayed DRAM
+ */
+int intel_cln_esram_test_contig_perfmetric(void)
+{
+ u32 crcsize = 0x60000;
+ unsigned long long crc32_fullmap = 0, crc32_fullunmap = 0;
+ uint32_t crc32table_le = kallsyms_lookup_name("crc32table_le");
+ int ret = 0;
+
+ if (crc32table_le == 0){
+ pr_err("%s unable to fine symbol crc32table_le\n", __func__);
+ return -ENODEV;
+ }
+
+ /* Get raw data metric */
+ crc_cache = 1;
+ crc32_fullunmap = intel_cln_crctest(esram_test_dev.pdata, crcsize);
+
+ /* Map CRC16 symbol (algorithm) + code (data) */
+ ret = intel_cln_esram_map_symbol(crc32_le);
+ if(ret){
+ bist_err(ret);
+ }
+ ret = intel_cln_esram_map_symbol((void*)crc32table_le);
+ if(ret){
+ bist_err(ret);
+ }
+
+ /* Map test data */
+ ret = intel_cln_esram_map_range(esram_test_dev.pdata, crcsize, name);
+ if(ret){
+ bist_err(ret);
+ }
+
+ /* Get metric */
+ crc_cache = 1;
+ crc32_fullmap = intel_cln_crctest(esram_test_dev.pdata, crcsize);
+#if 0
+ /* Tidy up */
+ ret = intel_cln_esram_unmap_range(esram_test_dev.pdata, crcsize, name);
+ if(ret){
+ bist_err(ret);
+ }
+ ret = intel_cln_esram_unmap_range(((void*)crc32_table),
+ sizeof(crc32_table), name);
+ if(ret){
+ bist_err(ret);
+ }
+ ret = intel_cln_esram_unmap_symbol(crc32);
+ if(ret){
+ bist_err(ret);
+ }
+#endif
+ pr_info("%s did crctest - mapped - in %llu ticks\n", __func__, crc32_fullmap);
+ pr_info("%s mapped count %llu unmapped %llu\n",
+ __func__, crc32_fullmap, crc32_fullunmap);
+ return crc32_fullmap < crc32_fullunmap;
+}
+
+/**
+ * intel_cln_esram_test_kernel_codemap
+ *
+ * Maps some kernel code - a data section and then calls the code contained
+ * therein. Proves out the running overlayed eSRAM works
+ */
+int intel_cln_esram_test_kernel_codemap(void)
+{
+#if 0
+ int ret = intel_cln_esram_map_symbol(msleep);
+ if(ret){
+ printk(KERN_ERR "%s map symbol msleep fail\n", __FUNCTION__);
+ bist_err(ret);
+ }
+
+ /* run the mapped code */
+ msleep(1);
+
+ /* unmap */
+ ret = intel_cln_esram_unmap_symbol(msleep);
+ if(ret){
+ printk(KERN_ERR "%s unmap symbol msleep fail\n", __FUNCTION__);
+ bist_err(ret);
+ }
+#endif
+ return 0;
+}
+
+/**
+ * intel_cln_esram_test_kernel_datamap
+ *
+ * Tests mapping/unmapping of a kernel data structure
+ */
+int intel_cln_esram_test_kernel_datamap(void)
+{
+#if 0
+ unsigned long jtag = 0;
+ unsigned long ctrl = 0;
+
+ /* Map the interrupt descriptor table */
+ int ret = intel_cln_esram_map_range(idt_table, INTEL_CLN_ESRAM_PAGE_SIZE, name);
+ if(ret){
+ bist_err(ret);
+ }
+
+ jtag = jiffies;
+ /* Wait for jiffies to tick or timeout to occur (failure) */
+ while(jtag == jiffies){
+ ctrl++;
+ }
+
+ /* unmap */
+ ret = intel_cln_esram_unmap_range(idt_table, INTEL_CLN_ESRAM_PAGE_SIZE, name);
+ if(ret){
+ bist_err(ret);
+ }
+#endif
+ return 0;
+}
+
+/**
+ * intel_cln_esram_test_sub_unsub
+ *
+ * Subscribe and unsubscribe 100% of available eSRAM
+ */
+int intel_cln_esram_test_sub_unsub(void)
+{
+ int ret = 0;
+ u32 idx = 0, size = INTEL_CLN_ESRAM_PAGE_SIZE * INTEL_CLN_ESRAM_PAGE_COUNT;
+
+ /* Set a known state */
+ for(idx = 0; idx < size; idx += sizeof(u32)){
+ *((u32*)&esram_test_dev.pdata[idx]) = idx;
+ }
+
+ /* Basic test of full range of memory */
+ ret = intel_cln_esram_map_range(esram_test_dev.pdata, size, name);
+ if(ret){
+ bist_err(ret);
+ }
+ for(idx = 0; idx < size; idx += sizeof(u32)){
+ if(*((u32*)&esram_test_dev.pdata[idx]) != idx){
+ pr_err("Entry %d is 0x%08x require 0x%08x",
+ idx, esram_test_dev.pdata[idx], idx);
+ bist_err(-EIO);
+ }
+ }
+#if 0
+ ret = intel_cln_esram_unmap_range(esram_test_dev.pdata, size, name);
+ if(ret){
+ bist_err(ret);
+ }
+#endif
+ return 0;
+}
+
+/**
+ * intel_cln_esram_test_over_sub
+ *
+ * Test oversubscription of eSRAM
+ */
+int intel_cln_esram_test_over_sub(void)
+{
+ int ret = 0;
+ u32 size = INTEL_CLN_ESRAM_PAGE_SIZE * (INTEL_CLN_ESRAM_PAGE_COUNT + 1);
+
+ /* Over subscribe should fail */
+ ret = intel_cln_esram_map_range(esram_test_dev.pdata, size, name);
+ if(ret == 0){
+ //intel_cln_esram_unmap_range(esram_test_dev.pdata, size, name);
+ bist_err(-EFAULT);
+ }
+ return 0;
+}
+
+/*
+ * File ops
+ */
+static long esram_test_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -EINVAL;
+
+ cmd -= CLN_ESRAM_IOCTL_BASE;
+ switch (cmd) {
+ case CLN_F_SW_APP_ESRAM_0:
+ /* Per page overlay */
+ ret = intel_cln_esram_test_perpage_overlay();
+ break;
+
+ case CLN_F_SW_APP_ESRAM_1:
+ /* Verify page reference counting */
+ ret = intel_cln_esram_test_pagref_count();
+ break;
+
+ case CLN_F_SW_APP_ESRAM_2:
+ /* Performance metric or overlay contig RAM */
+ ret = intel_cln_esram_test_contig_perfmetric();
+ if (ret == 1)
+ ret = 0;
+ break;
+
+ case CLN_F_SW_APP_ESRAM_3:
+ /* Verify mapping of kernel code section */
+ /* Covered by test #2 */
+ ret = 0; //intel_cln_esram_test_kernel_codemap();
+ break;
+
+ case CLN_F_SW_APP_ESRAM_4:
+ /* Verify mapping of kernel data section (IDT) */
+ /* Covered by test #2 */
+ ret = 0; //intel_cln_esram_test_kernel_datamap();
+ break;
+
+ case CLN_F_SW_APP_ESRAM_5:
+ /* Complete subscribe/unsubscribe eSRAM */
+ ret = intel_cln_esram_test_sub_unsub();
+ break;
+
+ case CLN_F_SW_APP_ESRAM_6:
+ /* Over subscribe eSRAM */
+ ret = intel_cln_esram_test_over_sub();
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int esram_test_open(struct inode *inode, struct file *file)
+{
+ mutex_lock(&esram_test_mutex);
+ nonseekable_open(inode, file);
+
+ if (mutex_lock_interruptible(&esram_test_dev.open_lock)) {
+ mutex_unlock(&esram_test_mutex);
+ return -ERESTARTSYS;
+ }
+
+ if (esram_test_dev.opened) {
+ mutex_unlock(&esram_test_dev.open_lock);
+ mutex_unlock(&esram_test_mutex);
+ return -EINVAL;
+ }
+
+ esram_test_dev.opened++;
+ mutex_unlock(&esram_test_dev.open_lock);
+ mutex_unlock(&esram_test_mutex);
+
+ return 0;
+}
+
+static int esram_test_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&esram_test_dev.open_lock);
+ esram_test_dev.opened = 0;
+ mutex_unlock(&esram_test_dev.open_lock);
+
+ return 0;
+}
+
+static const struct file_operations esram_test_file_ops = {
+ .open = esram_test_open,
+ .release = esram_test_release,
+ .unlocked_ioctl = esram_test_ioctl,
+ .llseek = no_llseek,
+};
+
+
+/**
+ * intel_cln_esram_test_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ *
+ * This driver manages eSRAM on a per-page basis. Therefore if we find block
+ * mode is enabled, or any global, block-level or page-level locks are in place
+ * at module initialisation time - we bail out.
+ */
+static int intel_cln_esram_test_probe(struct platform_device * pdev)
+{
+ int retval = 0;
+ unsigned int minor = 0;
+
+ esram_test_dev.size = INTEL_CLN_ESRAM_PAGE_COUNT * INTEL_CLN_ESRAM_PAGE_SIZE;
+
+ /* Get memory */
+ esram_test_dev.pdata = kzalloc(esram_test_dev.size, GFP_KERNEL);
+ if(unlikely(esram_test_dev.pdata == NULL)){
+ pr_err("Can't allocate %d bytes\n", esram_test_dev.size);
+ return -ENOMEM;
+ }
+
+ mutex_init(&esram_test_dev.open_lock);
+ cdev_init(&esram_test_dev.cdev, &esram_test_file_ops);
+ esram_test_dev.cdev.owner = THIS_MODULE;
+
+ retval = cdev_add(&esram_test_dev.cdev, MKDEV(esram_test_major, minor), 1);
+ if (retval) {
+ printk(KERN_ERR "chardev registration failed\n");
+ kfree(esram_test_dev.pdata);
+ return -EINVAL;
+ }
+ if (IS_ERR(device_create(esram_test_class, NULL,
+ MKDEV(esram_test_major, minor), NULL,
+ "esramtest%u", minor))){
+ dev_err(&pdev->dev, "can't create device\n");
+ kfree(esram_test_dev.pdata);
+ return -EINVAL;
+ }
+ printk(KERN_INFO "%s/%s/%s complete OK !!\n", __FUNCTION__, __DATE__,__TIME__);
+ return 0;
+
+}
+
+/**
+ * intel_cln_esram_remove
+ *
+ * @return 0 success < 0 failure
+ *
+ * Removes a platform device
+ */
+static int intel_cln_esram_test_remove(struct platform_device * pdev)
+{
+ unsigned int minor = MINOR(esram_test_dev.cdev.dev);
+
+ device_destroy(esram_test_class, MKDEV(esram_test_major, minor));
+ cdev_del(&esram_test_dev.cdev);
+ kfree(esram_test_dev.pdata);
+
+ return 0;
+}
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_esram_test_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = intel_cln_esram_test_remove,
+};
+
+/**
+ * intel_cln_esram_init
+ *
+ * @return 0 success < 0 failure
+ *
+ * Module entry point
+ */
+static int __init intel_cln_esram_test_init(void)
+{
+ int retval = 0;
+ dev_t dev;
+
+ esram_test_class = class_create(THIS_MODULE,"cln_esram_test");
+ if (IS_ERR(esram_test_class)) {
+ retval = PTR_ERR(esram_test_class);
+ printk(KERN_ERR "esram_test: can't register earam_test class\n");
+ goto err;
+ }
+
+ retval = alloc_chrdev_region(&dev, 0, 1, "esram_test");
+ if (retval) {
+ printk(KERN_ERR "earam_test: can't register character device\n");
+ goto err_class;
+ }
+ esram_test_major = MAJOR(dev);
+
+ memset(&esram_test_dev, 0x00, sizeof(esram_test_dev));
+ esram_test_dev.pldev = platform_create_bundle(
+ &intel_cln_esram_test_driver, intel_cln_esram_test_probe, NULL, 0, NULL, 0);
+
+ if(IS_ERR(esram_test_dev.pldev)){
+ printk(KERN_ERR "platform_create_bundle fail!\n");
+ retval = PTR_ERR(esram_test_dev.pldev);
+ goto err_class;
+ }
+
+ return 0;
+
+err_class:
+ class_destroy(esram_test_class);
+err:
+ return retval;
+}
+
+/**
+ * intel_cln_esram_exit
+ *
+ * Module exit
+ */
+static void __exit intel_cln_esram_test_exit(void)
+{
+ platform_device_unregister(esram_test_dev.pldev);
+ platform_driver_unregister(&intel_cln_esram_test_driver);
+}
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Clanton eSRAM ITS driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_init(intel_cln_esram_test_init);
+module_exit(intel_cln_esram_test_exit);
diff --git a/arch/x86/platform/cln/intel_cln_esram_test.h b/arch/x86/platform/cln/intel_cln_esram_test.h
new file mode 100644
index 0000000..98e4546
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_esram_test.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/**
+ * intel_cln_esram_test.h
+ *
+ * Define integers for ioctl operation
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>
+ */
+
+#ifndef __INTEL_CLN_ESRAM_TEST_H__
+#define __INTEL_CLN_ESRAM_TEST_H__
+
+#define CLN_ESRAM_IOCTL_BASE 255
+#define CLN_F_SW_APP_ESRAM_0 0x00000000
+#define CLN_F_SW_APP_ESRAM_1 0x00000001
+#define CLN_F_SW_APP_ESRAM_2 0x00000002
+#define CLN_F_SW_APP_ESRAM_3 0x00000003
+#define CLN_F_SW_APP_ESRAM_4 0x00000004
+#define CLN_F_SW_APP_ESRAM_5 0x00000005
+#define CLN_F_SW_APP_ESRAM_6 0x00000006
+#define CLN_F_SW_APP_ESRAM_7 0x00000007
+#define CLN_F_SW_APP_ESRAM_8 0x00000008
+
+#endif /* __INTEL_CLN_ESRAM_TEST_H__ */
+
diff --git a/arch/x86/platform/cln/intel_cln_imr.c b/arch/x86/platform/cln/intel_cln_imr.c
new file mode 100644
index 0000000..d955b52
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_imr.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton IMR driver
+ *
+ * IMR stand for Insolate Memory Region, supported by Clanton SoC.
+ *
+ * A total number of 8 IMRs have implemented by Clanton SoC,
+ * Some IMRs might be already occupied by BIOS or Linux during
+ * booting time.
+ *
+ * user can cat /proc/driver/imr/status for current imr usage report.
+ *
+ * To allocate imr, the input memory address format has to match the 1k algined
+ * actual Physical address required by HW.
+ *
+ * The IMR alloc API will locate the next available IMR slot set up
+ * with input memory region, then apply the input access right masks
+ *
+ * The IMR can be freed with the pre-allocated memory addresses.
+ */
+
+#include <asm-generic/uaccess.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/proc_fs.h>
+
+#include "intel_cln_imr.h"
+#include <asm/imr.h>
+
+#define DRIVER_NAME "intel-cln-imr"
+#define IMR_PROC_DIR "driver/imr"
+#define IMR_PROC_FILE "status"
+
+#define IMR_READ_MASK 0x1
+#define IMR_MAX_ID 7
+
+#ifndef phys_to_virt
+#define phys_to_virt __va
+#endif
+
+/* IMR HW register address structre */
+struct cln_imr_reg_t {
+ u8 imr_xl; /* high address register */
+ u8 imr_xh; /* low address register */
+ u8 imr_rm; /* read mask register */
+ u8 imr_wm; /* write mask register */
+} cln_imr_reg_t;
+
+/**
+ * struct cln_imr_addr_t
+ *
+ * IMR memory address structure
+ */
+struct cln_imr_addr_t {
+ u32 addr_low; /* low boundary memroy address */
+ u32 addr_high; /* high boundary memory address */
+ u32 read_mask; /* read access right mask */
+ u32 write_mask; /* write access right mask */
+} cln_imr_addr_t;
+
+/**
+ * struct cln_imr_pack
+ *
+ * local IMR pack structure
+ */
+struct cln_imr_pack {
+ bool occupied; /* IMR occupied */
+ bool locked; /* IMR lock */
+ struct cln_imr_reg_t reg; /* predefined imr register address */
+ struct cln_imr_addr_t addr; /* IMR address region structure */
+ unsigned char info[MAX_INFO_SIZE]; /* IMR info */
+} cln_imr_pack;
+
+
+/* Predefined HW register address */
+static struct cln_imr_reg_t imr_reg_value[] = {
+ { IMR0L, IMR0H, IMR0RM, IMR0WM },
+ { IMR1L, IMR1H, IMR1RM, IMR1WM },
+ { IMR2L, IMR2H, IMR2RM, IMR2WM },
+ { IMR3L, IMR3H, IMR3RM, IMR3WM },
+ { IMR4L, IMR4H, IMR4RM, IMR4WM },
+ { IMR5L, IMR5H, IMR5RM, IMR5WM },
+ { IMR6L, IMR6H, IMR6RM, IMR6WM },
+ { IMR7L, IMR7H, IMR7RM, IMR7WM }
+};
+
+/* proc directory */
+struct proc_dir_entry *pdir;
+
+/* proc file interface /proc/drivers/imr/stats */
+struct proc_dir_entry *pstat;
+
+/**
+ * module parameter
+ * IMR slot should repersant the available IMR region from
+ * linux boot and BIOS.
+ *
+ * For example: imr_bit_mask = 0x10111001
+ * occupied IMR: 0, 3, 4, 5, 7
+ * un-occupied IMR: 1, 2, 6
+ */
+static int imr_bit_mask = 0xFF;
+module_param(imr_bit_mask, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(imr_bit_mask, "IMR bit mask");
+
+/**
+ * module parameter
+ * if IMR lock is a nozero value, all unlocked
+ * imrs will be locked regardless the usage.
+ */
+static int imr_lock = 1;
+module_param(imr_lock, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(imr_lock, "switch to lock unused IMR");
+
+/* local IMR data structure */
+struct cln_imr_pack local_imr[IMR_MAXID];
+
+/**
+ * intel_cln_imr_read_reg
+ *
+ * @param reg: register address
+ * @return nothing
+ *
+ * return register value from input address.
+ */
+static inline uint32_t intel_cln_imr_read_reg(uint8_t reg)
+{
+ uint32_t temp = 0;
+
+ intel_cln_sb_read_reg(SB_ID_ESRAM, CFG_READ_OPCODE, reg, &temp, 0);
+ return temp;
+}
+
+/**
+ * intel_cln_imr_update_local_data
+ *
+ * @return nothing
+ *
+ * Populate IMR data structure from HW.
+ */
+static inline void intel_cln_imr_update_local_data(void)
+{
+ int i = 0;
+
+ for (i = 0; i < IMR_MAXID; i++) {
+
+ local_imr[i].addr.addr_low =
+ intel_cln_imr_read_reg(imr_reg_value[i].imr_xl);
+ local_imr[i].addr.addr_high =
+ intel_cln_imr_read_reg(imr_reg_value[i].imr_xh);
+ local_imr[i].addr.read_mask =
+ intel_cln_imr_read_reg(imr_reg_value[i].imr_rm);
+ local_imr[i].addr.write_mask =
+ intel_cln_imr_read_reg(imr_reg_value[i].imr_wm);
+
+ if (local_imr[i].addr.addr_low & IMR_LOCK_BIT)
+ local_imr[i].locked = true;
+
+ if (local_imr[i].addr.read_mask > 0 &&
+ local_imr[i].addr.read_mask < IMR_READ_ENABLE_ALL){
+ local_imr[i].occupied = true;
+ } else {
+ local_imr[i].occupied = false;
+ memcpy(local_imr[i].info, "NOT USED", MAX_INFO_SIZE);
+ }
+ }
+}
+
+/**
+ * prepare_input_addr
+ *
+ * @param addr: input physical memory address
+ * @return formated memory address
+ *
+ * 1. verify input memory address alignment
+ * 2. apply IMR_REG_MASK to match the format required by HW
+ */
+static inline uint32_t prepare_input_addr(uint32_t addr)
+{
+ if (addr & (IMR_MEM_ALIGN - 1))
+ return 0;
+
+ addr = (addr >> 8) & IMR_REG_MASK;
+ return addr;
+}
+
+/**
+ * intel_cln_imr_find_free_entry
+ *
+ * @return the next free imr slot
+ */
+int intel_cln_imr_find_free_entry(void)
+{
+ int i = 0;
+
+ intel_cln_imr_update_local_data();
+
+ for (i = 0; i < IMR_MAXID; i++) {
+ if ((!local_imr[i].occupied) && (!local_imr[i].locked))
+ return i;
+ }
+
+ pr_err("%s: No more free IMR available.\n", __func__);
+ return -ENOMEM;
+}
+
+
+/**
+ * intel_cln_remove_imr_entry
+ *
+ * @param id: imr slot id
+ * @return nothing
+ *
+ * remove imr slot base on input id
+ */
+void intel_cln_remove_imr_entry(int id)
+{
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_rm, IMR_READ_ENABLE_ALL,
+ 0);
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_wm, IMR_WRITE_ENABLE_ALL,
+ 0);
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_xl, IMR_BASE_ADDR, 0);
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_xh, IMR_BASE_ADDR, 0);
+}
+
+/**
+ * intel_cln_imr_add_entry
+ *
+ * @param id: imr slot id
+ * @param hi: hi memory address
+ * @param lo: lo memory address
+ * @param read: read access mask
+ * @param write: write access mask
+ * @return nothing
+ *
+ * Setup an IMR entry
+ */
+static void intel_cln_imr_add_entry(int id, uint32_t hi,
+ uint32_t lo, uint32_t read, uint32_t write, bool lock)
+{
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_xl, lo, 0);
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_xh, hi, 0);
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_rm, read, 0);
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_wm, write, 0);
+ if (lock) {
+ lo |= IMR_LOCK_BIT;
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ imr_reg_value[id].imr_xl, lo, 0);
+ }
+}
+
+/**
+ * intel_cln_imr_alloc
+ *
+ * @param high: high boundary of memory address
+ * @param low: low boundary of memorry address
+ * @param read: IMR read mask value
+ * @param write: IMR write mask value
+ * @return nothing
+ *
+ * setup the next available IMR with customized read and write masks
+ */
+int intel_cln_imr_alloc(uint32_t high, uint32_t low, uint32_t read,
+ uint32_t write, unsigned char *info, bool lock)
+{
+ int id = 0;
+
+ if (info == NULL)
+ return -EINVAL;
+
+ if ((low & IMR_LOCK_BIT) || (read == 0 || write == 0)) {
+ pr_err("%s: Invalid acces mode\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Calculate aligned addresses and validate range */
+ high = prepare_input_addr(high);
+ low = prepare_input_addr(low);
+
+ /* Find a free entry */
+ id = intel_cln_imr_find_free_entry();
+ if (id < 0)
+ return -ENOMEM;
+
+ /* Add entry - locking as necessary */
+ intel_cln_imr_add_entry(id, high, low, (read & IMR_READ_ENABLE_ALL),
+ write, lock);
+
+ /* Name the new entry */
+ memcpy(local_imr[id].info, info, MAX_INFO_SIZE);
+
+ /* Update local data structures */
+ intel_cln_imr_update_local_data();
+
+ DBG("%s: allocate IMR %d %s\n", __func__, id,
+ lock ? "locked" : "unlocked");
+
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_imr_alloc);
+
+/**
+ * get_phy_addr
+ * @return phy address value
+ *
+ * convert register format to physical address format.
+ */
+static uint32_t get_phy_addr(uint32_t reg_value)
+{
+ reg_value = ((reg_value & IMR_REG_MASK) << 8);
+ return reg_value;
+}
+
+/**
+ * intel_cln_imr_proc_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Populates IMR state via /proc/driver/imr
+ */
+static int intel_cln_imr_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+ int i = 0;
+ int size;
+ uint32_t hi_phy_addr, lo_phy_addr;
+
+ /* get the latest imr settings */
+ intel_cln_imr_update_local_data();
+
+ for (i = 0; i < IMR_MAXID; i++) {
+
+ /* read back the actual input physical memory address */
+ hi_phy_addr = get_phy_addr(local_imr[i].addr.addr_high);
+ lo_phy_addr = get_phy_addr(local_imr[i].addr.addr_low);
+
+ /* the IMR always protect extra 1k memory size above the input
+ * high reg value
+ */
+ size = ((hi_phy_addr - lo_phy_addr) / IMR_MEM_ALIGN) + 1;
+
+ len += snprintf(page+len, count,
+ "imr - id : %d\n"
+ "info : %s\n"
+ "occupied : %s\n"
+ "locked : %s\n"
+ "size : %d kb\n"
+ "hi addr (phy): 0x%08x\n"
+ "lo addr (phy): 0x%08x\n"
+ "hi addr (vir): 0x%08x\n"
+ "lo addr (vir): 0x%08x\n"
+ "read mask : 0x%08x\n"
+ "write mask : 0x%08x\n\n",
+ i,
+ local_imr[i].info,
+ local_imr[i].occupied ? "yes" : "no",
+ local_imr[i].locked ? "yes" : "no",
+ size,
+ hi_phy_addr,
+ lo_phy_addr,
+ (uint32_t)phys_to_virt(hi_phy_addr),
+ (uint32_t)phys_to_virt(lo_phy_addr),
+ local_imr[i].addr.read_mask,
+ local_imr[i].addr.write_mask);
+ }
+ *eof = 1;
+ return len;
+}
+
+/**
+ * intel_cln_imr_proc_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Function allows user-space to operate IMRs through proc interface
+ * e.g. "echo imr off 7 > /proc/drivers/imr/stats" to switch IMR 7 off
+ * if its unlocked.
+ */
+static int intel_cln_imr_proc_write(struct file *file, const char __user *buf,
+ unsigned long count, void *data)
+{
+ ssize_t ret = 0;
+ int id = 0;
+ char *cbuf = NULL;
+ char *sbuf = NULL;
+ char *cmd_id = NULL;
+ char *cmd = NULL;
+
+ if (count <= 1)
+ return -EINVAL;
+
+ /* Get input */
+ sbuf = cbuf = kzalloc(count+1, GFP_KERNEL);
+ if (cbuf == NULL)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (copy_from_user(cbuf, (char *)buf, count))
+ goto done;
+
+ DBG("%s: input read: %s !\n", __func__, cbuf);
+ /* Parse for format "entity on" "entity off" */
+ while (sbuf < (cbuf + count)) {
+ if (*sbuf == ' ') {
+ *sbuf = 0;
+ sbuf++;
+
+ if (cmd_id && cmd)
+ break;
+ if (cmd == NULL)
+ cmd = sbuf;
+ else
+ cmd_id = sbuf;
+ }
+ sbuf++;
+ }
+
+ ret = -EINVAL;
+ if (cmd == NULL || cmd_id == NULL)
+ goto done;
+
+ if (strstr(cmd, "off"))
+ DBG("try to remove IMR: %s.\n", cmd_id);
+ else
+ goto done;
+
+ id = (int)(cmd_id[0]-'0');
+ if (id < 0 || id > IMR_MAX_ID)
+ goto done;
+
+ /* get latest imr hardware settings */
+ intel_cln_imr_update_local_data();
+
+ if (local_imr[id].locked) {
+ pr_err("%s: IMR locked !\n", __func__);
+ goto done;
+ }
+
+ intel_cln_remove_imr_entry(id);
+ intel_cln_imr_update_local_data();
+
+ ret = 0;
+done:
+ if (ret == 0)
+ ret = (ssize_t)count;
+
+ kfree(cbuf);
+ return ret;
+}
+
+
+/**
+ * intel_cln_imr_free
+ *
+ * @param high: high boundary of memory address
+ * @param low: low boundary of memorry address
+ * @return nothing
+ *
+ * remove the imr based on input memory region
+ */
+int intel_cln_imr_free(uint32_t high, uint32_t low)
+{
+ int i = 0;
+
+ if (low > high) {
+ pr_err("%s: Invalid input address values.\n", __func__);
+ return -EINVAL;
+ }
+
+ high = prepare_input_addr(high);
+ if (!high) {
+ pr_err("%s: Invalid input memory address.\n", __func__);
+ return -EINVAL;
+ }
+
+ low = prepare_input_addr(low);
+ if (!low) {
+ pr_err("%s: Invalid input memory address.\n", __func__);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < IMR_MAXID; i++) {
+ if (local_imr[i].occupied
+ && (local_imr[i].addr.addr_low == low)
+ && (local_imr[i].addr.addr_high == high)
+ && (!local_imr[i].locked)) {
+ intel_cln_remove_imr_entry(i);
+ intel_cln_imr_update_local_data();
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(intel_cln_imr_free);
+
+/**
+ * intel_cln_imr_proc_remove
+ *
+ * @return nothing
+ * Removes /proc entires
+ */
+static void intel_cln_imr_proc_remove(void)
+{
+ remove_proc_entry(IMR_PROC_FILE, pdir);
+ remove_proc_entry(IMR_PROC_DIR, NULL);
+}
+
+/**
+ * intel_cln_imr_proc_add
+ *
+ * @return nothing
+ * add /proc/stat entry
+ */
+static int intel_cln_imr_proc_add(void)
+{
+ pdir = proc_mkdir(IMR_PROC_DIR, NULL);
+ if (pdir == NULL) {
+ pr_err("%s: PROC dir create failed.\n", __func__);
+ return -ENOMEM;
+ }
+
+ pstat = create_proc_entry(IMR_PROC_FILE, 0, pdir);
+ if (pstat == NULL) {
+ pr_err("%s: PROC imr file create failed.\n", __func__);
+ return -EIO;
+ }
+ pstat->read_proc = intel_cln_imr_proc_read;
+ pstat->write_proc = intel_cln_imr_proc_write;
+ pstat->data = NULL;
+
+ return 0;
+}
+
+/**
+ * intel_cln_imr_load_local_data
+ *
+ * @param mask: module parameter
+ * @return nothing
+ *
+ * prepare local IMR data structure from input module parameter.
+ */
+static void intel_cln_imr_load_local_data(int mask)
+{
+ int i = 0;
+
+ BUG_ON((mask > 255 || mask < 0));
+
+ for (i = 0; i < IMR_MAXID; i++) {
+ local_imr[i].addr.addr_low =
+ intel_cln_imr_read_reg(imr_reg_value[i].imr_xl);
+
+ /* mask bit 1 means imr occupied*/
+ if (((mask>>i) & IMR_READ_MASK) == 0) {
+ if (!(local_imr[i].addr.addr_low & IMR_LOCK_BIT))
+ intel_cln_remove_imr_entry(i);
+ }
+ }
+
+ intel_cln_imr_update_local_data();
+}
+
+/**
+ * intel_cln_imr_init_data
+ *
+ * @return nothing
+ * initialize local_imr data structure
+ */
+static void intel_cln_imr_init_data(void)
+{
+ int i = 0;
+
+ intel_cln_imr_update_local_data();
+
+ for (i = 0; i < IMR_MAXID; i++) {
+ local_imr[i].reg = imr_reg_value[i];
+ memcpy(local_imr[i].info, "System Reserved Region",
+ MAX_INFO_SIZE);
+ }
+}
+
+/**
+ * intel_cln_imr_lockall
+ *
+ * @param mask: module parameter
+ * @return nothing
+ *
+ * lock up all un-locked IMRs
+ */
+int intel_cln_imr_lockall(void)
+{
+ int i = 0;
+ uint32_t temp_addr;
+
+ /* Enumerate IMR data structures */
+ intel_cln_imr_init_data();
+ intel_cln_imr_load_local_data(imr_bit_mask);
+
+ /* Nothing else to do */
+ if (imr_lock == 0)
+ return -EINVAL;
+
+ /* Cycle through IMRs locking whichever are unlocked */
+ for (i = 0; i < IMR_MAXID; i++) {
+
+ temp_addr = local_imr[i].addr.addr_low;
+ if (!(temp_addr & IMR_LOCK_BIT)) {
+
+ DBG("%s: locking IMR %d\n", __func__, i);
+ temp_addr |= IMR_LOCK_BIT;
+ intel_cln_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
+ local_imr[i].reg.imr_xl,
+ temp_addr, 0);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_imr_lockall);
+
+/**
+ * intel_cln_imr_init
+ *
+ * @return 0 success < 0 failue
+ *
+ * module entry point
+ */
+static int __init intel_cln_imr_probe(struct platform_device * pdev)
+{
+ int ret;
+
+ /* initialise local imr data structure */
+ intel_cln_imr_init_data();
+
+ ret = intel_cln_imr_proc_add();
+ BUG_ON(ret != 0);
+
+ if(intel_cln_imr_runt_setparams() == 0){
+ intel_cln_imr_lockall();
+ }
+
+ pr_info("IMR setup complete\n");
+
+ return 0;
+}
+
+/**
+ * intel_cln_imr_exit
+ *
+ * @return nothing
+ * Module exit
+ */
+static int intel_cln_imr_remove(struct platform_device * pdev)
+{
+ /* this will disable all the unlocked IMRs */
+ intel_cln_imr_proc_remove();
+
+ return 0;
+}
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_imr_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_imr_probe,
+ .remove = intel_cln_imr_remove,
+};
+
+module_platform_driver(intel_cln_imr_driver);
+
+MODULE_DESCRIPTION("Intel Clanton SOC IMR API ");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+
diff --git a/arch/x86/platform/cln/intel_cln_imr.h b/arch/x86/platform/cln/intel_cln_imr.h
new file mode 100644
index 0000000..8ee2d70
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_imr.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton IMR driver
+ *
+ * IMR stand for Insolate Memory Region, supported by Clanton SoC.
+ *
+ * A total number of 8 IMRs have implemented by Clanton SoC,
+ * some IMRs might be already occupied by BIOS or Linux booting time.
+ *
+ * Input addresses parameter required the actual Physical address.
+ *
+ * The IMR alloc API will locate the next available IMR slot set up
+ * with input memory region, and apply with the default access right
+ * (CPU & CPU_snoop enable).
+ *
+ * The alloc_mask API takes input read & write masks values to set up
+ * IMR with customized access right.
+ *
+ * User can free IMR with pre-alloc specified addresses.
+ */
+
+#ifndef __INTEL_CLN_IMR_H__
+#define __INTEL_CLN_IMR_H__
+
+#include <linux/intel_cln_sb.h>
+#include "asm/io.h"
+
+#define CFG_READ_OPCODE 0x10 /* BUnit Control Read */
+#define CFG_WRITE_OPCODE 0x11 /* BUnit control write */
+
+/* DRAM IMR register addresses */
+#define IMR0L 0x40
+#define IMR0H 0x41
+#define IMR0RM 0x42
+#define IMR0WM 0x43
+#define IMR1L 0x44
+#define IMR1H 0x45
+#define IMR1RM 0x46
+#define IMR1WM 0x47
+#define IMR2L 0x48
+#define IMR2H 0x49
+#define IMR2RM 0x4A
+#define IMR2WM 0x4B
+#define IMR3L 0x4C
+#define IMR3H 0x4D
+#define IMR3RM 0x4E
+#define IMR3WM 0x4F
+#define IMR4L 0x50
+#define IMR4H 0x51
+#define IMR4RM 0x52
+#define IMR4WM 0x53
+#define IMR5L 0x54
+#define IMR5H 0x55
+#define IMR5RM 0x56
+#define IMR5WM 0x57
+#define IMR6L 0x58
+#define IMR6H 0x59
+#define IMR6RM 0x5A
+#define IMR6WM 0x5B
+#define IMR7L 0x5C
+#define IMR7H 0x5D
+#define IMR7RM 0x5E
+#define IMR7WM 0x5F
+
+#define IMR_LOCK_BIT 0x80000000
+#define IMR_WRITE_ENABLE_ALL 0xFFFFFFFF
+#define IMR_READ_ENABLE_ALL 0xBFFFFFFF
+#define IMR_REG_MASK 0xFFFFFC
+
+#define IMR_ESRAM_FLUSH_INIT 0x80000000 /* esram flush */
+#define IMR_SNOOP_ENABLE 0x40000000 /* core snoops */
+#define IMR_PUNIT_ENABLE 0x20000000
+#define IMR_SMM_ENABLE 0x02 /* core SMM access */
+#define IMR_NON_SMM_ENABLE 0x01 /* core non-SMM access */
+#define IMR_BASE_ADDR 0x00
+#define IMR_MEM_ALIGN 0x400
+
+#define MAX_INFO_SIZE 64
+#define IMR_MAXID 8
+
+/* snoop + Non SMM write mask */
+#define IMR_DEFAULT_MASK (IMR_SNOOP_ENABLE \
+ + IMR_ESRAM_FLUSH_INIT \
+ + IMR_NON_SMM_ENABLE)
+
+/* debug printk */
+#ifdef DEBUG
+#define DBG(args...) pr_info(args)
+#else
+#define DBG(args...)
+#endif
+
+extern unsigned long _text;
+extern unsigned long __init_begin;
+
+/**
+ * intel_cln_imr_alloc
+ *
+ * @param high: the end of physical memory address
+ * @param low: the start of physical memory address
+ * @param read: IMR read mask value
+ * @param write: IMR write maks value
+ * @param info: imr information
+ * @param lock: imr lock
+ *
+ * Setup imr with customised read/ write masks
+ */
+int intel_cln_imr_alloc(u32 high, u32 low, u32 read, u32 write,
+ unsigned char *info, bool lock);
+
+/**
+ * intel_cln_imr_free
+ *
+ * @param high: high boundary of memory address
+ * @param low: low boundary of memorry address
+ *
+ * remove the imr based on input memory region
+ */
+int intel_cln_imr_free(u32 high, u32 low);
+
+/**
+ * intel_cln_remove_imr_entry
+ *
+ * @param id: internal imr data struct id
+ *
+ * Remove imr based on input imr data structure id
+ */
+void intel_cln_remove_imr_entry(int id);
+
+#endif
diff --git a/arch/x86/platform/cln/intel_cln_imr_kernel.c b/arch/x86/platform/cln/intel_cln_imr_kernel.c
new file mode 100644
index 0000000..e53307e
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_imr_kernel.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton IMR driver
+ *
+ * IMR stand for Insolate Memory Region, supported by Clanton SoC.
+ *
+ * The IMR id 3 is pre-defined as the use for kernel data protection
+ *
+ * The early imr protects entire memory (from the beginning of kernel text
+ * section to the top of memory) during linux boot time. In the linux run
+ * time, the protection need to resize down to memory region that only
+ * contains: kernel text, read only data, and initialized data section.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/clanton.h>
+#include <linux/printk.h>
+#include "intel_cln_imr.h"
+
+/* pre-defined imr id for uncompressed kernel */
+#define IMR_KERNEL_ID 3
+
+/**
+ * addr_hw_ready
+ *
+ * shift input address value to match HW required 1k aligned format
+ */
+static inline uint32_t addr_hw_ready(uint32_t addr)
+{
+ /* memory alignment */
+ addr &= (~((1 << 10) - 1));
+
+ /* prepare input addr in HW required format */
+ addr = (addr >> 8) & IMR_REG_MASK;
+ return addr;
+}
+
+/**
+ * void intel_cln_imr_runt_kerndata_setup
+ *
+ * Setup imr for kernel text, read only data section
+ *
+ * The read only data (rodata) section placed between text and initialized data
+ * section by kernel.
+ */
+static void intel_cln_imr_runt_kerndata_setup(void)
+{
+ uint32_t hi;
+ uint32_t lo;
+
+ hi = (uint32_t)virt_to_phys(&__init_begin);
+ lo = (uint32_t)virt_to_phys(&_text);
+
+ if (intel_cln_imr_alloc((hi - IMR_MEM_ALIGN), lo,
+ IMR_DEFAULT_MASK, IMR_DEFAULT_MASK,
+ "KERNEL RUNTIME DATA", 0)) {
+ pr_err("IMR: Set up runtime kernel data imr faild!\n");
+ return;
+ }
+}
+
+/**
+ * intel_cln_imr_runt_oldkern_teardown
+ *
+ * remove the previous imr protection for uncompressed kernel data
+ *
+ */
+static void intel_cln_imr_runt_oldkern_teardown(void)
+{
+ intel_cln_remove_imr_entry(IMR_KERNEL_ID);
+}
+
+/**
+ * intel_cln_imr_runt_setparams
+ *
+ * set imr range for text, read only, initialised data in linux run time
+ */
+int intel_cln_imr_runt_setparams(void)
+{
+ if (intel_cln_plat_get_id() == CLANTON_PLAT_UNDEFINED)
+ return -ENODEV;
+
+ intel_cln_imr_runt_kerndata_setup();
+
+ /* Remove initial IMR */
+ intel_cln_imr_runt_oldkern_teardown();
+
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_imr_runt_setparams);
+
+/**
+ * intel_cln_imr_runt_init
+ *
+ * module entry point
+ */
+static int __init intel_cln_imr_runt_init(void)
+{
+ return 0;
+}
+
+/**
+ * intel_cln_imr_runt_exit
+ *
+ * Module exit
+ */
+static void __exit intel_cln_imr_runt_exit(void)
+{
+ /* do nothing */
+}
+
+MODULE_DESCRIPTION("Intel Clanton SOC IMR API ");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+
+subsys_initcall(intel_cln_imr_runt_init);
+module_exit(intel_cln_imr_runt_exit);
diff --git a/arch/x86/platform/cln/intel_cln_imr_test.c b/arch/x86/platform/cln/intel_cln_imr_test.c
new file mode 100644
index 0000000..2d98507
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_imr_test.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton IMR Test module
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include "intel_cln_imr.h"
+
+#define DRIVER_NAME "intel_cln_imr_test"
+
+/**
+ * XXX intel_cln_sb.h needs to be updated with SB_ID_PUNIT and change
+ * propagated. This is a workaround to make it look less ugly. */
+#define SB_ID_PUNIT SB_ID_THERMAL
+
+/* Memory-mapped SPI Flash address */
+#define ILB_SPIFLASH_BASEADDR 0xFF800000
+/* PUnit DMA block transfer size, in bytes */
+#define SPI_DMA_BLOCK_SIZE 512
+
+/**************************** Exported to LISA *******************************/
+
+/*
+ * Internally-used ioctl code. At the moment it is not reserved by any mainline
+ * driver.
+ */
+#define IMR_TEST_IOCTL_CODE 0xE1
+
+/*
+ * Integers for ioctl operation.
+ */
+#define IOCTL_CLN_SANITY_CHECK_PUNIT_DMA _IO(IMR_TEST_IOCTL_CODE, 0x00)
+#define IOCTL_CLN_IMR_1 _IO(IMR_TEST_IOCTL_CODE, 0x01)
+
+/*****************************************************************************/
+
+/**
+ * struct intel_cln_imr_dev
+ *
+ * Structure to represent module state/data/etc
+ */
+struct intel_cln_imr_test_dev {
+ unsigned int opened;
+ struct platform_device *pldev; /* Platform device */
+ struct cdev cdev;
+ struct mutex open_lock;
+};
+
+static struct intel_cln_imr_test_dev imr_test_dev;
+static struct class *imr_test_class;
+static DEFINE_MUTEX(imr_test_mutex);
+static int imr_test_major;
+
+/* PUnit DMA registers over side-band */
+#define PUNIT_SPI_DMA_COUNT_REG 0x60
+#define PUNIT_SPI_DMA_DEST_REG 0x61
+#define PUNIT_SPI_DMA_SRC_REG 0x62
+
+/**
+ * ilb_spi_dma_read
+ *
+ * @param src: physical address in Legacy SPI Flash
+ * @param dst: physical address of destination
+ * @param dma_block_count: number of 512B SPI Flash blocks to be transferred
+ *
+ * Read-access iLB SPI via PUnit DMA engine.
+ *
+ */
+static void ilb_spi_dma_read(u32 *src, u32 *dst, u32 dma_block_count)
+{
+ pr_info("%s: src=%p, dst=%p, count=%u\n", __func__, src, dst,
+ dma_block_count);
+
+ /* Setup source and destination addresses. */
+ intel_cln_sb_write_reg(SB_ID_PUNIT, CFG_WRITE_OPCODE,
+ PUNIT_SPI_DMA_SRC_REG, (u32) src, 0);
+ intel_cln_sb_write_reg(SB_ID_PUNIT, CFG_WRITE_OPCODE,
+ PUNIT_SPI_DMA_DEST_REG, (u32) dst, 0);
+
+ pr_info("%s: starting transaction\n", __func__);
+
+ /*
+ * Setup the number of block to be copied over. Transaction will start
+ * as soon as the register is filled with value.
+ */
+ intel_cln_sb_write_reg(SB_ID_PUNIT, CFG_WRITE_OPCODE,
+ PUNIT_SPI_DMA_COUNT_REG, dma_block_count, 0);
+
+ /* Poll for completion. */
+ while (dma_block_count > 0) {
+ intel_cln_sb_read_reg(SB_ID_PUNIT, CFG_READ_OPCODE,
+ PUNIT_SPI_DMA_COUNT_REG, &dma_block_count, 0);
+ }
+
+ pr_info("%s: transaction completed\n", __func__);
+}
+
+/**
+ * punit_dma_sanity_check
+ *
+ * @return 0 if success, 1 if failure
+ *
+ * Perform a basic sanity check for PUnit DMA engine. Copy over a 512B SPI
+ * Flash block.
+ */
+static int punit_dma_sanity_check(void)
+{
+ int err = 0;
+ u32 *buffer = NULL;
+ u32 buf_ph_addr = 0;
+
+ /* Allocate 512B buffer for 1 SPI Flash block */
+ buffer = kzalloc(SPI_DMA_BLOCK_SIZE, GFP_KERNEL);
+ if (!buffer) {
+ err = -ENOMEM;
+ goto end;
+ }
+
+ /* DMA first SPI Flash block into buffer */
+ buf_ph_addr = (u32)virt_to_phys(buffer);
+ ilb_spi_dma_read((u32 *)ILB_SPIFLASH_BASEADDR, (u32 *)buf_ph_addr, 1);
+
+ kfree(buffer);
+end:
+ return err;
+}
+
+/**
+ * imr_violate_kernel_punit_dma
+ *
+ * @return always 0
+ *
+ * PUnit-DMA access to the Uncompressed Kernel IMR.
+ * This is based on set_imr_kernel_data() in intel_cln_imr.c. Find the physical
+ * address of .text section and copy a 512B chunk of legacy SPI via PuUnit DMA.
+ *
+ */
+static int imr_violate_kernel_punit_dma(void)
+{
+ extern unsigned long _text;
+ u32 kernel_text = (u32)virt_to_phys(&_text);
+
+ /* We expect this to trigger an IMR violation reset */
+ ilb_spi_dma_read((u32 *)ILB_SPIFLASH_BASEADDR, (u32 *)kernel_text, 1);
+
+ /*
+ * If we're still alive, we have a serious bug:
+ * - we didn't appropriately target the IMR?
+ * - if we have, weren't we prevented from accessing?
+ * - if we weren't prevented, it's unlikely we're alive with a dirty
+ * text section
+ */
+ pr_err("%s: BUG: still running after DMAing into kernel text!?\n",
+ __func__);
+
+ return 0;
+}
+
+/*
+ * File ops
+ */
+static long imr_test_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -EINVAL;
+
+ switch (cmd) {
+ case IOCTL_CLN_SANITY_CHECK_PUNIT_DMA:
+ /* Check PUnit DMA actually works */
+ ret = punit_dma_sanity_check();
+ break;
+ case IOCTL_CLN_IMR_1:
+ /* Kernel IMR violation: PUnit DMA access */
+ ret = imr_violate_kernel_punit_dma();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int imr_test_open(struct inode *inode, struct file *file)
+{
+ mutex_lock(&imr_test_mutex);
+ nonseekable_open(inode, file);
+
+ if (mutex_lock_interruptible(&imr_test_dev.open_lock)) {
+ mutex_unlock(&imr_test_mutex);
+ return -ERESTARTSYS;
+ }
+
+ if (imr_test_dev.opened) {
+ mutex_unlock(&imr_test_dev.open_lock);
+ mutex_unlock(&imr_test_mutex);
+ return -EINVAL;
+ }
+
+ imr_test_dev.opened++;
+ mutex_unlock(&imr_test_dev.open_lock);
+ mutex_unlock(&imr_test_mutex);
+ return 0;
+}
+
+static int imr_test_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&imr_test_dev.open_lock);
+ imr_test_dev.opened = 0;
+ mutex_unlock(&imr_test_dev.open_lock);
+
+ return 0;
+}
+
+static const struct file_operations imr_test_file_ops = {
+ .open = imr_test_open,
+ .release = imr_test_release,
+ .unlocked_ioctl = imr_test_ioctl,
+ .llseek = no_llseek,
+};
+
+/**
+ * intel_cln_imr_test_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ */
+static int intel_cln_imr_test_probe(struct platform_device * pdev)
+{
+ int retval = 0;
+ unsigned int minor = 0;
+
+ mutex_init(&imr_test_dev.open_lock);
+ cdev_init(&imr_test_dev.cdev, &imr_test_file_ops);
+ imr_test_dev.cdev.owner = THIS_MODULE;
+
+ retval = cdev_add(&imr_test_dev.cdev, MKDEV(imr_test_major, minor), 1);
+ if (retval) {
+ printk(KERN_ERR "chardev registration failed\n");
+ return -EINVAL;
+ }
+ if (IS_ERR(device_create(imr_test_class, NULL,
+ MKDEV(imr_test_major, minor), NULL,
+ "imrtest%u", minor))){
+ dev_err(&pdev->dev, "can't create device\n");
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
+
+static int intel_cln_imr_test_remove(struct platform_device * pdev)
+{
+ unsigned int minor = MINOR(imr_test_dev.cdev.dev);
+
+ device_destroy(imr_test_class, MKDEV(imr_test_major, minor));
+ cdev_del(&imr_test_dev.cdev);
+
+ class_destroy(imr_test_class);
+
+ return 0;
+}
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_imr_test_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = intel_cln_imr_test_remove,
+};
+
+/**
+ * intel_cln_imr_test_init
+ *
+ * Load module.
+ */
+static int __init intel_cln_imr_test_init(void)
+{
+ int retval = 0;
+ dev_t dev;
+
+ imr_test_class = class_create(THIS_MODULE,"cln_imr_test");
+ if (IS_ERR(imr_test_class)) {
+ retval = PTR_ERR(imr_test_class);
+ printk(KERN_ERR "imr_test: can't register imr_test class\n");
+ goto err;
+ }
+
+ retval = alloc_chrdev_region(&dev, 0, 1, "imr_test");
+ if (retval) {
+ printk(KERN_ERR "earam_test: can't register character device\n");
+ goto err_class;
+ }
+ imr_test_major = MAJOR(dev);
+
+ memset(&imr_test_dev, 0x00, sizeof(imr_test_dev));
+ imr_test_dev.pldev = platform_create_bundle(
+ &intel_cln_imr_test_driver, intel_cln_imr_test_probe, NULL, 0, NULL, 0);
+
+ if(IS_ERR(imr_test_dev.pldev)){
+ printk(KERN_ERR "platform_create_bundle fail!\n");
+ retval = PTR_ERR(imr_test_dev.pldev);
+ goto err_class;
+ }
+
+ return 0;
+
+err_class:
+ class_destroy(imr_test_class);
+err:
+ return retval;
+}
+
+static void __exit intel_cln_imr_test_exit(void)
+{
+ platform_device_unregister(imr_test_dev.pldev);
+ platform_driver_unregister(&intel_cln_imr_test_driver);
+}
+
+module_init(intel_cln_imr_test_init);
+module_exit(intel_cln_imr_test_exit);
+
+MODULE_AUTHOR("Josef Ahmad <josef.ahmad@intel.com>");
+MODULE_DESCRIPTION("Clanton IMR test module");
+MODULE_LICENSE("Dual BSD/GPL");
+
diff --git a/arch/x86/platform/cln/intel_cln_layout_data.c b/arch/x86/platform/cln/intel_cln_layout_data.c
new file mode 100644
index 0000000..124bccf
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_layout_data.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define DRIVER_NAME "cln-layout-conf"
+static char __iomem * layout_conf_data;
+static int len;
+
+static ssize_t layout_conf_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ ssize_t plen = len+1;
+ if( plen > PAGE_SIZE )
+ plen = PAGE_SIZE;
+ memcpy(buf, layout_conf_data, plen);
+ return plen;
+}
+
+static struct kobj_attribute layout_conf_attr =
+ __ATTR(layout_conf, 0644, layout_conf_show, NULL);
+
+static int intel_cln_layout_data_probe(struct platform_device *pdev)
+{
+ extern struct kobject * board_data_kobj;
+ int ret = 0;
+
+ layout_conf_data = ioremap(pdev->resource->start,
+ resource_size(pdev->resource));
+ if (!layout_conf_data)
+ return -ENODEV;
+
+ len = resource_size(pdev->resource);
+ ret = sysfs_create_file(board_data_kobj, &layout_conf_attr.attr);
+ if (ret != 0){
+ pr_err("failed to create sysfs entry for layout config\n");
+ iounmap(layout_conf_data);
+ layout_conf_data = NULL;
+ }
+
+ return ret;
+}
+
+static int intel_cln_layout_data_remove(struct platform_device *pdev)
+{
+ extern struct kobject * board_data_kobj;
+
+ if (layout_conf_data){
+ sysfs_remove_file(board_data_kobj, &layout_conf_attr.attr);
+ iounmap(layout_conf_data);
+
+ }
+ return 0;
+}
+
+static struct platform_driver cln_layout_data_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_layout_data_probe,
+ .remove = intel_cln_layout_data_remove,
+};
+
+module_platform_driver(cln_layout_data_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Intel Clanton SPI Data API");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_plat_clanton_hill.c b/arch/x86/platform/cln/intel_cln_plat_clanton_hill.c
new file mode 100644
index 0000000..14a2fda
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_plat_clanton_hill.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "cln-plat-clanton-hill"
+#define GPIO_RESTRICT_NAME "cln-gpio-restrict-nc"
+
+#define CLN_SPI_MAX_CLK_DEFAULT 5000000
+
+/******************************************************************************
+ * Analog Devices AD7298 SPI Device Platform Data
+ ******************************************************************************/
+#include "linux/platform_data/ad7298.h"
+
+/* Maximum input voltage allowed for each ADC input, in milliVolts */
+#define AD7298_MAX_EXT_VIN 5000
+
+static const struct ad7298_platform_data ad7298_platform_data = {
+ .ext_ref = false,
+ .ext_vin_max = { AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN }
+};
+
+/******************************************************************************
+ * Intel Clanton SPI Controller Data
+ ******************************************************************************/
+static struct pxa2xx_spi_chip cln_ffrd_spi_0_cs_0 = {
+ .gpio_cs = 8,
+};
+
+
+/******************************************************************************
+ * ST Microelectronics LIS331DLH I2C Device Platform Data
+ ******************************************************************************/
+#include <linux/platform_data/st_accel_i2c.h>
+
+/* GPIO interrupt pins connected to the LIS331DLH */
+#define ST_ACCEL_INT1_GPIO 15
+#define ST_ACCEL_INT2_GPIO 4
+
+static struct st_accel_i2c_platform_data st_accel_i2c_platform_data;
+
+/**
+ * intel_cln_spi_add_onboard_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers onboard SPI device(s) present on the Clanton Hill platform
+ */
+static int intel_cln_spi_add_onboard_devs(void)
+{
+ struct spi_board_info spi_onboard_devs[] = {
+ {
+ .modalias = "ad7298",
+ .max_speed_hz = CLN_SPI_MAX_CLK_DEFAULT,
+ .platform_data = &ad7298_platform_data,
+ .mode = SPI_MODE_2,
+ .bus_num = 0,
+ .chip_select = 0,
+ .controller_data = &cln_ffrd_spi_0_cs_0,
+ },
+ };
+
+ return spi_register_board_info(spi_onboard_devs,
+ ARRAY_SIZE(spi_onboard_devs));
+}
+
+/**
+ * intel_cln_i2c_add_onboard_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers onboard I2C device(s) present on the Clanton Hill platform
+ */
+static int intel_cln_i2c_add_onboard_devs(void)
+{
+ struct i2c_board_info i2c_onboard_devs[] = {
+ {
+ I2C_BOARD_INFO("intel-cln-max9867", 0x18),
+ },
+ {
+ I2C_BOARD_INFO("lis331dlh", 0x19),
+ .irq = gpio_to_irq(ST_ACCEL_INT1_GPIO),
+ .platform_data = &st_accel_i2c_platform_data,
+ },
+ };
+ st_accel_i2c_platform_data.irq2 = gpio_to_irq(ST_ACCEL_INT2_GPIO);
+
+ return i2c_register_board_info(0, i2c_onboard_devs,
+ ARRAY_SIZE(i2c_onboard_devs));
+}
+
+
+/**
+ * intel_cln_gpio_restrict_probe
+ *
+ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
+ * GPIOs are never released nor accessed by this driver.
+ */
+static int intel_cln_gpio_restrict_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ struct gpio reserved_gpios[] = {
+ {
+ ST_ACCEL_INT1_GPIO,
+ GPIOF_IN,
+ "st_accel_i2c-int1"
+ },
+ {
+ ST_ACCEL_INT2_GPIO,
+ GPIOF_IN,
+ "st_accel_i2c-int2"
+ },
+ };
+
+ ret = intel_cln_spi_add_onboard_devs();
+ if (ret)
+ return ret;
+
+ ret = intel_cln_i2c_add_onboard_devs();
+ if (ret)
+ return ret;
+
+
+ ret = gpio_request_array(reserved_gpios,
+ ARRAY_SIZE(reserved_gpios));
+
+ return ret;
+}
+
+static struct platform_driver gpio_restrict_pdriver = {
+ .driver = {
+ .name = GPIO_RESTRICT_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_gpio_restrict_probe,
+};
+
+static int intel_cln_plat_clanton_hill_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = platform_driver_register(&gpio_restrict_pdriver);
+
+ return ret;
+}
+
+static int intel_cln_plat_clanton_hill_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver cln_clanton_hill_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_clanton_hill_probe,
+ .remove = intel_cln_plat_clanton_hill_remove,
+};
+
+module_platform_driver(cln_clanton_hill_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Cross Hill BSP Data");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_plat_clanton_peak.c b/arch/x86/platform/cln/intel_cln_plat_clanton_peak.c
new file mode 100644
index 0000000..104879e
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_plat_clanton_peak.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "cln-plat-clanton-peak"
+#define GPIO_RESTRICT_NAME "cln-gpio-restrict-nc"
+
+static struct spi_board_info spi_onboard_devs[] = {
+ {
+ .modalias = "spidev",
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .bus_num = 0,
+ },
+ {
+ .modalias = "spidev",
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .bus_num = 1,
+ },
+};
+
+/**
+ * intel_cln_spi_add_onboard_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers onboard SPI device(s) present on the Clanton Peak platform
+ */
+static int intel_cln_spi_add_onboard_devs(void)
+{
+ return spi_register_board_info(spi_onboard_devs,
+ ARRAY_SIZE(spi_onboard_devs));
+}
+
+/**
+ * intel_cln_gpio_restrict_probe
+ *
+ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
+ * GPIOs are never released nor accessed by this driver.
+ */
+static int intel_cln_gpio_restrict_probe(struct platform_device *pdev)
+{
+ /* TODO */
+
+ return 0;
+}
+
+static struct platform_driver gpio_restrict_pdriver = {
+ .driver = {
+ .name = GPIO_RESTRICT_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_gpio_restrict_probe,
+};
+
+static int intel_cln_plat_clanton_peak_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = intel_cln_spi_add_onboard_devs();
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&gpio_restrict_pdriver);
+
+ return ret;
+}
+
+static int intel_cln_plat_clanton_peak_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver clanton_peak_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_clanton_peak_probe,
+ .remove = intel_cln_plat_clanton_peak_remove,
+};
+
+module_platform_driver(clanton_peak_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Clanton Peak BSP Data");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_plat_cross_hill.c b/arch/x86/platform/cln/intel_cln_plat_cross_hill.c
new file mode 100644
index 0000000..b170bd1
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_plat_cross_hill.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "cln-plat-cross-hill"
+#define GPIO_RESTRICT_NAME_NC "cln-gpio-restrict-nc"
+#define GPIO_RESTRICT_NAME_SC "cln-gpio-restrict-sc"
+
+#define CLN_SPI_MAX_CLK_DEFAULT 5000000
+
+/*
+ * GPIO numbers to use for reading 4-bit Blackburn Peak SPI daughterboard ID
+ */
+#define SPI_BPEAK_RESET_GPIO 4
+#define SPI_BPEAK_ID0_GPIO 3
+#define SPI_BPEAK_ID1_GPIO 2
+#define SPI_BPEAK_ID2_GPIO 15
+#define SPI_BPEAK_ID3_GPIO 14
+
+static int nc_gpio_reg;
+static int sc_gpio_reg;
+
+/*
+ * Blackburn Peak SPI daughterboard ID values
+ */
+enum {
+ CLN_SPI_BPEAK_ID_ZB_TI = 0xA,
+ CLN_SPI_BPEAK_ID_ZB_DIGI,
+ CLN_SPI_BPEAK_ID_ZB_INFR_NXP,
+ CLN_SPI_BPEAK_ID_ZB_EXEGIN_ATMEL,
+ CLN_SPI_BPEAK_ID_ADC_MAXIM,
+ CLN_SPI_BPEAK_ID_NONE
+};
+
+
+/******************************************************************************
+ * Analog Devices AD7298 SPI Device Platform Data
+ ******************************************************************************/
+#include "linux/platform_data/ad7298.h"
+
+/* Maximum input voltage allowed for each ADC input, in milliVolts */
+#define AD7298_MAX_EXT_VIN 5000
+
+static const struct ad7298_platform_data ad7298_platform_data = {
+ .ext_ref = false,
+ .ext_vin_max = { AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN }
+};
+
+/******************************************************************************
+ * Intel Clanton SPI Controller Data
+ ******************************************************************************/
+static struct pxa2xx_spi_chip cln_ffrd_spi_0_cs_0 = {
+ .gpio_cs = 8,
+};
+
+static struct pxa2xx_spi_chip cln_ffrd_spi_1_cs_0 = {
+ .gpio_cs = 10,
+};
+
+#if 0
+/* TODO - not needed until dual-device blackburn peak modules are added */
+static struct pxa2xx_spi_chip cln_ffrd_spi_1_cs_1 = {
+ .gpio_cs = 11,
+};
+#endif
+
+
+/**
+ * intel_cln_spi_add_onboard_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers onboard SPI device(s) present on the Cross Hill platform
+ */
+static int intel_cln_spi_add_onboard_devs(void)
+{
+ struct spi_board_info spi_onboard_devs[] = {
+ {
+ .modalias = "ad7298",
+ .max_speed_hz = CLN_SPI_MAX_CLK_DEFAULT,
+ .platform_data = &ad7298_platform_data,
+ .mode = SPI_MODE_2,
+ .bus_num = 0,
+ .chip_select = 0,
+ .controller_data = &cln_ffrd_spi_0_cs_0,
+ },
+ };
+
+ return spi_register_board_info(spi_onboard_devs,
+ ARRAY_SIZE(spi_onboard_devs));
+}
+
+
+/**
+ * intel_cln_spi_get_bpeak_id
+ *
+ * @param bpeak_id: The Blackburn Peak SPI ID obtained from the daughterboard
+ * @return 0 on success or standard errnos on failure
+ *
+ * Reads an ID from GPIO-connected pins on Blackburn peak SPI daughterboard
+ */
+static int intel_cln_spi_get_bpeak_id(u8 *bpeak_id)
+{
+ int ret = 0;
+ struct gpio spi_bpeak_id_gpios[] = {
+ {
+ SPI_BPEAK_RESET_GPIO,
+ GPIOF_OUT_INIT_HIGH,
+ "spi_bpeak_reset"
+ },
+ {
+ SPI_BPEAK_ID0_GPIO,
+ GPIOF_IN,
+ "spi_bpeak_id0"
+ },
+ {
+ SPI_BPEAK_ID1_GPIO,
+ GPIOF_IN,
+ "spi_bpeak_id1"
+ },
+ {
+ SPI_BPEAK_ID2_GPIO,
+ GPIOF_IN,
+ "spi_bpeak_id2"
+ },
+ {
+ SPI_BPEAK_ID3_GPIO,
+ GPIOF_IN,
+ "spi_bpeak_id3"
+ }
+ };
+
+ /*
+ * Read a 4-bit ID value from ID GPIO inputs, which are only valid
+ * while a RESET GPIO output is asserted (active-low)
+ */
+ ret = gpio_request_array(spi_bpeak_id_gpios,
+ ARRAY_SIZE(spi_bpeak_id_gpios));
+ if (ret) {
+ pr_err("%s: Failed to allocate Blackburn Peak ID GPIO pins\n",
+ __func__);
+ return ret;
+ }
+
+ gpio_set_value(SPI_BPEAK_RESET_GPIO, 0);
+ *bpeak_id =
+ (gpio_get_value(SPI_BPEAK_ID3_GPIO) ? 1 << 3 : 0) |
+ (gpio_get_value(SPI_BPEAK_ID2_GPIO) ? 1 << 2 : 0) |
+ (gpio_get_value(SPI_BPEAK_ID1_GPIO) ? 1 << 1 : 0) |
+ (gpio_get_value(SPI_BPEAK_ID0_GPIO) ? 1 : 0);
+ gpio_set_value(SPI_BPEAK_RESET_GPIO, 1);
+
+ gpio_free_array(spi_bpeak_id_gpios,
+ ARRAY_SIZE(spi_bpeak_id_gpios));
+
+ return 0;
+}
+
+/**
+ * intel_cln_spi_add_bpeak_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers SPI device(s) indicated by the ID value obtained from a
+ * Blackburn Peak SPI daughterboard
+ */
+static int intel_cln_spi_add_bpeak_devs(void)
+{
+ u8 spi_bpeak_id = 0;
+ int ret = 0;
+
+ ret = intel_cln_spi_get_bpeak_id(&spi_bpeak_id);
+ if (ret) {
+ pr_err("%s: failed to obtain Blackburn Peak ID\n",
+ __func__);
+ return ret;
+ }
+
+ switch (spi_bpeak_id) {
+
+ case CLN_SPI_BPEAK_ID_NONE:
+ break;
+ case CLN_SPI_BPEAK_ID_ADC_MAXIM:
+ {
+ struct spi_board_info spi_bpeak_devs[] = {
+ {
+ .modalias = "max78m6610_lmu",
+ .max_speed_hz = 2000000,
+ .platform_data = NULL,
+ .mode = SPI_MODE_3,
+ .bus_num = 1,
+ .chip_select = 0,
+ .controller_data = &cln_ffrd_spi_1_cs_0,
+ },
+ };
+
+ return spi_register_board_info(spi_bpeak_devs,
+ ARRAY_SIZE(spi_bpeak_devs));
+ }
+ /* TODO - add other Blackburn Peak variants when details available */
+ default:
+ pr_err("%s: Unsupported Blackburn Peak SPI ID %u\n",
+ __func__, spi_bpeak_id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/** intel_cln_spi_devs_addon
+ *
+ * addon spi device when gpio support in place
+ */
+static int intel_cln_spi_devs_addon(void)
+{
+ int ret = 0;
+
+ ret = intel_cln_spi_add_onboard_devs();
+ if (ret)
+ return ret;
+
+ ret = intel_cln_spi_add_bpeak_devs();
+
+ return ret;
+}
+
+/**
+ * intel_cln_gpio_restrict_probe_nc
+ *
+ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
+ * GPIOs are never released nor accessed by this driver.
+ */
+static int intel_cln_gpio_restrict_probe_nc(struct platform_device *pdev)
+{
+ int ret;
+ nc_gpio_reg = 1;
+
+ if (nc_gpio_reg == 1 && sc_gpio_reg == 1) {
+ ret = intel_cln_spi_devs_addon();
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * intel_cln_gpio_restrict_probe_sc
+ *
+ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
+ * GPIOs are never released nor accessed by this driver.
+ */
+static int intel_cln_gpio_restrict_probe_sc(struct platform_device *pdev)
+{
+ int ret;
+ sc_gpio_reg = 1;
+
+ if (nc_gpio_reg == 1 && sc_gpio_reg == 1) {
+ ret = intel_cln_spi_devs_addon();
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static struct platform_driver gpio_restrict_pdriver_nc = {
+ .driver = {
+ .name = GPIO_RESTRICT_NAME_NC,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_gpio_restrict_probe_nc,
+};
+
+static struct platform_driver gpio_restrict_pdriver_sc = {
+ .driver = {
+ .name = GPIO_RESTRICT_NAME_SC,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_gpio_restrict_probe_sc,
+};
+
+static int intel_cln_plat_cross_hill_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = platform_driver_register(&gpio_restrict_pdriver_nc);
+ if (ret)
+ return ret;
+
+ return platform_driver_register(&gpio_restrict_pdriver_sc);
+}
+
+static int intel_cln_plat_cross_hill_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver cln_cross_hill_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_cross_hill_probe,
+ .remove = intel_cln_plat_cross_hill_remove,
+};
+
+module_platform_driver(cln_cross_hill_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Cross Hill BSP Data");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_plat_data.c b/arch/x86/platform/cln/intel_cln_plat_data.c
new file mode 100644
index 0000000..12e6b27
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_plat_data.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <asm/io.h>
+#include <linux/crc32.h>
+#include <linux/crc32c.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/clanton.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+
+#define PREFIX "CLN-PLT: "
+#define DRIVER_NAME "cln-plat"
+#define PLAT_MAGIC 0x54414450 /* PDAT */
+#define DESC_LEN 0x0A
+#define MAC_STRLEN 20
+#define MAC_LEN 6
+
+struct cln_plat_dat_hdr {
+ uint32_t magic;
+ uint32_t length;
+ uint32_t crc32;
+};
+
+struct cln_plat_data {
+ uint16_t plat_id;
+ uint16_t length;
+ uint8_t desc[DESC_LEN];
+ uint16_t version;
+};
+
+struct cln_bsp_reg {
+ struct platform_device pdev;
+ cln_plat_id_t id;
+};
+
+static struct cln_bsp_reg bsp_data [] = {
+ {
+ .pdev.name = "cln-plat-clanton-peak",
+ .pdev.id = -1,
+ .id = CLANTON_PEAK,
+ },
+ {
+ .pdev.name = "cln-plat-kips-bay",
+ .pdev.id = -1,
+ .id = KIPS_BAY,
+ },
+ {
+ .pdev.name = "cln-plat-cross-hill",
+ .pdev.id = -1,
+ .id = CROSS_HILL,
+ },
+ {
+ .pdev.name = "cln-plat-clanton-hill",
+ .pdev.id = -1,
+ .id = CLANTON_HILL,
+ },
+ {
+ .pdev.name = "cln-plat-izmir",
+ .pdev.id = -1,
+ .id = IZMIR,
+ },
+
+};
+
+/**
+ * struct cln_plat_data_list
+ *
+ * Structure to hold a linked list of platform data refs
+ */
+struct cln_plat_data_list {
+ char name[DESC_LEN+1];
+ struct cln_plat_data * plat_data;
+ struct kobj_attribute plat_attr;
+ struct list_head list;
+};
+
+static char __iomem * plat_data;
+static char * plat_bin_name = "pdat_bin";
+static unsigned int plat_bin_size;
+static struct cln_plat_dat_hdr * plat_hdr;
+static struct list_head entry_list;
+
+/**
+ * intel_cln_plat_sysfs_show_bin
+ *
+ * Generic show routine for any of the sysfs entries of this module
+ */
+static ssize_t intel_cln_plat_sysfs_show_bin(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ ssize_t plen = plat_bin_size;
+ if( plen > PAGE_SIZE )
+ plen = PAGE_SIZE;
+
+ memcpy(buf, plat_data, plen);
+ return plen;
+}
+
+/**
+ * intel_cln_plat_sysfs_show
+ *
+ * Generic show routine for any of the sysfs entries of this module
+ */
+static ssize_t intel_cln_plat_sysfs_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ unsigned char * data;
+ char fmt[0x20];
+ struct cln_plat_data_list * plat_item_list;
+ ssize_t plen = 0;
+
+ list_for_each_entry(plat_item_list, &entry_list, list){
+ if ( attr == &plat_item_list->plat_attr ){
+
+ /* Derive length */
+ plen = plat_item_list->plat_data->length;
+ if (unlikely(plen > PAGE_SIZE))
+ plen = PAGE_SIZE;
+
+ /* Hook data */
+ data =(char*)(plat_item_list->plat_data);
+ data += +sizeof(struct cln_plat_data);
+
+ /* Enumrate return */
+ switch (plat_item_list->plat_data->plat_id){
+ case PLAT_DATA_ID:
+ case PLAT_DATA_SN:
+ snprintf(fmt, sizeof(fmt), "0x%%0%dx\n",
+ plen*2);
+ return sprintf(buf, fmt, *(int16_t*)data);
+ case PLAT_DATA_MAC0:
+ case PLAT_DATA_MAC1:
+ if (unlikely(plen != MAC_LEN)){
+ return sprintf(buf, "invalid mac\n");
+ }
+ return snprintf(buf, MAC_STRLEN,
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ data[0], data[1], data[2], data[3],
+ data[4], data[5]);
+ default:
+ /* Treat as string data */
+ return snprintf(buf, plen, "%s", data);
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * intel_cln_plat_cleanup
+ *
+ * Generic cleanup code for the platform data interface
+ *
+ */
+static void intel_cln_plat_cleanup (void)
+{
+ extern struct kobject * board_data_kobj;
+ struct cln_plat_data_list * plat_item_list;
+
+ if (plat_data != NULL){
+ iounmap(plat_data);
+ plat_data = NULL;
+ }
+
+ list_for_each_entry(plat_item_list, &entry_list, list){
+ sysfs_remove_file(board_data_kobj,
+ &plat_item_list->plat_attr.attr);
+ kfree(plat_item_list);
+ }
+}
+
+/**
+ * intel_cln_plat_get_desc_len
+ *
+ * @param desc: Pointer to desc string
+ * @return len on success < 0 failure
+ *
+ * Function called to get a bounds checked desc field from platfrom data
+ *
+ */
+static int intel_cln_plat_get_desc_len (char * desc)
+{
+ int len = 0;
+ if (desc == NULL){
+ return -EINVAL;
+ }
+
+ for(; *desc != '\0' && len < DESC_LEN; desc++, len++);
+ return len;
+}
+
+/**
+ * intel_cln_plat_probe
+ *
+ * @param pdev: Pointer to platform device
+ * @return 0 success < 0 failure
+ *
+ * Function called to probe platform device "cln-plat"
+ *
+ */
+static int intel_cln_plat_probe(struct platform_device *pdev)
+{
+ char __iomem * end_addr = NULL;
+ char __iomem * data = NULL;
+ cln_plat_id_t id = CLANTON_PLAT_UNDEFINED;
+ extern struct kobject * board_data_kobj;
+ struct cln_plat_data * plat_item = NULL;
+ struct cln_plat_data_list * plat_item_list = NULL;
+ u32 crc = 0;
+ int ret = 0, i = 0;
+
+ INIT_LIST_HEAD(&entry_list);
+ plat_hdr = ioremap(pdev->resource->start, resource_size(pdev->resource));
+ end_addr = (char*)plat_hdr + resource_size(pdev->resource);
+ plat_data = (char*)plat_hdr;
+ if (!plat_hdr)
+ return -ENODEV;
+
+ /* Verify header magic */
+ if (plat_hdr->magic != PLAT_MAGIC){
+ pr_err(PREFIX"Expected magic 0x%08x read 0x%08lx\n",
+ PLAT_MAGIC, (unsigned long)plat_hdr->magic);
+ }
+
+ /* Validate length is sane */
+ if ((char*)plat_hdr + plat_hdr->length > end_addr ||
+ plat_hdr->length < sizeof(struct cln_plat_data)){
+ pr_err(PREFIX"Invalid length 0x%08lx\n",
+ (unsigned long)plat_hdr->length);
+ return -ENODEV;
+ }
+
+ /* Point to real end addr */
+ end_addr = (char*)plat_hdr +
+ sizeof(struct cln_plat_dat_hdr) + plat_hdr->length;
+ plat_bin_size = end_addr - plat_data;
+
+ /* Get pointer to start of data */
+ plat_item = (struct cln_plat_data*)(plat_hdr+1);
+ data = ((char*)(plat_item)+sizeof(struct cln_plat_data));
+
+ /* Validate CRC32 */
+ crc = ~crc32(0xFFFFFFFF, plat_item, plat_hdr->length);
+ if (crc != plat_hdr->crc32){
+ pr_err(PREFIX"CRC 0x%08x header indicates 0x%08x - fatal!\n",
+ crc, plat_hdr->crc32);
+ return -EFAULT;
+ }
+
+ /* /sys/firmware/board_data/plat_bin - dump entire platform binary */
+ plat_item_list = kzalloc(sizeof(struct cln_plat_data_list),
+ GFP_KERNEL);
+ if (unlikely(plat_item_list == NULL)) {
+ pr_err("kzalloc fail !\n");
+ intel_cln_plat_cleanup();
+ return -ENOMEM;
+ }
+ sysfs_attr_init(&plat_item_list->plat_attr.attr);
+ plat_item_list->plat_attr.attr.name = plat_bin_name;
+ plat_item_list->plat_attr.attr.mode = 0644;
+ plat_item_list->plat_attr.show = intel_cln_plat_sysfs_show_bin;
+
+ ret = sysfs_create_file(board_data_kobj,
+ &plat_item_list->plat_attr.attr);
+ if (unlikely(ret != 0)){
+ intel_cln_plat_cleanup();
+ pr_err("failed to create sysfs entry\n");
+ return ret;
+ }
+
+ /* Add to list */
+ list_add(&plat_item_list->list, &entry_list);
+
+ /* Iterate through each entry - add sysfs entry as appropriate */
+ while ( (char*)plat_item < end_addr){
+
+ /* Bounds check */
+ if (data + plat_item->length > end_addr){
+ pr_err(PREFIX"Data 0x%p over-runs max-addr 0x%p\n",
+ data, end_addr);
+ break;
+ }
+
+ /* Extract data */
+ switch(plat_item->plat_id){
+ case PLAT_DATA_ID:
+ id = *((uint16_t*)data);
+ pr_info(PREFIX"Clanton Platform ID = %d\n", id);
+ break;
+ case PLAT_DATA_SN:
+ case PLAT_DATA_MAC0:
+ case PLAT_DATA_MAC1:
+ break;
+ default:
+ /* Unknown identifier */
+ break;
+ }
+
+ plat_item_list = kzalloc(sizeof(struct cln_plat_data_list),
+ GFP_KERNEL);
+ if (unlikely(plat_item_list == NULL)) {
+ pr_err("kzalloc fail !\n");
+ intel_cln_plat_cleanup();
+ return -ENOMEM;
+ }
+
+ /* Get name of entity */
+ i = intel_cln_plat_get_desc_len(plat_item->desc);
+ if (i <= 0){
+ pr_err("desc len is %d!\n", i);
+ intel_cln_plat_cleanup();
+ return i;
+ }
+
+ memcpy(plat_item_list->name, plat_item->desc, i);
+ plat_item_list->plat_data = plat_item;
+
+ sysfs_attr_init(&plat_item_list->plat_attr.attr);
+ plat_item_list->plat_attr.attr.name = plat_item_list->name;
+ plat_item_list->plat_attr.attr.mode = 0644;
+ plat_item_list->plat_attr.show = intel_cln_plat_sysfs_show;
+
+ ret = sysfs_create_file(board_data_kobj,
+ &plat_item_list->plat_attr.attr);
+ if (unlikely(ret != 0)){
+ intel_cln_plat_cleanup();
+ pr_err("failed to create sysfs entry\n");
+ return ret;
+ }
+
+ /* Add to list */
+ list_add(&plat_item_list->list, &entry_list);
+
+ /* Next */
+ plat_item = (struct cln_plat_data*)
+ (((char*)plat_item) + plat_item->length + sizeof(struct cln_plat_data));
+ data = ((char*)(plat_item) + sizeof(struct cln_plat_data));
+ }
+
+ /* Register BSP enabling platform code */
+ for (i = 0; i < sizeof(bsp_data)/sizeof(struct cln_bsp_reg); i++){
+ if (bsp_data[i].id == id){
+ platform_device_register(&bsp_data[i].pdev);
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * intel_cln_plat_remove
+ *
+ * @param pdev: Pointer to platform device
+ * @return 0 success < 0 failure
+ *
+ * Function called to remove the platfrom device from kernel space
+ *
+ */
+static int intel_cln_plat_remove(struct platform_device *pdev)
+{
+ intel_cln_plat_cleanup();
+ return 0;
+}
+
+static struct platform_driver cln_plat_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_probe,
+ .remove = intel_cln_plat_remove,
+};
+
+module_platform_driver(cln_plat_driver);
+
+/**
+ * intel_cln_get_id
+ *
+ * @return platform id on success or < CLANTON_PLAT_UNDEFINED on error
+ *
+ * Function called to get platform id
+ *
+ */
+cln_plat_id_t intel_cln_plat_get_id(void)
+{
+ unsigned char * data;
+ struct cln_plat_data_list * plat_item_list;
+
+ if (plat_data == NULL)
+ return CLANTON_PLAT_UNDEFINED;
+
+ list_for_each_entry(plat_item_list, &entry_list, list){
+
+ /* Enumrate return */
+ if(plat_item_list->plat_data->plat_id == PLAT_DATA_ID){
+
+ /* Hook data */
+ data =(char*)(plat_item_list->plat_data);
+ data += +sizeof(struct cln_plat_data);
+
+ /* Return payload */
+ return *(int16_t*)data;
+ }
+ }
+ return CLANTON_PLAT_UNDEFINED;
+}
+EXPORT_SYMBOL(intel_cln_plat_get_id);
+
+/**
+ * intel_cln_plat_get_mac
+ *
+ * @param id: Index of MAC address to find
+ * @param mac: Output parameter for mac address
+ *
+ * @return 0 success < 0 failure
+ *
+ * Function called to remove the platfrom device from kernel space
+ *
+ */
+int intel_cln_plat_get_mac(plat_dataid_t id, char * mac)
+{
+ unsigned char * data;
+ unsigned int plen = 0;
+ struct cln_plat_data_list * plat_item_list;
+
+ if ((id != PLAT_DATA_MAC0 && id != PLAT_DATA_MAC1) || mac == NULL){
+ pr_err("invalid input id %d mac %p\n", id, mac);
+ return -EINVAL;
+ }
+
+ list_for_each_entry(plat_item_list, &entry_list, list){
+ if(plat_item_list->plat_data->plat_id == id){
+
+ /* Derive length */
+ plen = plat_item_list->plat_data->length;
+ if (unlikely(plen != MAC_LEN)){
+ pr_err("%s mac len invalid!\n", __func__);
+ return -ENODEV;
+ }
+
+ /* Hook data */
+ data =(char*)(plat_item_list->plat_data);
+ data += +sizeof(struct cln_plat_data);
+
+ /* Good to go */
+ memcpy(mac, data, MAC_LEN);
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+EXPORT_SYMBOL(intel_cln_plat_get_mac);
+
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Intel Clanton SPI Data API");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_plat_izmir.c b/arch/x86/platform/cln/intel_cln_plat_izmir.c
new file mode 100644
index 0000000..e8fefc0
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_plat_izmir.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c/at24.h>
+
+#define DRIVER_NAME "cln-plat-izmir"
+#define GPIO_RESTRICT_NAME "cln-gpio-restrict-sc"
+#define LPC_SCH_SPINAME "spi-lpc-sch"
+
+#define CLN_SPI_MAX_CLK_DEFAULT 5000000
+
+/******************************************************************************
+ * Analog Devices AD7298 SPI Device Platform Data
+ ******************************************************************************/
+#include "linux/platform_data/ad7298.h"
+
+/* Maximum input voltage allowed for each ADC input, in milliVolts */
+#define AD7298_MAX_EXT_VIN 5000
+
+static const struct ad7298_platform_data ad7298_platform_data = {
+ .ext_ref = false,
+ .ext_vin_max = { AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN }
+};
+
+static struct at24_platform_data at24_platform_data = {
+ .byte_len = (11 * 1024),
+ .page_size = 1,
+ .flags = AT24_FLAG_ADDR16,
+};
+
+/******************************************************************************
+ * Intel Izmir i2c clients
+ ******************************************************************************/
+static struct i2c_board_info __initdata izmir_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("cy8c9540a", 0x20),
+ },
+ {
+ I2C_BOARD_INFO("at24", 0x50),
+ .platform_data = &at24_platform_data,
+ },
+};
+
+/******************************************************************************
+ * Intel Clanton SPI Controller Data
+ ******************************************************************************/
+static struct pxa2xx_spi_chip cln_ffrd_spi_0_cs_0 = {
+ .gpio_cs = 8,
+};
+
+static struct pxa2xx_spi_chip cln_ffrd_spi_1_cs_0 = {
+ .gpio_cs = 10,
+};
+
+#define LPC_SCH_SPI_BUS_ID 0x03
+
+static struct platform_device lpc_sch_spi = {
+ .name = "spi-lpc-sch-drv",
+ .id = LPC_SCH_SPI_BUS_ID,
+};
+
+/* TODO: extract this data from layout.conf encoded in flash */
+struct mtd_partition ilb_partitions [] = {
+ {
+ .name = "grub",
+ .size = 4096,
+ .offset = 0,
+ },
+ {
+ .name = "grub.conf",
+ .size = 0xA00,
+ .offset = 0x50500,
+ },
+ {
+ .name = "layout.conf",
+ .size = 4096,
+ .offset = 0x708000,
+ },
+ {
+ .name = "sketch",
+ .size = 0x40000,
+ .offset = 0x750000,
+ },
+ {
+ .name = "raw",
+ .size = 8192000,
+ .offset = 0,
+
+ },
+};
+
+static struct flash_platform_data ilb_flash = {
+ .type = "s25fl064k",
+ .parts = ilb_partitions,
+ .nr_parts = ARRAY_SIZE(ilb_partitions),
+};
+
+static struct spi_board_info spi_onboard_devs[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &ilb_flash,
+ .bus_num = LPC_SCH_SPI_BUS_ID,
+ .chip_select = 0,
+ },
+ {
+ .modalias = "ad7298",
+ .max_speed_hz = CLN_SPI_MAX_CLK_DEFAULT,
+ .platform_data = &ad7298_platform_data,
+ .mode = SPI_MODE_2,
+ .bus_num = 0,
+ .chip_select = 0,
+ .controller_data = &cln_ffrd_spi_0_cs_0,
+ },
+ {
+ .modalias = "spidev",
+ .chip_select = 0,
+ .controller_data = &cln_ffrd_spi_1_cs_0,
+ .max_speed_hz = 50000000,
+ .bus_num = 1,
+ },
+};
+
+/**
+ * intel_cln_spi_add_onboard_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers onboard SPI device(s) present on the Izmir platform
+ */
+static int intel_cln_spi_add_onboard_devs(void)
+{
+
+ return spi_register_board_info(spi_onboard_devs,
+ ARRAY_SIZE(spi_onboard_devs));
+}
+
+
+/**
+ * intel_cln_gpio_restrict_probe
+ *
+ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
+ * GPIOs are never released nor accessed by this driver.
+ */
+static int intel_cln_gpio_restrict_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = intel_cln_spi_add_onboard_devs();
+
+ return ret;
+}
+
+static struct platform_driver gpio_restrict_pdriver = {
+ .driver = {
+ .name = GPIO_RESTRICT_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_gpio_restrict_probe,
+};
+
+/* LPC SPI */
+static int intel_cln_plat_izmir_lpcspi_probe(struct platform_device *pdev)
+{
+ lpc_sch_spi.resource = pdev->resource;
+ return platform_device_register(&lpc_sch_spi);
+}
+
+static struct platform_driver intel_cln_plat_izmir_lpcspi_pdriver = {
+ .driver = {
+ .name = LPC_SCH_SPINAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_izmir_lpcspi_probe,
+};
+
+static int intel_cln_plat_izmir_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ /* i2c */
+ ret = i2c_register_board_info(0, izmir_i2c_board_info,
+ ARRAY_SIZE(izmir_i2c_board_info));
+ if (ret) {
+ goto end;
+ }
+
+ /* gpio */
+ ret = platform_driver_register(&gpio_restrict_pdriver);
+ if (ret)
+ goto end;
+
+ /* legacy SPI */
+ ret = platform_driver_register(&intel_cln_plat_izmir_lpcspi_pdriver);
+ if (ret)
+ goto end;
+
+
+end:
+ return ret;
+}
+
+static int intel_cln_plat_izmir_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver cln_izmir_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_izmir_probe,
+ .remove = intel_cln_plat_izmir_remove,
+};
+
+module_platform_driver(cln_izmir_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Izmir BSP Data");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_plat_kips_bay.c b/arch/x86/platform/cln/intel_cln_plat_kips_bay.c
new file mode 100644
index 0000000..11e1613
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_plat_kips_bay.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Legacy Platform Data Layout.conf accessor
+ *
+ * Simple Legacy SPI flash access layer
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "cln-plat-kips-bay"
+#define GPIO_RESTRICT_NAME "cln-gpio-restrict-sc"
+
+#define CLN_SPI_MAX_CLK_DEFAULT 5000000
+
+static int gpio_cs = 1;
+
+module_param(gpio_cs, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(gpio_cs, "Enable GPIO chip-select for SPI channel 1");
+
+
+/******************************************************************************
+ * Analog Devices AD7298 SPI Device Platform Data
+ ******************************************************************************/
+#include "linux/platform_data/ad7298.h"
+
+/* Maximum input voltage allowed for each ADC input, in milliVolts */
+#define AD7298_MAX_EXT_VIN 5000
+
+static const struct ad7298_platform_data ad7298_platform_data = {
+ .ext_ref = false,
+ .ext_vin_max = { AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN,
+ AD7298_MAX_EXT_VIN, AD7298_MAX_EXT_VIN }
+};
+
+/******************************************************************************
+ * Intel Clanton SPI Controller Data
+ ******************************************************************************/
+static struct pxa2xx_spi_chip cln_ffrd_spi_0_cs_0 = {
+ .gpio_cs = 8,
+};
+
+static struct pxa2xx_spi_chip cln_ffrd_spi_1_cs_0 = {
+ .gpio_cs = 10,
+};
+
+/**
+ * intel_cln_spi_add_onboard_devs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Registers onboard SPI device(s) present on the Kips Bay platform
+ */
+static int intel_cln_spi_add_onboard_devs(void)
+{
+ int ret = 0;
+ struct spi_board_info spi0_onboard_devs[] = {
+ {
+ .modalias = "ad7298",
+ .max_speed_hz = CLN_SPI_MAX_CLK_DEFAULT,
+ .platform_data = &ad7298_platform_data,
+ .mode = SPI_MODE_2,
+ .bus_num = 0,
+ .chip_select = 0,
+ .controller_data = &cln_ffrd_spi_0_cs_0,
+ }
+ };
+ struct spi_board_info spi1_onboard_devs_gpiocs[] = {
+ {
+ .modalias = "spidev",
+ .chip_select = 0,
+ .controller_data = NULL,
+ .max_speed_hz = 50000000,
+ .bus_num = 1,
+ .controller_data = &cln_ffrd_spi_1_cs_0,
+ },
+ };
+ struct spi_board_info spi1_onboard_devs[] = {
+ {
+ .modalias = "spidev",
+ .chip_select = 0,
+ .controller_data = NULL,
+ .max_speed_hz = 50000000,
+ .bus_num = 1,
+ },
+ };
+
+ ret = spi_register_board_info(spi0_onboard_devs,
+ ARRAY_SIZE(spi0_onboard_devs));
+ if (ret)
+ return ret;
+
+ if (gpio_cs)
+ return spi_register_board_info(spi1_onboard_devs_gpiocs,
+ ARRAY_SIZE(spi1_onboard_devs_gpiocs));
+ else
+ return spi_register_board_info(spi1_onboard_devs,
+ ARRAY_SIZE(spi1_onboard_devs));
+}
+
+
+/**
+ * intel_cln_gpio_restrict_probe
+ *
+ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
+ * GPIOs are never released nor accessed by this driver.
+ */
+static int intel_cln_gpio_restrict_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = intel_cln_spi_add_onboard_devs();
+
+ return ret;
+}
+
+static struct platform_driver gpio_restrict_pdriver = {
+ .driver = {
+ .name = GPIO_RESTRICT_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_gpio_restrict_probe,
+};
+
+static int intel_cln_plat_kips_bay_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = platform_driver_register(&gpio_restrict_pdriver);
+
+ return ret;
+}
+
+static int intel_cln_plat_kips_bay_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver cln_kips_bay_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_plat_kips_bay_probe,
+ .remove = intel_cln_plat_kips_bay_remove,
+};
+
+module_platform_driver(cln_kips_bay_driver);
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("Kips Bay BSP Data");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/arch/x86/platform/cln/intel_cln_sb.c b/arch/x86/platform/cln/intel_cln_sb.c
new file mode 100644
index 0000000..ef3714d
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_sb.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton side-band driver
+ *
+ * Thread-safe sideband read/write routine.
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2012
+ */
+
+#include <linux/errno.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+
+#define INTEL_CLN_SB_CMD_ADDR (0x000000D0)
+#define INTEL_CLN_SB_DATA_ADDR (0x000000D4)
+
+#define INTEL_CLN_SB_MCR_SHIFT (24)
+#define INTEL_CLN_SB_PORT_SHIFT (16)
+#define INTEL_CLN_SB_REG_SHIFT (8)
+#define INTEL_CLN_SB_BYTEEN (0xF0) /* enable all 32 bits */
+
+/* Simple structure for module */
+struct intel_cln_sb_dev{
+ struct pci_dev * pdev;
+ spinlock_t slock;
+ u8 initialized;
+};
+
+static struct intel_cln_sb_dev sb_dev = {
+ .initialized = 0
+};
+
+/* Dependant drivers */
+struct platform_device pdev [] = {
+ {
+ .name = "intel-cln-esram",
+ },
+ {
+ .name = "intel-cln-imr",
+ },
+ {
+ .name = "intel-cln-ecc",
+ },
+ {
+ .name = "intel-cln-thrm",
+ },
+};
+
+/**
+ * intel_cln_sb_read_reg
+ *
+ * @param cln_sb_id: Sideband identifier
+ * @param command: Command to send to destination identifier
+ * @param reg: Target register w/r to cln_sb_id
+ * @return nothing
+ *
+ * Utility function to allow thread-safe read of side-band
+ * command - can be different read op-code types - which is why we don't
+ * hard-code this value directly into msg
+ */
+void intel_cln_sb_read_reg(cln_sb_id id, u8 cmd, u8 reg, u32 *data, u8 lock)
+{
+ u32 msg = (cmd << INTEL_CLN_SB_MCR_SHIFT) |
+ ((id << INTEL_CLN_SB_PORT_SHIFT) & 0xFF0000)|
+ ((reg << INTEL_CLN_SB_REG_SHIFT) & 0xFF00)|
+ INTEL_CLN_SB_BYTEEN;
+
+ if(data == NULL)
+ return;
+
+ if (likely(lock == 1)) {
+ spin_lock(&sb_dev.slock);
+ }
+
+ pci_write_config_dword(sb_dev.pdev, INTEL_CLN_SB_CMD_ADDR, msg);
+ pci_read_config_dword(sb_dev.pdev, INTEL_CLN_SB_DATA_ADDR, data);
+
+ if(likely(lock == 1)){
+ spin_unlock(&sb_dev.slock);
+ }
+
+}
+EXPORT_SYMBOL(intel_cln_sb_read_reg);
+
+/**
+ * intel_cln_sb_write_reg
+ *
+ * @param cln_sb_id: Sideband identifier
+ * @param command: Command to send to destination identifier
+ * @param reg: Target register w/r to cln_sb_id
+ * @return nothing
+ *
+ * Utility function to allow thread-safe write of side-band
+ */
+void intel_cln_sb_write_reg(cln_sb_id id, u8 cmd, u8 reg, u32 data, u8 lock)
+{
+ u32 msg = (cmd << INTEL_CLN_SB_MCR_SHIFT) |
+ ((id << INTEL_CLN_SB_PORT_SHIFT) & 0xFF0000)|
+ ((reg << INTEL_CLN_SB_REG_SHIFT) & 0xFF00)|
+ INTEL_CLN_SB_BYTEEN;
+
+ if(likely(lock == 1)){
+ spin_lock(&sb_dev.slock);
+ }
+
+ pci_write_config_dword(sb_dev.pdev, INTEL_CLN_SB_DATA_ADDR, data);
+ pci_write_config_dword(sb_dev.pdev, INTEL_CLN_SB_CMD_ADDR, msg);
+
+ if(likely(lock == 1)){
+ spin_unlock(&sb_dev.slock);
+ }
+}
+EXPORT_SYMBOL(intel_cln_sb_write_reg);
+
+/**
+ * intel_cln_sb_runfn_lock
+ *
+ * @param fn: Callback function - which requires side-band spinlock and !irq
+ * @param arg: Callback argument
+ * @return 0 on success < 0 on failure
+ *
+ * Runs the given function pointer inside of a call to the local spinlock using
+ * spin_lock_irqsave/spin_unlock_irqrestore. Needed for the eSRAMv1 driver to
+ * guarantee atomicity, but, available to any other user of sideband provided
+ * rules are respected.
+ * Rules:
+ * fn may not sleep
+ * fn may not change the state of irqs
+ */
+int intel_cln_sb_runfn_lock(int (*fn)( void * arg ), void * arg)
+{
+ unsigned long flags = 0;
+ int ret = 0;
+
+ if(unlikely(fn == NULL)){
+ return -EINVAL;
+ }
+
+ /* Get spinlock with IRQs off */
+ spin_lock_irqsave(&sb_dev.slock, flags);
+
+ /* Run function atomically */
+ ret = fn(arg);
+
+ /* Release lock */
+ spin_unlock_irqrestore(&sb_dev.slock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(intel_cln_sb_runfn_lock);
+
+/**
+ * sb_probe
+ *
+ * @param dev: the PCI device matching
+ * @param id: entry in the match table
+ * @return 0
+ *
+ * Callback from PCI layer when dev/vendor ids match.
+ * Sets up necessary resources
+ */
+static int intel_cln_sb_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int i = 0;
+
+ /* Init struct */
+ memset(&sb_dev, 0x00, sizeof(sb_dev));
+
+ /* Hook device */
+ sb_dev.pdev = dev;
+
+ /* Init locking structures */
+ spin_lock_init(&sb_dev.slock);
+
+ /* Set state */
+ sb_dev.initialized = 1;
+
+ /* Register side-band sub-ordinate drivers */
+ for (i = 0; i < sizeof(pdev)/sizeof(struct platform_device); i++){
+ platform_device_register(&pdev[i]);
+ }
+ pr_info("Intel Clanton side-band driver registered\n");
+ return 0;
+}
+
+/**
+ * sb_remove
+ *
+ * @param pdev: PCI device
+ * @return nothing
+ *
+ * Callback from PCI sub-system upon PCI dev removal
+ */
+static void intel_cln_sb_remove(struct pci_dev *pdev)
+{
+}
+
+/* Clanton hardware */
+struct pci_device_id intel_cln_sb_ids[] = {
+ { PCI_VDEVICE(INTEL, 0x0958), 0},
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, intel_cln_sb_ids);
+
+/* PCI callbacks */
+static struct pci_driver intel_cln_sb_driver = {
+ .name = "intel_cln_sb",
+ .id_table = intel_cln_sb_ids,
+ .probe = intel_cln_sb_probe,
+ .remove = intel_cln_sb_remove,
+};
+
+/**
+ * intel_cln_sb_init
+ *
+ * Module entry point
+ */
+static int __init intel_cln_sb_init(void)
+{
+ return pci_register_driver(&intel_cln_sb_driver);
+}
+
+/**
+ * intel_cln_sb_exit
+ *
+ * Module exit
+ */
+static void __exit intel_cln_sb_exit(void)
+{
+ sb_dev.initialized = 0;
+ pci_unregister_driver(&intel_cln_sb_driver);
+}
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Clanton SOC side-band driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* Initialise early since other drivers eSRAM, DRAM ECC and thermal depend */
+device_initcall(intel_cln_sb_init);
+module_exit(intel_cln_sb_exit);
diff --git a/arch/x86/platform/cln/intel_cln_smep_test.c b/arch/x86/platform/cln/intel_cln_smep_test.c
new file mode 100644
index 0000000..16f43db
--- /dev/null
+++ b/arch/x86/platform/cln/intel_cln_smep_test.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/**
+ * intel_cln_smep_test.c
+ *
+ * Simple test module to verify SMEP works as expected on MIA
+ * DO NOT RELEASE THIS FILE OUTSIDE OF CLANTON GROUP
+ * DO NOT ATTEMPT TO UPSTREAM THIS CODE - YOU WILL BE PUBLICLY EMBARRSSED !
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@intel.com>
+ *
+ */
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include <linux/cdev.h>
+#include <linux/crc16.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "intel_cln_smep_test"
+
+/**
+ * struct intel_cln_smep_dev
+ *
+ * Structre to represent module state/data/etc
+ */
+struct intel_cln_smep_test_dev{
+ unsigned int opened;
+ struct platform_device *pldev; /* Platform device */
+ struct cdev cdev;
+ struct mutex open_lock;
+ char * pdata;
+ u32 size;
+};
+
+static struct intel_cln_smep_test_dev smep_test_dev;
+static struct class *smep_test_class;
+static DEFINE_MUTEX(smep_test_mutex);
+static int smep_test_major;
+static char * name = "testmap";
+
+/**
+ * smep_test_ioctl
+ *
+ * Allows user-space to command kernel switch SMEP on/off
+ */
+static long smep_test_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int cr4 = 0;
+
+ cr4 = read_cr4();
+ printk(KERN_INFO "%s entry CR4 is 0x%08x\n", __FUNCTION__, cr4);
+
+ switch(cmd){
+ case 0:
+ printk(KERN_INFO "Switching SMEP off\n");
+ cr4 &= ~X86_CR4_SMEP;
+
+ break;
+ case 1:
+ printk(KERN_INFO "Switching SMEP on\n");
+ cr4 |= X86_CR4_SMEP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Latch value */
+ write_cr4(cr4);
+
+ /* Print contents of CR4 */
+ cr4 = read_cr4();
+ printk(KERN_INFO "%s exit CR4 is 0x%08x\n", __FUNCTION__, cr4);
+
+ return 0;
+}
+
+/**
+ * smep_test_write
+ *
+ * Accepts a buffer from user-space and then tries to execute the contents
+ * Be very careful
+ */
+static ssize_t smep_test_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /*
+ * We assume we are passed a pointer to function of type
+ * void fn(void)
+ */
+ void (*fn)(void) = (void(*))buf;
+ if (count) {
+ printk(KERN_INFO "Will attempt exec %d bytes of ring3 code @ 0x%p\n",
+ count, buf);
+ fn();
+ printk(KERN_INFO "Exec of data @ 0x%p complete\n", buf);
+ }
+ return count;
+}
+
+static int smep_test_open(struct inode *inode, struct file *file)
+{
+ mutex_lock(&smep_test_mutex);
+ nonseekable_open(inode, file);
+
+ if (mutex_lock_interruptible(&smep_test_dev.open_lock)) {
+ mutex_unlock(&smep_test_mutex);
+ return -ERESTARTSYS;
+ }
+
+ if (smep_test_dev.opened) {
+ mutex_unlock(&smep_test_dev.open_lock);
+ mutex_unlock(&smep_test_mutex);
+ return -EINVAL;
+ }
+
+ smep_test_dev.opened++;
+ mutex_unlock(&smep_test_dev.open_lock);
+ mutex_unlock(&smep_test_mutex);
+ return 0;
+}
+
+static int smep_test_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&smep_test_dev.open_lock);
+ smep_test_dev.opened = 0;
+ mutex_unlock(&smep_test_dev.open_lock);
+
+ return 0;
+}
+
+
+
+static const struct file_operations smep_test_file_ops = {
+ .open = smep_test_open,
+ .release = smep_test_release,
+ .unlocked_ioctl = smep_test_ioctl,
+ .write = smep_test_write,
+ .llseek = no_llseek,
+};
+
+
+/**
+ * intel_cln_smep_test_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ *
+ * This driver manages eSRAM on a per-page basis. Therefore if we find block
+ * mode is enabled, or any global, block-level or page-level locks are in place
+ * at module initialisation time - we bail out.
+ */
+static int intel_cln_smep_test_probe(struct platform_device * pdev)
+{
+ int retval = 0;
+ unsigned int minor = 0;
+
+ mutex_init(&smep_test_dev.open_lock);
+ cdev_init(&smep_test_dev.cdev, &smep_test_file_ops);
+ smep_test_dev.cdev.owner = THIS_MODULE;
+
+ retval = cdev_add(&smep_test_dev.cdev, MKDEV(smep_test_major, minor), 1);
+ if (retval) {
+ printk(KERN_ERR "chardev registration failed\n");
+ return -EINVAL;
+ }
+ if (IS_ERR(device_create(smep_test_class, NULL,
+ MKDEV(smep_test_major, minor), NULL,
+ "smeptest%u", minor))){
+ dev_err(&pdev->dev, "can't create device\n");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "%s complete OK - device /dev/smeptest%u\n", __FUNCTION__, minor);
+ return 0;
+
+}
+
+/**
+ * intel_cln_smep_remove
+ *
+ * @return 0 success < 0 failure
+ *
+ * Removes a platform device
+ */
+static int intel_cln_smep_test_remove(struct platform_device * pdev)
+{
+ unsigned int minor = MINOR(smep_test_dev.cdev.dev);
+
+ device_destroy(smep_test_class, MKDEV(smep_test_major, minor));
+ cdev_del(&smep_test_dev.cdev);
+
+ return 0;
+}
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_smep_test_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = intel_cln_smep_test_remove,
+};
+
+/**
+ * intel_cln_smep_init
+ *
+ * @return 0 success < 0 failure
+ *
+ * Module entry point
+ */
+static int __init intel_cln_smep_test_init(void)
+{
+ int retval = 0;
+ dev_t dev;
+
+ smep_test_class = class_create(THIS_MODULE,"cln_smep_test");
+ if (IS_ERR(smep_test_class)) {
+ retval = PTR_ERR(smep_test_class);
+ printk(KERN_ERR "smep_test: can't register earam_test class\n");
+ goto err;
+ }
+
+ retval = alloc_chrdev_region(&dev, 0, 1, "smep_test");
+ if (retval) {
+ printk(KERN_ERR "smep_test: can't register character device\n");
+ goto err_class;
+ }
+ smep_test_major = MAJOR(dev);
+
+ memset(&smep_test_dev, 0x00, sizeof(smep_test_dev));
+ smep_test_dev.pldev = platform_create_bundle(
+ &intel_cln_smep_test_driver, intel_cln_smep_test_probe, NULL, 0, NULL, 0);
+
+ if(IS_ERR(smep_test_dev.pldev)){
+ printk(KERN_ERR "smep_test platform_create_bundle fail!\n");
+ retval = PTR_ERR(smep_test_dev.pldev);
+ goto err_class;
+ }
+
+ return 0;
+
+err_class:
+ class_destroy(smep_test_class);
+err:
+ return retval;
+}
+
+/**
+ * intel_cln_smep_exit
+ *
+ * Module exit
+ */
+static void __exit intel_cln_smep_test_exit(void)
+{
+ platform_device_unregister(smep_test_dev.pldev);
+ platform_driver_unregister(&intel_cln_smep_test_driver);
+}
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Clanton SMEP test");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_init(intel_cln_smep_test_init);
+module_exit(intel_cln_smep_test_exit);
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 6db1cc4..41ac17c 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
-obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
+obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
+obj-$(CONFIG_EFI_CAPSULE) += efi_capsule.o
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c
index d9c1b95..9fd5168 100644
--- a/arch/x86/platform/efi/efi-bgrt.c
+++ b/arch/x86/platform/efi/efi-bgrt.c
@@ -24,19 +24,29 @@ struct bmp_header {
u32 size;
} __packed;
-void efi_bgrt_init(void)
+bool __init efi_bgrt_probe(void)
{
acpi_status status;
- void __iomem *image;
- bool ioremapped = false;
- struct bmp_header bmp_header;
if (acpi_disabled)
- return;
+ return false;
+ bgrt_tab = NULL;
status = acpi_get_table("BGRT", 0,
(struct acpi_table_header **)&bgrt_tab);
if (ACPI_FAILURE(status))
+ return false;
+
+ return true;
+}
+
+void __init efi_bgrt_init(void)
+{
+ void __iomem *image;
+ bool ioremapped = false;
+ struct bmp_header bmp_header;
+
+ if (acpi_disabled || bgrt_tab == NULL)
return;
if (bgrt_tab->header.length < sizeof(*bgrt_tab))
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index e2cd38f..0e22b5f4 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -847,6 +847,7 @@ void __init efi_enter_virtual_mode(void)
u64 end, systab, end_pfn;
void *p, *va, *new_memmap = NULL;
int count = 0;
+ bool bgrt_map;
efi.systab = NULL;
@@ -860,6 +861,11 @@ void __init efi_enter_virtual_mode(void)
return;
}
+ /*
+ * Determine if mapping EFI boot code/data is required for BGRT mapping
+ */
+ bgrt_map = efi_bgrt_probe();
+
/* Merge contiguous regions of the same type and attribute */
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
u64 prev_size;
@@ -889,9 +895,9 @@ void __init efi_enter_virtual_mode(void)
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
md = p;
- if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
- md->type != EFI_BOOT_SERVICES_CODE &&
- md->type != EFI_BOOT_SERVICES_DATA)
+ if (!((md->attribute & EFI_MEMORY_RUNTIME) || (bgrt_map &&
+ (md->type == EFI_BOOT_SERVICES_CODE ||
+ md->type == EFI_BOOT_SERVICES_DATA))))
continue;
size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/arch/x86/platform/efi/efi_capsule.c b/arch/x86/platform/efi/efi_capsule.c
new file mode 100644
index 0000000..d329d6d
--- /dev/null
+++ b/arch/x86/platform/efi/efi_capsule.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+
+#include <asm/cln.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/efi.h>
+
+#define DRIVER_NAME "efi_capsule_update"
+#define PFX "efi-capsupdate: "
+#define MAX_PATH 256
+#define MAX_CHUNK PAGE_SIZE
+#define CSH_HDR_SIZE 0x400
+
+typedef struct {
+ u64 length;
+ union {
+ u64 data_block;
+ u64 continuation_pointer;
+ };
+} efi_blk_desc_t;
+
+static struct kobject * efi_capsule_kobj;
+static struct list_head sg_list;
+static char fpath[MAX_PATH];
+static int csh_jump = CSH_HDR_SIZE; /* Clanton EDK wants CSH jump */
+
+/**
+ * efi_capsule_trigger_update
+ *
+ * Trigger the EFI capsule update
+ */
+static int efi_capsule_trigger_update(void)
+{
+ struct file *fp = NULL;
+ mm_segment_t old_fs = get_fs();
+ int ret = 0;
+ u32 nblocks = 0, i = 0, total_size = 0, data_len = 0, offset = 0;
+ efi_capsule_header_t *chdr = NULL;
+ efi_blk_desc_t * desc_block = NULL;
+ u8 ** data = NULL;
+
+ set_fs (KERNEL_DS);
+ fp = filp_open(fpath, O_RDONLY, 0);
+
+ /* Sanity check input */
+ if (IS_ERR(fp)|| fp->f_op == NULL ||fp->f_op->read == NULL ||
+ fp->f_dentry->d_inode->i_size == 0){
+ pr_err(PFX"file open [%s] error!\n", fpath);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Determine necessary sizes */
+ nblocks = (fp->f_dentry->d_inode->i_size/MAX_CHUNK) + 2;
+ total_size = fp->f_dentry->d_inode->i_size;
+
+ pr_info(PFX "nblocks %d total_size %d\n", nblocks, total_size);
+
+ /* Allocate array of descriptor blocks + 1 for terminator */
+ desc_block = (efi_blk_desc_t*)kzalloc(nblocks * sizeof(efi_blk_desc_t), GFP_KERNEL);
+ if (desc_block == NULL){
+ pr_info(PFX"%s failed to allocate %d blocks\n", __func__, nblocks);
+ ret = -ENOMEM;
+ goto done_close;
+ }
+
+ pr_info(PFX"File %s size %u descriptor blocks %u\n",
+ fpath, total_size, nblocks);
+
+ data = kmalloc(nblocks, GFP_KERNEL);
+ if (data == NULL){
+ ret = -ENOMEM;
+ pr_info("Failed to allocate %d bytes\n", nblocks);
+ goto done;
+ }
+
+ for (i = 0; i < nblocks; i++){
+ data[i] = kmalloc(MAX_CHUNK, GFP_KERNEL);
+ if (data[i] == NULL){
+ ret = -ENOMEM;
+ pr_info("Alloc fail %d bytes entry %d\n",
+ nblocks, i);
+ goto done;
+ }
+
+ }
+
+ /* Read in data */
+ for (i = 0; i < nblocks && offset < total_size; i++){
+ /* Determine read len */
+ data_len = offset < total_size - MAX_CHUNK ?
+ MAX_CHUNK : total_size - offset;
+ ret = fp->f_op->read(fp, data[i], data_len, &fp->f_pos);
+ if (ret < 0){
+ pr_err(PFX"Error reading @ data %u\n", offset);
+ ret = -EIO;
+ goto done;
+ }
+ offset += data_len;
+
+ /* Sanity check */
+ if (i >= nblocks){
+ pr_err(PFX"%s Driver bug line %d\n", __func__, __LINE__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Validate header as appropriate */
+ if (chdr == NULL){
+ chdr = (efi_capsule_header_t*)&data[i][csh_jump];
+ desc_block[i].data_block = __pa(&data[i][csh_jump]);
+ desc_block[i].length = data_len - csh_jump;
+ pr_info(PFX"hdr offset in file %d bytes\n", csh_jump);
+ pr_info(PFX"hdr size %u flags 0x%08x imagesize 0x%08x\n",
+ chdr->headersize, chdr->flags, chdr->imagesize);
+
+ }else{
+ desc_block[i].data_block = __pa(&data[i][0]);
+ desc_block[i].length = data_len;
+ }
+
+ pr_info(PFX "block %d length %u data @ phys 0x%08x\n",
+ i, (int)desc_block[i].length,
+ (unsigned int)desc_block[i].data_block);
+ }
+
+ if (i > nblocks-1){
+ pr_err(PFX"%s Used block %d expected %d !\n", __func__, i, nblocks-1);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ pr_info(PFX"submitting capsule to EDKII firmware\n");
+
+ ret = efi.update_capsule(&chdr, 1, __pa(desc_block));
+ if(ret != EFI_SUCCESS) {
+ pr_err(PFX"submission fail err=0x%08x\n", ret);
+ }else{
+ pr_info(PFX"submission success\n");
+ ret = 0;
+ }
+
+ if (chdr != NULL && chdr->flags & 0x10000){
+ pr_info(PFX"capsule persist across S3 skipping capsule free\n");
+ goto done_close;
+ }
+done:
+ for (i = 0; i < nblocks; i++){
+ if (data && data[i])
+ kfree(data[i]);
+ }
+ if (data)
+ kfree(data);
+
+ if (desc_block != NULL)
+ kfree(desc_block);
+done_close:
+ if (!IS_ERR(fp))
+ filp_close(fp, NULL);
+
+ set_fs (old_fs);
+ return ret;
+}
+
+/**
+ * efi_capsule_csh_jump
+ *
+ * sysfs callback used to show current path
+ */
+static ssize_t efi_capsule_csh_jump_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, sizeof(fpath), "%d\n", csh_jump > 0);
+}
+
+/**
+ * efi_capsule_path_store
+ *
+ * sysfs callback used to set a new capsule path
+ */
+static ssize_t efi_capsule_csh_jump_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (buf != NULL && buf[0] == '0')
+ csh_jump = 0;
+ else
+ csh_jump = CSH_HDR_SIZE;
+ return count;
+}
+
+static struct kobj_attribute efi_capsule_csh_jump_attr =
+ __ATTR(csh_jump, 0644, efi_capsule_csh_jump_show, efi_capsule_csh_jump_store);
+
+/**
+ * efi_capsule_path_show
+ *
+ * sysfs callback used to show current path
+ */
+static ssize_t efi_capsule_path_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, sizeof(fpath), fpath);
+}
+
+/**
+ * efi_capsule_path_store
+ *
+ * sysfs callback used to set a new capsule path
+ */
+static ssize_t efi_capsule_path_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (count > MAX_PATH-1)
+ return -EINVAL;
+
+ memset(fpath, 0x00, sizeof(fpath));
+ memcpy(fpath, buf, count);
+
+ return count;
+}
+
+static struct kobj_attribute efi_capsule_path_attr =
+ __ATTR(capsule_path, 0644, efi_capsule_path_show, efi_capsule_path_store);
+
+/**
+ * efi_capsule_update_store
+ *
+ * sysfs callback used to initiate update
+ */
+static ssize_t efi_capsule_update_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{ int ret = 0;
+
+ ret = efi_capsule_trigger_update();
+ return ret == 0 ? count : ret;
+}
+
+static struct kobj_attribute efi_capsule_update_attr =
+ __ATTR(capsule_update, 0644, NULL, efi_capsule_update_store);
+
+#define SYSFS_ERRTXT "Error adding sysfs entry!\n"
+/**
+ * intel_cln_capsule_update_init
+ *
+ * @return 0 success < 0 failure
+ *
+ * Module entry point
+ */
+static int __init efi_capsule_update_init(void)
+{
+ int retval = 0;
+ extern struct kobject * firmware_kobj;
+
+ INIT_LIST_HEAD(&sg_list);
+
+ /* efi_capsule_kobj subordinate of firmware @ /sys/firmware/efi */
+ efi_capsule_kobj = kobject_create_and_add("efi", firmware_kobj);
+ if (!efi_capsule_kobj) {
+ pr_err(PFX"kset create error\n");
+ retval = -ENODEV;
+ goto err;
+ }
+
+ if(sysfs_create_file(efi_capsule_kobj, &efi_capsule_path_attr.attr)) {
+ pr_err(PFX SYSFS_ERRTXT);
+ retval = -ENODEV;
+ goto err;
+ }
+ if(sysfs_create_file(efi_capsule_kobj, &efi_capsule_update_attr.attr)) {
+ pr_err(PFX SYSFS_ERRTXT);
+ retval = -ENODEV;
+ goto err;
+
+ }
+ if(sysfs_create_file(efi_capsule_kobj, &efi_capsule_csh_jump_attr.attr)) {
+ pr_err(PFX SYSFS_ERRTXT);
+ retval = -ENODEV;
+ goto err;
+
+ }
+
+err:
+ return retval;
+}
+
+/**
+ * intel_cln_esram_exit
+ *
+ * Module exit
+ */
+static void __exit efi_capsule_update_exit(void)
+{
+}
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
+MODULE_DESCRIPTION("EFI Capsule Update driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_init(efi_capsule_update_init);
+module_exit(efi_capsule_update_exit);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 03243d4..3ce8454 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -420,8 +420,8 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
* code. There's no locking restriction.
*/
struct device *class_find_device(struct class *class, struct device *start,
- void *data,
- int (*match)(struct device *, void *))
+ const void *data,
+ int (*match)(struct device *, const void *))
{
struct class_dev_iter iter;
struct device *dev;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index a235085..dda0c7f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1617,9 +1617,9 @@ struct device *device_create(struct class *class, struct device *parent,
}
EXPORT_SYMBOL_GPL(device_create);
-static int __match_devt(struct device *dev, void *data)
+static int __match_devt(struct device *dev, const void *data)
{
- dev_t *devt = data;
+ const dev_t *devt = data;
return dev->devt == *devt;
}
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c1218..427050f 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -34,18 +34,46 @@ if DMADEVICES
comment "DMA Devices"
config INTEL_MID_DMAC
+ tristate "Intel DMAC Moorsetown/Medfield/Clanton DMA controllers"
+ depends on X86
+ default n
+ help
+ Enable support for the Intel(R) MID/Clanton DMA engine present
+ in Intel MID chipsets and Clanton SOC devices
+
+ Say Y here if you have such a chipset.
+
+ If unsure, say N.
+
+if INTEL_MID_DMAC
+
+config INTEL_MID_PCI
tristate "Intel MID DMA support for Peripheral DMA controllers"
- depends on PCI && X86
+ depends on X86 && PCI
select DMA_ENGINE
default n
help
Enable support for the Intel(R) MID DMA engine present
- in Intel MID chipsets.
+ in Intel MID chipsets
Say Y here if you have such a chipset.
If unsure, say N.
+config INTEL_CLN_DMAC
+ tristate "Intel CLN DMA support for Peripheral DMA controllers"
+ depends on PCI && X86 && INTEL_CLN_SOC
+ default n
+ help
+ Enable support for the Intel(R) Clanton DMA engine present
+ in Intel Clanton DMA enabled UART. This is not a generic DMA
+ driver, instead this enables DMAC regs for Clanton's UART alone
+
+ Say Y here if you have a Clanton processor.
+
+ If unsure, say N.
+endif
+
config ASYNC_TX_ENABLE_CHANNEL_SWITCH
bool
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index a0de82e..91883c2 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -30,9 +30,9 @@
#include <linux/module.h>
#include "dmaengine.h"
+#include "intel_mid_dma_regs.h"
#define MAX_CHAN 4 /*max ch across controllers*/
-#include "intel_mid_dma_regs.h"
#define INTEL_MID_DMAC1_ID 0x0814
#define INTEL_MID_DMAC2_ID 0x0813
@@ -43,6 +43,14 @@
#define LNW_PERIPHRAL_STATUS 0x0
#define LNW_PERIPHRAL_MASK 0x8
+/**
+ * struct intel_mid_dma_probe_info
+ *
+ * @max_chan: maximum channels to probe
+ * @ch_base: offset from register base
+ * @block_size: TBD
+ * @pimr_mask: indicates if mask registers to be mapped
+ */
struct intel_mid_dma_probe_info {
u8 max_chan;
u8 ch_base;
@@ -1015,7 +1023,7 @@ static void dma_tasklet2(unsigned long data)
* See if this is our interrupt if so then schedule the tasklet
* otherwise ignore
*/
-static irqreturn_t intel_mid_dma_interrupt(int irq, void *data)
+irqreturn_t intel_mid_dma_interrupt(int irq, void *data)
{
struct middma_device *mid = data;
u32 tfr_status, err_status;
@@ -1048,6 +1056,7 @@ static irqreturn_t intel_mid_dma_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL(intel_mid_dma_interrupt);
static irqreturn_t intel_mid_dma_interrupt1(int irq, void *data)
{
diff --git a/drivers/dma/intel_mid_dma/Makefile b/drivers/dma/intel_mid_dma/Makefile
new file mode 100644
index 0000000..567eca5
--- /dev/null
+++ b/drivers/dma/intel_mid_dma/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_MID_DMAC) += intel_mid_dma.o
+intel_mid_dma-objs:= intel_mid_dma_core.o intel_cln_dma_pci.o intel_mid_dma_pci.o
+
diff --git a/drivers/dma/intel_mid_dma/intel_cln_dma_pci.c b/drivers/dma/intel_mid_dma/intel_cln_dma_pci.c
new file mode 100644
index 0000000..442c2f2
--- /dev/null
+++ b/drivers/dma/intel_mid_dma/intel_cln_dma_pci.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+
+/*
+ * intel_mid_dma.c - Intel Langwell DMA Drivers
+ *
+ * Author: Vinod Koul <bryan.odonoghue@linux.intel.com>
+ * This is an entry point for Intel Clanton based DMAC on Clanton's UART
+ * specifically we don't have a dedicated PCI function, instead we have DMAC
+ * regs hung off of a PCI BAR. This entry/exit allows re-use of the core
+ * DMA API for MID devices manipulated to suit our BAR setup
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/intel_mid_dma.h>
+#include <linux/module.h>
+
+#include "intel_mid_dma_core.h"
+#include "intel_mid_dma_regs.h"
+
+/**
+ * intel_mid_dma_probe - PCI Probe
+ * @pdev: Controller PCI device structure
+ * @id: pci device id structure
+ *
+ * Initialize the PCI device, map BARs, query driver data.
+ * Call intel_setup_dma to complete contoller and chan initilzation
+ */
+int __devinit intel_cln_dma_probe(struct pci_dev *pdev,
+ struct middma_device *device)
+{
+ u32 base_addr, bar_size;
+ int err;
+
+ pr_debug("MDMA: probe for %x\n", pdev->device);
+ pr_debug("MDMA: CH %d, base %d, block len %d, Periphral mask %x\n",
+ device->max_chan, device->chan_base,
+ device->block_size, device->pimr_mask);
+
+ device->pdev = pci_dev_get(pdev);
+ device->ispci_fn = true;
+
+ base_addr = pci_resource_start(pdev, 1);
+ bar_size = pci_resource_len(pdev, 1);
+ device->dma_base = ioremap_nocache(base_addr, DMA_REG_SIZE);
+ if (!device->dma_base) {
+ pr_err("ERR_MDMA:ioremap failed\n");
+ err = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ err = intel_mid_dma_setup(pdev, device, false);
+ if (err)
+ goto err_dma;
+
+ return 0;
+
+err_dma:
+ iounmap(device->dma_base);
+err_ioremap:
+ pr_err("ERR_MDMA:Probe failed %d\n", err);
+ return err;
+}
+EXPORT_SYMBOL(intel_cln_dma_probe);
+
+/**
+ * intel_mid_dma_remove - PCI remove
+ * @pdev: Controller PCI device structure
+ *
+ * Free up all resources and data
+ * Call shutdown_dma to complete contoller and chan cleanup
+ */
+void __devexit intel_cln_dma_remove(struct pci_dev *pdev, struct middma_device *device)
+{
+ intel_mid_dma_shutdown(pdev, device);
+}
+EXPORT_SYMBOL(intel_cln_dma_remove);
+
+/* Power Management */
+/*
+* dma_suspend - PCI suspend function
+*
+* @pci: PCI device structure
+* @state: PM message
+*
+* This function is called by OS when a power event occurs
+*/
+int intel_cln_dma_suspend(struct middma_device *device)
+{
+ int i = 0;
+ pr_debug("MDMA: dma_suspend called\n");
+
+ for (i = 0; i < device->max_chan; i++) {
+ if (device->ch[i].in_use)
+ return -EAGAIN;
+ }
+ dmac1_mask_periphral_intr(device);
+ device->state = SUSPENDED;
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_dma_suspend);
+
+/**
+* dma_resume - PCI resume function
+*
+* @pci: PCI device structure
+*
+* This function is called by OS when a power event occurs
+*/
+int intel_cln_dma_resume(struct middma_device *device)
+{
+ pr_debug("MDMA: dma_resume called\n");
+ device->state = RUNNING;
+ iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_dma_resume);
+
+static int intel_cln_dma_runtime_suspend(struct middma_device *device)
+{
+ device->state = SUSPENDED;
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_dma_runtime_suspend);
+
+static int intel_cln_dma_runtime_resume(struct middma_device *device)
+{
+ device->state = RUNNING;
+ iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
+ return 0;
+}
+EXPORT_SYMBOL(intel_cln_dma_runtime_resume);
+
+
diff --git a/drivers/dma/intel_mid_dma/intel_mid_dma_pci.c b/drivers/dma/intel_mid_dma/intel_mid_dma_pci.c
new file mode 100644
index 0000000..be7705b
--- /dev/null
+++ b/drivers/dma/intel_mid_dma/intel_mid_dma_pci.c
@@ -0,0 +1,287 @@
+/*
+ * intel_mid_dma.c - Intel Langwell DMA Drivers
+ *
+ * Copyright (C) 2008-12 Intel Corp
+ * Author: Vinod Koul <vinod.koul@intel.com>
+ * The driver design is based on dw_dmac driver
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *
+ */
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/intel_mid_dma.h>
+#include <linux/module.h>
+
+#include "intel_mid_dma_regs.h"
+#include "intel_mid_dma_core.h"
+
+#define INTEL_MID_DMAC1_ID 0x0814
+#define INTEL_MID_DMAC2_ID 0x0813
+#define INTEL_MID_GP_DMAC2_ID 0x0827
+#define INTEL_MFLD_DMAC1_ID 0x0830
+
+#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \
+ ((kernel_ulong_t)&(struct intel_mid_dma_probe_info) { \
+ .max_chan = (_max_chan), \
+ .ch_base = (_ch_base), \
+ .block_size = (_block_size), \
+ .pimr_mask = (_pimr_mask), \
+ })
+
+/**
+ * intel_mid_dma_probe - PCI Probe
+ * @pdev: Controller PCI device structure
+ * @id: pci device id structure
+ *
+ * Initialize the PCI device, map BARs, query driver data.
+ * Call setup_dma to complete contoller and chan initilzation
+ */
+static int intel_mid_dma_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct middma_device *device;
+ u32 base_addr, bar_size;
+ struct intel_mid_dma_probe_info *info;
+ int err;
+
+ pr_debug("MDMA: probe for %x\n", pdev->device);
+ info = (void *)id->driver_data;
+ pr_debug("MDMA: CH %d, base %d, block len %d, Periphral mask %x\n",
+ info->max_chan, info->ch_base,
+ info->block_size, info->pimr_mask);
+
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_enable_device;
+
+ err = pci_request_regions(pdev, "intel_mid_dmac");
+ if (err)
+ goto err_request_regions;
+
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err)
+ goto err_set_dma_mask;
+
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err)
+ goto err_set_dma_mask;
+
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
+ if (!device) {
+ pr_err("ERR_MDMA:kzalloc failed probe\n");
+ err = -ENOMEM;
+ goto err_kzalloc;
+ }
+ device->pdev = pci_dev_get(pdev);
+
+ base_addr = pci_resource_start(pdev, 0);
+ bar_size = pci_resource_len(pdev, 0);
+ device->dma_base = ioremap_nocache(base_addr, DMA_REG_SIZE);
+ if (!device->dma_base) {
+ pr_err("ERR_MDMA:ioremap failed\n");
+ err = -ENOMEM;
+ goto err_ioremap;
+ }
+ pci_set_drvdata(pdev, device);
+ pci_set_master(pdev);
+ device->max_chan = info->max_chan;
+ device->chan_base = info->ch_base;
+ device->block_size = info->block_size;
+ device->pimr_mask = info->pimr_mask;
+
+ err = mid_setup_dma(pdev);
+ if (err)
+ goto err_dma;
+
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_allow(&pdev->dev);
+ return 0;
+
+err_dma:
+ iounmap(device->dma_base);
+err_ioremap:
+ pci_dev_put(pdev);
+ kfree(device);
+err_kzalloc:
+err_set_dma_mask:
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+err_request_regions:
+err_enable_device:
+ pr_err("ERR_MDMA:Probe failed %d\n", err);
+ return err;
+}
+
+/**
+ * intel_mid_dma_remove - PCI remove
+ * @pdev: Controller PCI device structure
+ *
+ * Free up all resources and data
+ * Call shutdown_dma to complete contoller and chan cleanup
+ */
+static void intel_mid_dma_remove(struct pci_dev *pdev)
+{
+ struct middma_device *device = pci_get_drvdata(pdev);
+
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_forbid(&pdev->dev);
+ middma_shutdown(pdev);
+ pci_dev_put(pdev);
+ kfree(device);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+/* Power Management */
+/*
+* dma_suspend - PCI suspend function
+*
+* @pci: PCI device structure
+* @state: PM message
+*
+* This function is called by OS when a power event occurs
+*/
+static int dma_suspend(struct device *dev)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+ int i;
+ struct middma_device *device = pci_get_drvdata(pci);
+ pr_debug("MDMA: dma_suspend called\n");
+
+ for (i = 0; i < device->max_chan; i++) {
+ if (device->ch[i].in_use)
+ return -EAGAIN;
+ }
+ dmac1_mask_periphral_intr(device);
+ device->state = SUSPENDED;
+ pci_save_state(pci);
+ pci_disable_device(pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ return 0;
+}
+
+/**
+* dma_resume - PCI resume function
+*
+* @pci: PCI device structure
+*
+* This function is called by OS when a power event occurs
+*/
+int dma_resume(struct device *dev)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+ int ret;
+ struct middma_device *device = pci_get_drvdata(pci);
+
+ pr_debug("MDMA: dma_resume called\n");
+ pci_set_power_state(pci, PCI_D0);
+ pci_restore_state(pci);
+ ret = pci_enable_device(pci);
+ if (ret) {
+ pr_err("MDMA: device can't be enabled for %x\n", pci->device);
+ return ret;
+ }
+ intel_mid_dma_resume(device);
+ return 0;
+}
+
+static int dma_runtime_suspend(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct middma_device *device = pci_get_drvdata(pci_dev);
+
+ device->state = SUSPENDED;
+ return 0;
+}
+
+static int dma_runtime_resume(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct middma_device *device = pci_get_drvdata(pci_dev);
+
+ device->state = RUNNING;
+ iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
+ return 0;
+}
+
+static int dma_runtime_idle(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct middma_device *device = pci_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < device->max_chan; i++) {
+ if (device->ch[i].in_use)
+ return -EAGAIN;
+ }
+
+ return pm_schedule_suspend(dev, 0);
+}
+
+/******************************************************************************
+* PCI stuff
+*/
+static struct pci_device_id intel_mid_dma_ids[] = {
+ { PCI_VDEVICE(INTEL, INTEL_MID_DMAC1_ID), INFO(2, 6, 4095, 0x200020)},
+ { PCI_VDEVICE(INTEL, INTEL_MID_DMAC2_ID), INFO(2, 0, 2047, 0)},
+ { PCI_VDEVICE(INTEL, INTEL_MID_GP_DMAC2_ID), INFO(2, 0, 2047, 0)},
+ { PCI_VDEVICE(INTEL, INTEL_MFLD_DMAC1_ID), INFO(4, 0, 4095, 0x400040)},
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, intel_mid_dma_ids);
+
+static const struct dev_pm_ops intel_mid_dma_pm = {
+ .runtime_suspend = dma_runtime_suspend,
+ .runtime_resume = dma_runtime_resume,
+ .runtime_idle = dma_runtime_idle,
+ .suspend = dma_suspend,
+ .resume = dma_resume,
+};
+
+static struct pci_driver intel_mid_dma_pci_driver = {
+ .name = "Intel MID DMA",
+ .id_table = intel_mid_dma_ids,
+ .probe = intel_mid_dma_probe,
+ .remove = __devexit_p(intel_mid_dma_remove),
+#ifdef CONFIG_PM
+ .driver = {
+ .pm = &intel_mid_dma_pm,
+ },
+#endif
+};
+
+static int __init intel_mid_dma_init(void)
+{
+ pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n",
+ INTEL_MID_DMA_DRIVER_VERSION);
+ return pci_register_driver(&intel_mid_dma_pci_driver);
+}
+fs_initcall(intel_mid_dma_init);
+
+static void __exit intel_mid_dma_exit(void)
+{
+ pci_unregister_driver(&intel_mid_dma_pci_driver);
+}
+module_exit(intel_mid_dma_exit);
+
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_DESCRIPTION("Intel (R) MID DMAC Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(INTEL_MID_DMA_DRIVER_VERSION);
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h
index 17b4219..4be7a01 100644
--- a/drivers/dma/intel_mid_dma_regs.h
+++ b/drivers/dma/intel_mid_dma_regs.h
@@ -27,6 +27,7 @@
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
+#include <linux/intel_mid_dma.h>
#include <linux/pci_ids.h>
#define INTEL_MID_DMA_DRIVER_VERSION "1.1.0"
@@ -158,115 +159,17 @@ union intel_mid_dma_cfg_hi {
};
-/**
- * struct intel_mid_dma_chan - internal mid representation of a DMA channel
- * @chan: dma_chan strcture represetation for mid chan
- * @ch_regs: MMIO register space pointer to channel register
- * @dma_base: MMIO register space DMA engine base pointer
- * @ch_id: DMA channel id
- * @lock: channel spinlock
- * @active_list: current active descriptors
- * @queue: current queued up descriptors
- * @free_list: current free descriptors
- * @slave: dma slave structure
- * @descs_allocated: total number of descriptors allocated
- * @dma: dma device structure pointer
- * @busy: bool representing if ch is busy (active txn) or not
- * @in_use: bool representing if ch is in use or not
- * @raw_tfr: raw trf interrupt received
- * @raw_block: raw block interrupt received
- */
-struct intel_mid_dma_chan {
- struct dma_chan chan;
- void __iomem *ch_regs;
- void __iomem *dma_base;
- int ch_id;
- spinlock_t lock;
- struct list_head active_list;
- struct list_head queue;
- struct list_head free_list;
- unsigned int descs_allocated;
- struct middma_device *dma;
- bool busy;
- bool in_use;
- u32 raw_tfr;
- u32 raw_block;
- struct intel_mid_dma_slave *mid_slave;
-};
-
static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan(
struct dma_chan *chan)
{
return container_of(chan, struct intel_mid_dma_chan, chan);
}
-enum intel_mid_dma_state {
- RUNNING = 0,
- SUSPENDED,
-};
-/**
- * struct middma_device - internal representation of a DMA device
- * @pdev: PCI device
- * @dma_base: MMIO register space pointer of DMA
- * @dma_pool: for allocating DMA descriptors
- * @common: embedded struct dma_device
- * @tasklet: dma tasklet for processing interrupts
- * @ch: per channel data
- * @pci_id: DMA device PCI ID
- * @intr_mask: Interrupt mask to be used
- * @mask_reg: MMIO register for periphral mask
- * @chan_base: Base ch index (read from driver data)
- * @max_chan: max number of chs supported (from drv_data)
- * @block_size: Block size of DMA transfer supported (from drv_data)
- * @pimr_mask: MMIO register addr for periphral interrupt (from drv_data)
- * @state: dma PM device state
- */
-struct middma_device {
- struct pci_dev *pdev;
- void __iomem *dma_base;
- struct pci_pool *dma_pool;
- struct dma_device common;
- struct tasklet_struct tasklet;
- struct intel_mid_dma_chan ch[MAX_CHAN];
- unsigned int pci_id;
- unsigned int intr_mask;
- void __iomem *mask_reg;
- int chan_base;
- int max_chan;
- int block_size;
- unsigned int pimr_mask;
- enum intel_mid_dma_state state;
-};
-
static inline struct middma_device *to_middma_device(struct dma_device *common)
{
return container_of(common, struct middma_device, common);
}
-struct intel_mid_dma_desc {
- void __iomem *block; /*ch ptr*/
- struct list_head desc_node;
- struct dma_async_tx_descriptor txd;
- size_t len;
- dma_addr_t sar;
- dma_addr_t dar;
- u32 cfg_hi;
- u32 cfg_lo;
- u32 ctl_lo;
- u32 ctl_hi;
- struct pci_pool *lli_pool;
- struct intel_mid_dma_lli *lli;
- dma_addr_t lli_phys;
- unsigned int lli_length;
- unsigned int current_lli;
- dma_addr_t next;
- enum dma_transfer_direction dirn;
- enum dma_status status;
- enum dma_slave_buswidth width; /*width of DMA txn*/
- enum intel_mid_dma_mode cfg_mode; /*mode configuration*/
-
-};
-
struct intel_mid_dma_lli {
dma_addr_t sar;
dma_addr_t dar;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 682de75..97e951b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -243,13 +243,14 @@ config GPIO_VR41XX
Say yes here to support the NEC VR4100 series General-purpose I/O Uint
config GPIO_SCH
- tristate "Intel SCH/TunnelCreek/Centerton GPIO"
+ tristate "Intel SCH/TunnelCreek/Centerton/Clanton GPIO"
depends on PCI && X86
select MFD_CORE
select LPC_SCH
help
Say yes here to support GPIO interface on Intel Poulsbo SCH,
- Intel Tunnel Creek processor or Intel Centerton processor.
+ Intel Tunnel Creek processor, Intel Centerton processor or Intel
+ Clanton.
The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by
@@ -261,6 +262,8 @@ config GPIO_SCH
The Intel Centerton processor has a total of 30 GPIO pins.
Twenty-one are powered by the core power rail and 9 from the
suspend power supply.
+ The Intel Clanton has 2 GPIOs powered by the core power well and 6
+ form the suspend power well.
config GPIO_ICH
tristate "Intel ICH GPIO"
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index edae963..73591be 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -41,6 +41,13 @@ static DEFINE_SPINLOCK(gpio_lock);
static unsigned short gpio_ba;
+static void cln_gpio_restrict_release(struct device *dev) {}
+static struct platform_device cln_gpio_restrict_pdev =
+{
+ .name = "cln-gpio-restrict-nc",
+ .dev.release = cln_gpio_restrict_release,
+};
+
static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num)
{
u8 curr_dirs;
@@ -240,6 +247,14 @@ static int sch_gpio_probe(struct platform_device *pdev)
sch_gpio_resume.ngpio = 9;
break;
+ case PCI_DEVICE_ID_INTEL_CLANTON_ILB:
+ sch_gpio_core.base = 0;
+ sch_gpio_core.ngpio = 2;
+
+ sch_gpio_resume.base = 2;
+ sch_gpio_resume.ngpio = 6;
+ break;
+
default:
err = -ENODEV;
goto err_sch_gpio_core;
@@ -256,6 +271,10 @@ static int sch_gpio_probe(struct platform_device *pdev)
if (err < 0)
goto err_sch_gpio_resume;
+ err = platform_device_register(&cln_gpio_restrict_pdev);
+ if (err < 0)
+ goto err_sch_gpio_resume;
+
return 0;
err_sch_gpio_resume:
@@ -277,6 +296,8 @@ static int sch_gpio_remove(struct platform_device *pdev)
if (gpio_ba) {
int err;
+ platform_device_unregister(&cln_gpio_restrict_pdev);
+
err = gpiochip_remove(&sch_gpio_core);
if (err)
dev_err(&pdev->dev, "%s failed, %d\n",
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 199fca1..5e897ff 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -60,11 +60,17 @@ struct gpio_desc {
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
#define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */
+#define FLAG_PULLUP 10 /* Gpio drive is resistive pullup */
+#define FLAG_PULLDOWN 11 /* Gpio drive is resistive pulldown */
+#define FLAG_STRONG 12 /* Gpio drive is strong (fast output) */
+#define FLAG_HIZ 13 /* Gpio drive is Hi-Z (input) */
#define ID_SHIFT 16 /* add new flags before this one */
#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
+#define GPIO_DRIVE_MASK (BIT(FLAG_PULLUP) | BIT(FLAG_PULLDOWN) \
+ | BIT(FLAG_STRONG) | BIT(FLAG_HIZ))
#ifdef CONFIG_DEBUG_FS
const char *label;
@@ -243,6 +249,10 @@ static DEFINE_MUTEX(sysfs_lock);
* * is read/write as zero/nonzero
* * also affects existing and subsequent "falling" and "rising"
* /edge configuration
+ * /drive
+ * * sets signal drive mode
+ * * is read/write as "pullup", "pulldown", "strong" or "hiz"
+ *
*/
static ssize_t gpio_direction_show(struct device *dev,
@@ -573,9 +583,85 @@ static ssize_t gpio_active_low_store(struct device *dev,
static const DEVICE_ATTR(active_low, 0644,
gpio_active_low_show, gpio_active_low_store);
+static ssize_t gpio_drive_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+ status = -EIO;
+ } else {
+ if (test_bit(FLAG_PULLUP, &desc->flags))
+ status = sprintf(buf, "pullup\n");
+ else if (test_bit(FLAG_PULLDOWN, &desc->flags))
+ status = sprintf(buf, "pulldown\n");
+ else if (test_bit(FLAG_STRONG, &desc->flags))
+ status = sprintf(buf, "strong\n");
+ else if (test_bit(FLAG_HIZ, &desc->flags))
+ status = sprintf(buf, "hiz\n");
+ else
+ status = -EINVAL;
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static ssize_t gpio_drive_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ unsigned gpio = desc - gpio_desc;
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else {
+ if (sysfs_streq(buf, "pullup")) {
+ status = gpio_set_drive(gpio, GPIOF_DRIVE_PULLUP);
+ if (!status) {
+ desc->flags &= ~GPIO_DRIVE_MASK;
+ set_bit(FLAG_PULLUP, &desc->flags);
+ }
+ } else if (sysfs_streq(buf, "pulldown")) {
+ status = gpio_set_drive(gpio, GPIOF_DRIVE_PULLDOWN);
+ if (!status) {
+ desc->flags &= ~GPIO_DRIVE_MASK;
+ set_bit(FLAG_PULLDOWN, &desc->flags);
+ }
+ } else if (sysfs_streq(buf, "strong")) {
+ status = gpio_set_drive(gpio, GPIOF_DRIVE_STRONG);
+ if (!status) {
+ desc->flags &= ~GPIO_DRIVE_MASK;
+ set_bit(FLAG_STRONG, &desc->flags);
+ }
+ } else if (sysfs_streq(buf, "hiz")) {
+ status = gpio_set_drive(gpio, GPIOF_DRIVE_HIZ);
+ if (!status) {
+ desc->flags &= ~GPIO_DRIVE_MASK;
+ set_bit(FLAG_HIZ, &desc->flags);
+ }
+ } else {
+ status = -EINVAL;
+ }
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status ? : size;
+}
+
+static const DEVICE_ATTR(drive, 0644,
+ gpio_drive_show, gpio_drive_store);
+
static const struct attribute *gpio_attrs[] = {
&dev_attr_value.attr,
&dev_attr_active_low.attr,
+ &dev_attr_drive.attr,
NULL,
};
@@ -806,7 +892,7 @@ fail_unlock:
}
EXPORT_SYMBOL_GPL(gpio_export);
-static int match_export(struct device *dev, void *data)
+static int match_export(struct device *dev, const void *data)
{
return dev_get_drvdata(dev) == data;
}
@@ -1677,6 +1763,50 @@ fail:
}
EXPORT_SYMBOL_GPL(gpio_set_debounce);
+/**
+ * gpio_set_drive - sets drive @mode for a @gpio
+ * @gpio: the gpio to set the drive mode
+ * @mode: the drive mode
+ */
+int gpio_set_drive(unsigned gpio, unsigned mode)
+{
+ unsigned long flags;
+ struct gpio_chip *chip;
+ struct gpio_desc *desc = &gpio_desc[gpio];
+ int status = -EINVAL;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ if (!gpio_is_valid(gpio))
+ goto fail;
+ chip = desc->chip;
+ if (!chip || !chip->set || !chip->set_drive)
+ goto fail;
+ gpio -= chip->base;
+ if (gpio >= chip->ngpio)
+ goto fail;
+ status = gpio_ensure_requested(desc, gpio);
+ if (status < 0)
+ goto fail;
+
+ /* now we know the gpio is valid and chip won't vanish */
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ might_sleep_if(chip->can_sleep);
+
+ return chip->set_drive(chip, gpio, mode);
+
+fail:
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ if (status)
+ pr_debug("%s: gpio-%d status %d\n",
+ __func__, gpio, status);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(gpio_set_drive);
+
/* I/O calls are only valid after configuration completed; the relevant
* "is this a valid GPIO" error checks should already have been done.
*
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index bdca511..3793dc8 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -22,7 +22,7 @@ config I2C_ALI1535
config I2C_ALI1563
tristate "ALI 1563"
- depends on PCI && EXPERIMENTAL
+ depends on PCI
help
If you say yes to this option, support will be included for the SMB
Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB
@@ -56,7 +56,7 @@ config I2C_AMD756
config I2C_AMD756_S4882
tristate "SMBus multiplexing on the Tyan S4882"
- depends on I2C_AMD756 && X86 && EXPERIMENTAL
+ depends on I2C_AMD756 && X86
help
Enabling this option will add specific SMBus support for the Tyan
S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed
@@ -164,7 +164,7 @@ config I2C_NFORCE2
config I2C_NFORCE2_S4985
tristate "SMBus multiplexing on the Tyan S4985"
- depends on I2C_NFORCE2 && X86 && EXPERIMENTAL
+ depends on I2C_NFORCE2 && X86
help
Enabling this option will add specific SMBus support for the Tyan
S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed
@@ -215,7 +215,7 @@ config I2C_SIS96X
config I2C_VIA
tristate "VIA VT82C586B"
- depends on PCI && EXPERIMENTAL
+ depends on PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the VIA
@@ -267,7 +267,7 @@ comment "Mac SMBus host controller drivers"
config I2C_HYDRA
tristate "CHRP Apple Hydra Mac I/O I2C interface"
- depends on PCI && PPC_CHRP && EXPERIMENTAL
+ depends on PCI && PPC_CHRP
select I2C_ALGOBIT
help
This supports the use of the I2C interface in the Apple Hydra Mac
@@ -293,7 +293,7 @@ comment "I2C system bus drivers (mostly embedded / system-on-chip)"
config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
- depends on ARCH_AT91 && EXPERIMENTAL
+ depends on ARCH_AT91
help
This supports the use of the I2C interface on Atmel AT91
processors.
@@ -386,7 +386,7 @@ config I2C_DESIGNWARE_PLATFORM
config I2C_DESIGNWARE_PCI
tristate "Synopsys DesignWare PCI"
- depends on PCI
+ depends on PCI && !INTEL_CLN_SOC
select I2C_DESIGNWARE_CORE
help
If you say yes to this option, support will be included for the
@@ -519,7 +519,6 @@ config I2C_NUC900
config I2C_OCORES
tristate "OpenCores I2C Controller"
- depends on EXPERIMENTAL
help
If you say yes to this option, support will be included for the
OpenCores I2C controller. For details see
@@ -712,7 +711,7 @@ config I2C_OCTEON
config I2C_XILINX
tristate "Xilinx I2C Controller"
- depends on EXPERIMENTAL && HAS_IOMEM
+ depends on HAS_IOMEM
help
If you say yes to this option, support will be included for the
Xilinx I2C controller.
@@ -803,7 +802,7 @@ config I2C_PARPORT_LIGHT
config I2C_TAOS_EVM
tristate "TAOS evaluation module"
- depends on EXPERIMENTAL
+ depends on TTY
select SERIO
select SERIO_SERPORT
default n
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index f5258c2..0852773 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -164,6 +164,29 @@ static char *abort_sources[] = {
"lost arbitration",
};
+/*
+ * Bitmask for struct i2c_dw_data_cmd's `cmd' field.
+ * - DW_IC_CMD_READ: read/~write operation
+ * - DW_IC_CMD_STOP: stop condition generation (only for devices requiring
+ * explicit transaction termination)
+ * - DW_IC_CMD_RESTART: (re)start condition generation (only for devices
+ * requiring explicit transaction termination)
+ */
+#define DW_IC_CMD_READ 0x01
+#define DW_IC_CMD_STOP 0x02
+#define DW_IC_CMD_RESTART 0x04
+
+/*
+ * Define the IC_DATA_CMD format.
+ */
+static union i2c_dw_data_cmd {
+ struct fields {
+ u8 data;
+ u8 cmd;
+ } fields;
+ u16 value;
+} data_cmd;
+
u32 dw_readl(struct dw_i2c_dev *dev, int offset)
{
u32 value;
@@ -380,6 +403,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
u32 addr = msgs[dev->msg_write_idx].addr;
u32 buf_len = dev->tx_buf_len;
u8 *buf = dev->tx_buf;
+ int segment_start = 0;
intr_mask = DW_IC_INTR_DEFAULT_MASK;
@@ -403,21 +427,65 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
break;
}
+ segment_start = 0;
if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
/* new i2c_msg */
buf = msgs[dev->msg_write_idx].buf;
buf_len = msgs[dev->msg_write_idx].len;
+ segment_start = 1;
}
tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
+ /*
+ * The maximum number of read requests that can be put into TX
+ * FIFO depends on the number read operations already pending
+ * in RX FIFO + the number of outstanding read operations still
+ * queued in the TX FIFO.
+ * This prevents RX FIFO overrun.
+ */
+ rx_limit -= dev->rx_outstanding;
+
while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+ data_cmd.fields.data = 0x00;
+ data_cmd.fields.cmd = 0x00;
+
if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
- dw_writel(dev, 0x100, DW_IC_DATA_CMD);
+ /* Master-receiver */
+ data_cmd.fields.cmd = DW_IC_CMD_READ;
rx_limit--;
- } else
- dw_writel(dev, *buf++, DW_IC_DATA_CMD);
+ dev->rx_outstanding++;
+ } else {
+ /* Master-transmitter */
+ data_cmd.fields.data = *buf;
+ buf++;
+ }
+
+ if (1 == dev->explicit_stop
+ && 1 == segment_start) {
+ /*
+ * First byte of a transaction segment for a
+ * device requiring explicit transaction
+ * termination: generate (re)start symbol.
+ */
+ segment_start = 0;
+ data_cmd.fields.cmd |= DW_IC_CMD_RESTART;
+ }
+
+ if (1 == dev->explicit_stop
+ && dev->msg_write_idx == dev->msgs_num - 1
+ && 1 == buf_len) {
+ /*
+ * Last byte of last transction segment for a
+ * device requiring explicit transaction
+ * termination: generate stop symbol.
+ */
+ data_cmd.fields.cmd |= DW_IC_CMD_STOP;
+ }
+
+ dw_writel(dev, data_cmd.value, DW_IC_DATA_CMD);
+
tx_limit--; buf_len--;
}
@@ -468,8 +536,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
rx_valid = dw_readl(dev, DW_IC_RXFLR);
- for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+ for (; len > 0 && rx_valid > 0; len--, rx_valid--) {
*buf++ = dw_readl(dev, DW_IC_DATA_CMD);
+ dev->rx_outstanding--;
+ }
if (len > 0) {
dev->status |= STATUS_READ_IN_PROGRESS;
@@ -527,6 +597,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev->msg_err = 0;
dev->status = STATUS_IDLE;
dev->abort_source = 0;
+ dev->rx_outstanding = 0;
ret = i2c_dw_wait_bus_not_busy(dev);
if (ret < 0)
@@ -625,8 +696,6 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
dw_readl(dev, DW_IC_CLR_RX_DONE);
if (stat & DW_IC_INTR_ACTIVITY)
dw_readl(dev, DW_IC_CLR_ACTIVITY);
- if (stat & DW_IC_INTR_STOP_DET)
- dw_readl(dev, DW_IC_CLR_STOP_DET);
if (stat & DW_IC_INTR_START_DET)
dw_readl(dev, DW_IC_CLR_START_DET);
if (stat & DW_IC_INTR_GEN_CALL)
@@ -677,8 +746,21 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
* the current transmit status.
*/
+ /*
+ * Process stop condition after the last transaction segment is
+ * transmitted (and received if appropriate).
+ */
+ if (dev->msgs_num == dev->msg_write_idx
+ && (DW_IC_INTR_STOP_DET & dw_readl(dev, DW_IC_INTR_STAT))
+ && 0 == dw_readl(dev, DW_IC_TXFLR)
+ && 0 == dw_readl(dev, DW_IC_RXFLR)
+ && 0 == dev->rx_outstanding) {
+ dw_readl(dev, DW_IC_CLR_STOP_DET);
+ complete(&dev->cmd_complete);
+ }
+
tx_aborted:
- if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+ if ((stat & (DW_IC_INTR_TX_ABRT)) || dev->msg_err)
complete(&dev->cmd_complete);
return IRQ_HANDLED;
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 9c1840e..691aff8 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -34,6 +34,14 @@
#define DW_IC_CON_RESTART_EN 0x20
#define DW_IC_CON_SLAVE_DISABLE 0x40
+struct dw_pci_controller {
+ u32 bus_num;
+ u32 bus_cfg;
+ u32 tx_fifo_depth;
+ u32 rx_fifo_depth;
+ u32 clk_khz;
+ u8 explicit_stop;
+};
/**
* struct dw_i2c_dev - private i2c-designware data
@@ -60,6 +68,8 @@
* @adapter: i2c subsystem adapter node
* @tx_fifo_depth: depth of the hardware tx fifo
* @rx_fifo_depth: depth of the hardware rx fifo
+ * @rx_outstanding: current outstanding master-receiver bytes in TX FIFO
+ * @explicit_stop: set to 1 if hardware requires explicit stop bit transmission
*/
struct dw_i2c_dev {
struct device *dev;
@@ -88,6 +98,8 @@ struct dw_i2c_dev {
u32 master_cfg;
unsigned int tx_fifo_depth;
unsigned int rx_fifo_depth;
+ int rx_outstanding;
+ u8 explicit_stop;
};
#define ACCESS_SWAP 0x00000001
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 6add851..62ad7dc 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -56,14 +56,6 @@ enum dw_pci_ctl_id_t {
medfield_5,
};
-struct dw_pci_controller {
- u32 bus_num;
- u32 bus_cfg;
- u32 tx_fifo_depth;
- u32 rx_fifo_depth;
- u32 clk_khz;
-};
-
#define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \
DW_IC_CON_SLAVE_DISABLE | \
DW_IC_CON_RESTART_EN)
@@ -75,6 +67,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[moorestown_1] = {
.bus_num = 1,
@@ -82,6 +75,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[moorestown_2] = {
.bus_num = 2,
@@ -89,6 +83,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[medfield_0] = {
.bus_num = 0,
@@ -96,6 +91,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[medfield_1] = {
.bus_num = 1,
@@ -103,6 +99,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[medfield_2] = {
.bus_num = 2,
@@ -110,6 +107,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[medfield_3] = {
.bus_num = 3,
@@ -117,6 +115,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[medfield_4] = {
.bus_num = 4,
@@ -124,6 +123,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
[medfield_5] = {
.bus_num = 5,
@@ -131,6 +131,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.tx_fifo_depth = 32,
.rx_fifo_depth = 32,
.clk_khz = 25000,
+ .explicit_stop = 0,
},
};
static struct i2c_algorithm i2c_dw_algo = {
@@ -282,6 +283,7 @@ const struct pci_device_id *id)
dev->tx_fifo_depth = controller->tx_fifo_depth;
dev->rx_fifo_depth = controller->rx_fifo_depth;
+ dev->explicit_stop = controller->explicit_stop;
r = i2c_dw_init(dev);
if (r)
goto err_iounmap;
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index b34d754..9125ed7 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -33,7 +33,6 @@
#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */
#define AD7298_PDD (1 << 0) /* partial power down enable */
-#define AD7298_MAX_CHAN 8
#define AD7298_BITS 12
#define AD7298_STORAGE_BITS 16
#define AD7298_INTREF_mV 2500
@@ -46,6 +45,7 @@ struct ad7298_state {
struct spi_device *spi;
struct regulator *reg;
unsigned ext_ref;
+ u16 ext_vin_max[AD7298_MAX_CHAN];
struct spi_transfer ring_xfer[10];
struct spi_transfer scan_single_xfer[3];
struct spi_message ring_msg;
@@ -269,7 +269,10 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
- *val = ad7298_get_ref_voltage(st);
+ if (st->ext_vin_max[chan->channel])
+ *val = st->ext_vin_max[chan->channel];
+ else
+ *val = ad7298_get_ref_voltage(st);
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_TEMP:
@@ -304,8 +307,15 @@ static int ad7298_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
- if (pdata && pdata->ext_ref)
- st->ext_ref = AD7298_EXTREF;
+ if (pdata) {
+ int i;
+
+ if (pdata->ext_ref)
+ st->ext_ref = AD7298_EXTREF;
+
+ for (i = 0; i < AD7298_MAX_CHAN; i++)
+ st->ext_vin_max[i] = pdata->ext_vin_max[i];
+ }
if (st->ext_ref) {
st->reg = regulator_get(&spi->dev, "vref");
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index 3e24571..da30c5c 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -168,13 +168,13 @@ static struct class mISDN_class = {
};
static int
-_get_mdevice(struct device *dev, void *id)
+_get_mdevice(struct device *dev, const void *id)
{
struct mISDNdevice *mdev = dev_to_mISDN(dev);
if (!mdev)
return 0;
- if (mdev->id != *(u_int *)id)
+ if (mdev->id != *(const u_int *)id)
return 0;
return 1;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ff553ba..ad15d3a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -907,6 +907,44 @@ config MFD_TIMBERDALE
The timberdale FPGA can be found on the Intel Atom development board
for in-vehicle infontainment, called Russellville.
+config CY8C9540A
+ tristate "Cypress CY8C9540 GPIO/PWM expander"
+ depends on INTEL_CLN_GIP
+ depends on PWM
+ help
+ I/O expander providing GPIO/PWM functionality.
+ This is Clanton-specific for now.
+
+config INTEL_CLN_GIP
+ tristate "Intel Clanton GIP"
+ depends on PCI && X86 && INTEL_CLN_SOC
+ depends on I2C
+ select GENERIC_IRQ_CHIP
+ help
+ GIP driver for Clanton SoC.
+ Clanton GIP is a single PCI function exporting a GPIO and an I2C
+ controller, namely Synopsys DesignWare GPIO and Synopsys DesignWare
+ I2C. The GPIO interface exports a total amount of 8 interrupt-capable
+ GPIOs.
+
+config INTEL_CLN_GIP_TEST
+ tristate "Intel Clanton GIP support for Integration Testing"
+ depends on INTEL_CLN_GIP
+ depends on INTEL_CLN_SOC_FPGAEMU || INTEL_CLN_SOC_SVP
+ select I2C_CHARDEV
+ select GPIO_SYSFS
+ select SPI
+ select SPI_BITBANG
+ select SPI_GPIO
+ select SPI_MASTER
+ select SPI_SPIDEV
+ help
+ Clanton GIP automated Integration Testing package.
+ It selects kernel components needed for GPIO and I2C tests as per
+ Integration Test Specification, and it also adds a kernel-space
+ facility for testing the GPIO.
+ Note this module is also used to test the Clanton Legacy GPIO.
+
config LPC_SCH
tristate "Intel SCH LPC"
depends on PCI
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8b977f8..2fb8008 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -123,6 +123,13 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
+obj-$(CONFIG_CY8C9540A) += cy8c9540a.o
+obj-$(CONFIG_INTEL_CLN_GIP) += intel_cln_gip.o
+intel_cln_gip-objs := intel_cln_gip_core.o \
+ intel_cln_gip_gpio.o \
+ intel_cln_gip_i2c.o \
+ ../i2c/busses/i2c-designware-core.o
+obj-$(CONFIG_INTEL_CLN_GIP_TEST)+=intel_cln_gip_test.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
obj-$(CONFIG_LPC_ICH) += lpc_ich.o
obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
diff --git a/drivers/mfd/cy8c9540a.c b/drivers/mfd/cy8c9540a.c
new file mode 100644
index 0000000..42af10b
--- /dev/null
+++ b/drivers/mfd/cy8c9540a.c
@@ -0,0 +1,887 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+
+/*
+ * Driver for Cypress CY8C9540A I/O Expander and PWM
+ *
+ * Izmir-specific.
+ * Based on gpio-adp5588.
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define DRV_NAME "cy8c9540a"
+
+/* CY8C9540A settings */
+#define NGPIO 40
+#define NPWM 8
+#define PWM_MAX_PERIOD 0xff
+#define DEVID_FAMILY_CY8C9540A 0x40
+#define DEVID_FAMILY_MASK 0xf0
+#define NPORTS 6
+
+/* Register offset */
+#define REG_INPUT_PORT0 0x00
+#define REG_OUTPUT_PORT0 0x08
+#define REG_INTR_STAT_PORT0 0x10
+#define REG_PORT_SELECT 0x18
+#define REG_INTR_MASK 0x19
+#define REG_SELECT_PWM 0x1a
+#define REG_PIN_DIR 0x1c
+#define REG_DRIVE_PULLUP 0x1d
+#define REG_PWM_SELECT 0x28
+#define REG_PWM_CLK 0x29
+#define REG_PWM_PERIOD 0x2a
+#define REG_PWM_PULSE_W 0x2b
+#define REG_ENABLE 0x2d
+#define REG_DEVID_STAT 0x2e
+
+struct cy8c9540a {
+ struct i2c_client *client;
+ struct gpio_chip gpio_chip;
+ struct pwm_chip pwm_chip;
+ struct mutex lock;
+ /* protect serialized access to the interrupt controller bus */
+ struct mutex irq_lock;
+ /* cached output registers */
+ u8 outreg_cache[NPORTS];
+ /* cached IRQ mask */
+ u8 irq_mask_cache[NPORTS];
+ /* IRQ mask to be applied */
+ u8 irq_mask[NPORTS];
+};
+
+/* Per-port GPIO offset */
+static const u8 cy8c9540a_port_offs[] = {
+ 0,
+ 8,
+ 16,
+ 20,
+ 28,
+ 36,
+};
+
+/* Galileo-specific data. */
+
+#define GPIO_BASE_ID 16
+#define GPIO_IRQBASE 64
+#define PWM_BASE_ID 0
+#define PWM_CLK 0x00 /* see resulting PWM_TCLK_NS */
+#define PWM_TCLK_NS 31250 /* 32kHz */
+#define SOC_GPIO_INT_PIN 13
+
+/* PWM-to-GPIO mapping (0 == first Cypress GPIO). */
+#define PWM_UNUSED -1
+static const int pwm2gpio_mapping[] = {
+ PWM_UNUSED,
+ 3,
+ PWM_UNUSED,
+ 2,
+ 9,
+ 1,
+ 8,
+ 0,
+};
+
+static inline u8 cypress_get_port(unsigned gpio)
+{
+ u8 i = 0;
+ for (i = 0; i < sizeof(cy8c9540a_port_offs) - 1; i ++) {
+ if (! (gpio / cy8c9540a_port_offs[i + 1]))
+ break;
+ }
+ return i;
+}
+
+static inline u8 cypress_get_offs(unsigned gpio, u8 port)
+{
+ return gpio - cy8c9540a_port_offs[port];
+}
+
+static int cy8c9540a_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ s32 ret = 0;
+ u8 port = 0;
+ u8 in_reg = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, gpio_chip);
+ struct i2c_client *client = dev->client;
+
+ port = cypress_get_port(gpio);
+ in_reg = REG_INPUT_PORT0 + port;
+
+ ret = i2c_smbus_read_byte_data(client, in_reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't read input port%u\n", in_reg);
+ }
+
+ return !!(ret & BIT(cypress_get_offs(gpio, port)));
+}
+
+static void cy8c9540a_gpio_set_value(struct gpio_chip *chip,
+ unsigned gpio, int val)
+{
+ s32 ret = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, gpio_chip);
+ struct i2c_client *client = dev->client;
+ u8 port = cypress_get_port(gpio);
+ u8 out_reg = REG_OUTPUT_PORT0 + port;
+
+ mutex_lock(&dev->lock);
+
+ if (val) {
+ dev->outreg_cache[port] |= BIT(cypress_get_offs(gpio, port));
+ } else {
+ dev->outreg_cache[port] &= ~BIT(cypress_get_offs(gpio, port));
+ }
+
+ ret = i2c_smbus_write_byte_data(client, out_reg,
+ dev->outreg_cache[port]);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write output port%u\n", port);
+ }
+
+ mutex_unlock(&dev->lock);
+}
+
+static int cy8c9540a_gpio_set_drive(struct gpio_chip *chip, unsigned gpio,
+ unsigned mode)
+{
+ int ret = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, gpio_chip);
+ struct i2c_client *client = dev->client;
+ u8 port = cypress_get_port(gpio);
+ u8 pin = cypress_get_offs(gpio, port);
+ u8 offs = 0;
+ u8 val = 0;
+
+ switch(mode) {
+ case GPIOF_DRIVE_PULLUP:
+ offs = 0x0;
+ break;
+ case GPIOF_DRIVE_STRONG:
+ offs = 0x4;
+ break;
+ case GPIOF_DRIVE_HIZ:
+ offs = 0x6;
+ break;
+ default:
+ /*
+ * See databook for alternative modes. This driver won't
+ * support them though.
+ */
+ return -EINVAL;
+ break;
+ }
+
+ mutex_lock(&dev->lock);
+
+ ret = i2c_smbus_write_byte_data(client, REG_PORT_SELECT, port);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't select port %u\n", port);
+ goto end;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, REG_DRIVE_PULLUP + offs);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't read pin direction\n");
+ goto end;
+ }
+
+ val = (u8)(ret | BIT(pin));
+
+ ret = i2c_smbus_write_byte_data(client, REG_DRIVE_PULLUP + offs, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't set drive mode port %u\n", port);
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ mutex_unlock(&dev->lock);
+ return ret;
+}
+
+static int cy8c9540a_gpio_direction(struct gpio_chip *chip, unsigned gpio,
+ int out, int val)
+{
+ s32 ret = 0;
+ u8 pins = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, gpio_chip);
+ struct i2c_client *client = dev->client;
+ u8 port = cypress_get_port(gpio);
+
+ if (out) {
+ cy8c9540a_gpio_set_value(chip, gpio, val);
+ }
+
+ mutex_lock(&dev->lock);
+
+ ret = i2c_smbus_write_byte_data(client, REG_PORT_SELECT, port);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't select port %u\n", port);
+ goto end;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, REG_PIN_DIR);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't read pin direction\n");
+ goto end;
+ }
+
+ pins = (u8)ret & 0xff;
+ if (out) {
+ pins &= ~BIT(cypress_get_offs(gpio, port));
+ } else {
+ pins |= BIT(cypress_get_offs(gpio, port));
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_PIN_DIR, pins);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write pin direction\n");
+ }
+
+end:
+ mutex_unlock(&dev->lock);
+ return ret;
+}
+
+static int cy8c9540a_gpio_direction_output(struct gpio_chip *chip,
+ unsigned gpio, int val)
+{
+ return cy8c9540a_gpio_direction(chip, gpio, 1, val);
+}
+
+static int cy8c9540a_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ return cy8c9540a_gpio_direction(chip, gpio, 0, 0);
+}
+
+static void cy8c9540a_irq_bus_lock(struct irq_data *d)
+{
+ struct cy8c9540a *dev = irq_data_get_irq_chip_data(d);
+ mutex_lock(&dev->irq_lock);
+}
+
+static void cy8c9540a_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct cy8c9540a *dev = irq_data_get_irq_chip_data(d);
+ struct i2c_client *client = dev->client;
+ int ret = 0;
+ int i = 0;
+
+ for (i = 0; i < NPORTS; i++) {
+ if (dev->irq_mask_cache[i] ^ dev->irq_mask[i]) {
+ dev->irq_mask_cache[i] = dev->irq_mask[i];
+ ret = i2c_smbus_write_byte_data(client, REG_PORT_SELECT, i);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't select port %u\n", i);
+ goto end;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_INTR_MASK, dev->irq_mask[i]);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write int mask on port %u\n", i);
+ goto end;
+ }
+
+ }
+ }
+
+end:
+ mutex_unlock(&dev->irq_lock);
+}
+
+static void cy8c9540a_irq_mask(struct irq_data *d)
+{
+ struct cy8c9540a *dev = irq_data_get_irq_chip_data(d);
+ unsigned gpio = d->irq - GPIO_IRQBASE;
+ u8 port = cypress_get_port(gpio);
+
+ dev->irq_mask[port] |= BIT(cypress_get_offs(gpio, port));
+}
+
+static void cy8c9540a_irq_unmask(struct irq_data *d)
+{
+ struct cy8c9540a *dev = irq_data_get_irq_chip_data(d);
+ unsigned gpio = d->irq - GPIO_IRQBASE;
+ u8 port = cypress_get_port(gpio);
+
+ dev->irq_mask[port] &= ~BIT(cypress_get_offs(gpio, port));
+}
+
+static int cy8c9540a_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ return GPIO_IRQBASE + gpio;
+}
+
+static int cy8c9540a_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct cy8c9540a *dev = irq_data_get_irq_chip_data(d);
+ int ret = 0;
+
+ if ((type != IRQ_TYPE_EDGE_BOTH)) {
+ dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
+ d->irq, type);
+ ret = -EINVAL;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static struct irq_chip cy8c9540a_irq_chip = {
+ .name = "cy8c9540a-irq",
+ .irq_mask = cy8c9540a_irq_mask,
+ .irq_unmask = cy8c9540a_irq_unmask,
+ .irq_bus_lock = cy8c9540a_irq_bus_lock,
+ .irq_bus_sync_unlock = cy8c9540a_irq_bus_sync_unlock,
+ .irq_set_type = cy8c9540a_irq_set_type,
+};
+
+static irqreturn_t cy8c9540a_irq_handler(int irq, void *devid)
+{
+ struct cy8c9540a *dev = devid;
+ u8 stat[NPORTS], pending = 0;
+ unsigned port = 0, gpio = 0, gpio_irq = 0;
+ int ret = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(dev->client, REG_INTR_STAT_PORT0,
+ NPORTS, stat); /* W1C */
+ if (ret < 0) {
+ memset(stat, 0, sizeof(stat));
+ }
+
+ ret = IRQ_NONE;
+
+ for (port = 0; port < NPORTS; port ++) {
+ /* Databook doesn't specify if this is a post-mask status
+ register or not. Consider it 'raw' for safety. */
+ mutex_lock(&dev->irq_lock);
+ pending = stat[port] & (~dev->irq_mask[port]);
+ mutex_unlock(&dev->irq_lock);
+
+ while (pending) {
+ ret = IRQ_HANDLED;
+ gpio = __ffs(pending);
+ pending &= ~BIT(gpio);
+ gpio_irq = GPIO_IRQBASE + cy8c9540a_port_offs[port]
+ + gpio;
+ handle_nested_irq(gpio_irq);
+ }
+ }
+
+ return ret;
+}
+
+static int cy8c9540a_irq_setup(struct cy8c9540a *dev)
+{
+ struct i2c_client *client = dev->client;
+ u8 dummy[NPORTS];
+ unsigned gpio = 0;
+ int ret = 0;
+ int i = 0;
+
+ mutex_init(&dev->irq_lock);
+
+ /* Clear interrupt state */
+
+ ret = i2c_smbus_read_i2c_block_data(dev->client, REG_INTR_STAT_PORT0,
+ NPORTS, dummy); /* W1C */
+ if (ret < 0) {
+ dev_err(&client->dev, "couldn't clear int status\n");
+ goto err;
+ }
+
+ /* Initialise interrupt mask */
+
+ memset(dev->irq_mask_cache, 0xff, sizeof(dev->irq_mask_cache));
+ memset(dev->irq_mask, 0xff, sizeof(dev->irq_mask));
+ for (i = 0; i < NPORTS; i++) {
+ ret = i2c_smbus_write_byte_data(client, REG_PORT_SELECT, i);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't select port %u\n", i);
+ goto err;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_INTR_MASK, dev->irq_mask[i]);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write int mask on port %u\n", i);
+ goto err;
+ }
+ }
+
+ /* Allocate external interrupt GPIO pin */
+
+ ret = gpio_request(SOC_GPIO_INT_PIN, "cy8c9540a-int");
+ if (ret) {
+ dev_err(&client->dev, "failed to request gpio%u\n",
+ SOC_GPIO_INT_PIN);
+ goto err;
+ }
+
+ /* Allocate IRQ descriptors for Cypress GPIOs and set handler */
+
+ ret = irq_alloc_descs(GPIO_IRQBASE, GPIO_IRQBASE, NGPIO, 0);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to allocate IRQ numbers\n");
+ goto err_free_gpio;
+ }
+
+ for (gpio = 0; gpio < NGPIO; gpio++) {
+ int irq = gpio + GPIO_IRQBASE;
+ irq_set_chip_data(irq, dev);
+ irq_set_chip_and_handler(irq, &cy8c9540a_irq_chip,
+ handle_edge_irq);
+ irq_set_nested_thread(irq, 1);
+ irq_set_noprobe(irq);
+ }
+
+ ret = request_threaded_irq(gpio_to_irq(SOC_GPIO_INT_PIN),
+ NULL,
+ cy8c9540a_irq_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ dev_name(&client->dev), dev);
+ if (ret) {
+ dev_err(&client->dev, "failed to request irq %d\n",
+ client->irq);
+ goto err_free_irq_descs;
+ }
+
+ return 0;
+
+err_free_irq_descs:
+ irq_free_descs(GPIO_IRQBASE, NGPIO);
+err_free_gpio:
+ gpio_free(SOC_GPIO_INT_PIN);
+err:
+ mutex_destroy(&dev->irq_lock);
+ return ret;
+}
+
+static void cy8c9540a_irq_teardown(struct cy8c9540a *dev)
+{
+ mutex_destroy(&dev->irq_lock);
+ irq_free_descs(GPIO_IRQBASE, NGPIO);
+ free_irq(gpio_to_irq(SOC_GPIO_INT_PIN), dev);
+ gpio_free(SOC_GPIO_INT_PIN);
+}
+
+static int cy8c9540a_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ int ret = 0;
+ int period = 0, duty = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, pwm_chip);
+ struct i2c_client *client = dev->client;
+
+ if (pwm->pwm > NPWM) {
+ return -EINVAL;
+ }
+
+ period = period_ns / PWM_TCLK_NS;
+ duty = duty_ns / PWM_TCLK_NS;
+
+ /*
+ * Check period's upper bound. Note the duty cycle is already sanity
+ * checked by the PWM framework.
+ */
+ if (period > PWM_MAX_PERIOD) {
+ dev_err(&client->dev, "period must be within [0-%d]ns\n",
+ PWM_MAX_PERIOD * PWM_TCLK_NS);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->lock);
+
+ ret = i2c_smbus_write_byte_data(client, REG_PWM_SELECT, (u8)pwm->pwm);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to REG_PWM_SELECT\n");
+ goto end;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_PWM_PERIOD, (u8)period);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to REG_PWM_PERIOD\n");
+ goto end;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_PWM_PULSE_W, (u8)duty);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to REG_PWM_PULSE_W\n");
+ goto end;
+ }
+
+end:
+ mutex_unlock(&dev->lock);
+
+ return ret;
+}
+
+static int cy8c9540a_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ int ret = 0;
+ int gpio = 0;
+ int port = 0, pin = 0;
+ u8 out_reg = 0;
+ u8 val = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, pwm_chip);
+ struct i2c_client *client = dev->client;
+
+ if (pwm->pwm > NPWM) {
+ return -EINVAL;
+ }
+
+ gpio = pwm2gpio_mapping[pwm->pwm];
+ port = cypress_get_port(gpio);
+ pin = cypress_get_offs(gpio, port);
+ out_reg = REG_OUTPUT_PORT0 + port;
+
+ /* Set pin as output driving high */
+ ret = cy8c9540a_gpio_direction(&dev->gpio_chip, gpio, 1, 1);
+ if (val < 0) {
+ dev_err(&client->dev, "can't set pwm%u as output\n", pwm->pwm);
+ return ret;
+ }
+
+ mutex_lock(&dev->lock);
+
+ /* Enable PWM */
+ val = i2c_smbus_read_byte_data(client, REG_SELECT_PWM);
+ if (val < 0) {
+ dev_err(&client->dev, "can't read REG_SELECT_PWM\n");
+ ret = val;
+ goto end;
+ }
+ val |= BIT((u8)pin);
+ ret = i2c_smbus_write_byte_data(client, REG_SELECT_PWM, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to SELECT_PWM\n");
+ goto end;
+ }
+
+end:
+ mutex_unlock(&dev->lock);
+
+ return ret;
+}
+
+static void cy8c9540a_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ int ret = 0;
+ int gpio = 0;
+ int port = 0, pin = 0;
+ u8 val = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, pwm_chip);
+ struct i2c_client *client = dev->client;
+
+ if (pwm->pwm > NPWM) {
+ return;
+ }
+
+ gpio = pwm2gpio_mapping[pwm->pwm];
+ if (PWM_UNUSED == gpio) {
+ dev_err(&client->dev, "pwm%d is unused\n", pwm->pwm);
+ return;
+ }
+
+ port = cypress_get_port(gpio);
+ pin = cypress_get_offs(gpio, port);
+
+ mutex_lock(&dev->lock);
+
+ /* Disable PWM */
+ val = i2c_smbus_read_byte_data(client, REG_SELECT_PWM);
+ if (val < 0) {
+ dev_err(&client->dev, "can't read REG_SELECT_PWM\n");
+ goto end;
+ }
+ val &= ~BIT((u8)pin);
+ ret = i2c_smbus_write_byte_data(client, REG_SELECT_PWM, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to SELECT_PWM\n");
+ }
+
+end:
+ mutex_unlock(&dev->lock);
+
+ return;
+}
+
+/*
+ * Some PWMs are unavailable on Galileo. Prevent user from reserving them.
+ */
+static int cy8c9540a_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ int gpio = 0;
+ struct cy8c9540a *dev =
+ container_of(chip, struct cy8c9540a, pwm_chip);
+ struct i2c_client *client = dev->client;
+
+ if (pwm->pwm > NPWM) {
+ return -EINVAL;
+ }
+
+ gpio = pwm2gpio_mapping[pwm->pwm];
+ if (PWM_UNUSED == gpio) {
+ dev_err(&client->dev, "pwm%d unavailable\n", pwm->pwm);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct pwm_ops cy8c9540a_pwm_ops = {
+ .request = cy8c9540a_pwm_request,
+ .config = cy8c9540a_pwm_config,
+ .enable = cy8c9540a_pwm_enable,
+ .disable = cy8c9540a_pwm_disable,
+};
+
+/*
+ * cy8c9540a_setup
+ *
+ * Initialise the device with default setup.
+ * No need to roll back if this fails.
+ */
+static int cy8c9540a_setup(struct cy8c9540a *dev)
+{
+ int ret = 0;
+ struct i2c_client *client = dev->client;
+ int i = 0;
+ const u8 eeprom_enable_seq[] = {0x43, 0x4D, 0x53, 0x2};
+
+ /* Disable PWM, set all GPIOs as input. */
+ for (i = 0; i < NPORTS; i ++) {
+ ret = i2c_smbus_write_byte_data(client, REG_PORT_SELECT, i);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't select port %u\n", i);
+ goto end;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_SELECT_PWM, 0x00);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to SELECT_PWM\n");
+ goto end;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_PIN_DIR, 0xff);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to PIN_DIR\n");
+ goto end;
+ }
+ }
+
+ /* Cache the output registers */
+ ret = i2c_smbus_read_i2c_block_data(dev->client, REG_OUTPUT_PORT0,
+ sizeof(dev->outreg_cache),
+ dev->outreg_cache);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't cache output registers\n");
+ goto end;
+ }
+
+ /* Set default PWM clock source. */
+ for (i = 0; i < NPWM; i ++) {
+ ret = i2c_smbus_write_byte_data(client, REG_PWM_SELECT, i);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't select pwm %u\n", i);
+ goto end;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, REG_PWM_CLK, PWM_CLK);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't write to REG_PWM_CLK\n");
+ goto end;
+ }
+ }
+
+ /* Enable the EEPROM */
+ ret = i2c_smbus_write_i2c_block_data(client, REG_ENABLE,
+ sizeof(eeprom_enable_seq),
+ eeprom_enable_seq);
+ if (ret < 0) {
+ dev_err(&client->dev, "can't enable EEPROM\n");
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static int cy8c9540a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct cy8c9540a *dev;
+ struct gpio_chip *gc;
+ int ret = 0;
+ s32 dev_id = 0;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_I2C_BLOCK |
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&client->dev, "SMBUS Byte/Block unsupported\n");
+ return -EIO;
+ }
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ dev_err(&client->dev, "failed to alloc memory\n");
+ return -ENOMEM;
+ }
+
+ dev->client = client;
+
+ gc = &dev->gpio_chip;
+ gc->direction_input = cy8c9540a_gpio_direction_input;
+ gc->direction_output = cy8c9540a_gpio_direction_output;
+ gc->get = cy8c9540a_gpio_get_value;
+ gc->set = cy8c9540a_gpio_set_value;
+ gc->set_drive = cy8c9540a_gpio_set_drive;
+
+ gc->can_sleep = 1;
+
+ gc->base = GPIO_BASE_ID;
+ gc->ngpio = NGPIO;
+ gc->label = client->name;
+ gc->owner = THIS_MODULE;
+ gc->to_irq = cy8c9540a_gpio_to_irq;
+
+ mutex_init(&dev->lock);
+
+ /* Whoami */
+ dev_id = i2c_smbus_read_byte_data(client, REG_DEVID_STAT);
+ if (dev_id < 0) {
+ dev_err(&client->dev, "can't read device ID\n");
+ ret = dev_id;
+ goto err;
+ }
+ dev_info(&client->dev, "dev_id=0x%x\n", dev_id & 0xff);
+ if (DEVID_FAMILY_CY8C9540A != (dev_id & DEVID_FAMILY_MASK)) {
+ dev_err(&client->dev, "unknown/unsupported dev_id 0x%x\n",
+ dev_id & 0xff);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = cy8c9540a_setup(dev);
+ if (ret) {
+ goto err;
+ }
+
+ ret = cy8c9540a_irq_setup(dev);
+ if (ret) {
+ goto err;
+ }
+ ret = gpiochip_add(&dev->gpio_chip);
+ if (ret) {
+ dev_err(&client->dev, "gpiochip_add failed %d\n", ret);
+ goto err_irq;
+ }
+
+ dev->pwm_chip.dev = &client->dev;
+ dev->pwm_chip.ops = &cy8c9540a_pwm_ops;
+ dev->pwm_chip.base = PWM_BASE_ID;
+ dev->pwm_chip.npwm = NPWM;
+
+ ret = pwmchip_add(&dev->pwm_chip);
+ if (ret) {
+ dev_err(&client->dev, "pwmchip_add failed %d\n", ret);
+ goto err_gpiochip;
+ }
+
+ i2c_set_clientdata(client, dev);
+
+ return 0;
+err_gpiochip:
+ if(gpiochip_remove(&dev->gpio_chip))
+ dev_warn(&client->dev, "gpiochip_remove failed\n");
+err_irq:
+ cy8c9540a_irq_teardown(dev);
+err:
+ mutex_destroy(&dev->lock);
+ kfree(dev);
+
+ return ret;
+}
+
+static int cy8c9540a_remove(struct i2c_client *client)
+{
+ struct cy8c9540a *dev = i2c_get_clientdata(client);
+ int ret = 0;
+ int err = 0;
+
+ ret = pwmchip_remove(&dev->pwm_chip);
+ if (ret < 0) {
+ dev_err(&client->dev, "pwmchip_remove failed %d\n", ret);
+ err = ret;
+ }
+
+ ret = gpiochip_remove(&dev->gpio_chip);
+ if (ret) {
+ dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
+ err = ret;
+ }
+
+ cy8c9540a_irq_teardown(dev);
+
+ mutex_destroy(&dev->lock);
+ kfree(dev);
+
+ return err;
+}
+
+static const struct i2c_device_id cy8c9540a_id[] = {
+ {DRV_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, cy8c9540a_id);
+
+static struct i2c_driver cy8c9540a_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ },
+ .probe = cy8c9540a_probe,
+ .remove = cy8c9540a_remove,
+ .id_table = cy8c9540a_id,
+};
+
+module_i2c_driver(cy8c9540a_driver);
+
+MODULE_AUTHOR("Josef Ahmad <josef.ahmad@linux.intel.com>");
+MODULE_DESCRIPTION("GPIO/PWM driver for CY8C9540A I/O expander");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/intel_cln_gip.h b/drivers/mfd/intel_cln_gip.h
new file mode 100644
index 0000000..18ab774
--- /dev/null
+++ b/drivers/mfd/intel_cln_gip.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton GIP (GPIO/I2C) driver
+ */
+
+#ifndef __INTEL_CLNGIP_H__
+#define __INTEL_CLNGIP_H__
+
+#include <linux/i2c.h>
+#include <linux/pci.h>
+#include "../i2c/busses/i2c-designware-core.h"
+
+/* PCI BAR for register base address */
+#define GIP_I2C_BAR 0
+#define GIP_GPIO_BAR 1
+
+/**
+ * intel_cln_gpio_probe
+ *
+ * @param pdev: Pointer to GIP PCI device
+ * @return 0 success < 0 failure
+ *
+ * Perform GPIO-specific probing on behalf of the top-level GIP driver.
+ */
+int intel_cln_gpio_probe(struct pci_dev *pdev);
+
+/**
+ * intel_cln_gpio_remove
+ *
+ * @param pdev: Pointer to GIP PCI device
+ *
+ * Perform GPIO-specific resource release on behalf of the top-level GIP driver.
+ */
+void intel_cln_gpio_remove(struct pci_dev *pdev);
+
+/**
+ * intel_cln_gpio_isr
+ *
+ * @param irq: IRQ number to be served
+ * @param dev_id: used to distinguish the device (for shared interrupts)
+ *
+ * Perform GPIO-specific ISR of the top-level GIP driver.
+ */
+irqreturn_t intel_cln_gpio_isr(int irq, void *dev_id);
+
+/**
+ * intel_cln_gpio_save_state
+ *
+ * Save GPIO register state for system-wide suspend events and mask out
+ * interrupts.
+ */
+void intel_cln_gpio_save_state(void);
+
+/**
+ * intel_cln_gpio_restore_state
+ *
+ * Restore GPIO register state for system-wide resume events and clear out
+ * spurious interrupts.
+ */
+void intel_cln_gpio_restore_state(void);
+
+/**
+ * intel_cln_i2c_probe
+ * @param pdev: Pointer to GIP PCI device
+ * @param drvdata: private driver data
+ * @return 0 success < 0 failure
+ *
+ * Perform I2C-specific probing on behalf of the top-level GIP driver.
+ */
+int intel_cln_i2c_probe(struct pci_dev *pdev,
+ struct dw_i2c_dev **drvdata);
+
+/**
+ * intel_cln_i2c_remove
+ * @param pdev: Pointer to GIP PCI device
+ * @param dev: Pointer to I2C private data
+ *
+ * Perform I2C-specific resource release on behalf of the top-level GIP driver.
+ */
+void intel_cln_i2c_remove(struct pci_dev *pdev,
+ struct dw_i2c_dev *dev);
+
+#endif /* __INTEL_CLNGIP_H__ */
diff --git a/drivers/mfd/intel_cln_gip_core.c b/drivers/mfd/intel_cln_gip_core.c
new file mode 100644
index 0000000..7464b32
--- /dev/null
+++ b/drivers/mfd/intel_cln_gip_core.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton GIP (GPIO/I2C) PCI driver
+ *
+ * PCI glue logic for Clanton GIP driver.
+ * Clanton GIP is a single PCI function exporting a GPIO and an I2C device.
+ * The PCI driver performs the bus-dependent probe/release operations, and
+ * call into GPIO/I2C specific modules for handling the two diffrerent
+ * functionalities.
+ */
+
+#include <asm/cln.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "intel_cln_gip.h"
+
+static unsigned int enable_msi = 1;
+module_param(enable_msi, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_msi, "Enable PCI MSI mode");
+
+static unsigned int i2c = 1;
+module_param(i2c, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(i2c, "Register I2C adapter");
+
+static unsigned int gpio = 1;
+module_param(gpio, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(gpio, "Register GPIO chip");
+
+/* GIP private data, supporting only a single instance of the device. */
+struct intel_cln_gip_data {
+ struct pci_dev *pci_device;
+ struct dw_i2c_dev *i2c_drvdata;
+};
+
+/**
+ * intel_cln_gip_handler
+ *
+ * @param irq: IRQ number to be served
+ * @param dev_id: device private data
+ *
+ * Top-level interrupt handler for GIP driver.
+ * It calls into the appropriate sub-routines and gathers the return values.
+ */
+static irqreturn_t intel_cln_gip_handler(int irq, void *dev_id)
+{
+ irqreturn_t ret_i2c = IRQ_NONE;
+ irqreturn_t ret_gpio = IRQ_NONE;
+ struct intel_cln_gip_data *data = (struct intel_cln_gip_data *)dev_id;
+
+ mask_pvm(data->pci_device);
+
+ if (likely(i2c)) {
+ /* Only I2C gets platform data */
+ ret_i2c = i2c_dw_isr(irq, data->i2c_drvdata);
+ }
+
+ if (likely(gpio)) {
+ ret_gpio = intel_cln_gpio_isr(irq, NULL);
+ }
+
+ unmask_pvm(data->pci_device);
+
+ if (likely(IRQ_HANDLED == ret_i2c || IRQ_HANDLED == ret_gpio))
+ return IRQ_HANDLED;
+
+ /* Each sub-ISR routine returns either IRQ_HANDLED or IRQ_NONE. */
+ return IRQ_NONE;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(intel_cln_gip_ids) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0934), },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, intel_cln_gip_ids);
+
+#ifdef CONFIG_PM
+
+/**
+ * cln_gip_suspend
+ *
+ * @param device: Pointer to device
+ * @return 0 success < 0 failure
+ *
+ * Prepare GIP for system-wide transition to sleep state.
+ * Save context, disable GPIO chip and I2C adapter, transition PCI device into
+ * low-power state.
+ */
+static int cln_gip_suspend(struct device *dev)
+{
+ int err = 0;
+ struct intel_cln_gip_data *data = NULL;
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ data = (struct intel_cln_gip_data *)pci_get_drvdata(pdev);
+
+ i2c_dw_disable(data->i2c_drvdata);
+ intel_cln_gpio_save_state();
+
+ err = pci_save_state(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_save_state failed\n");
+ return err;
+ }
+
+ err = pci_set_power_state(pdev, PCI_D3hot);
+ if (err) {
+ dev_err(&pdev->dev, "pci_set_power_state failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * cln_gip_resume
+ *
+ * @param device: Pointer to device
+ * @return 0 success < 0 failure
+ *
+ * Prepare GIP for system-wide transition to fully active state.
+ * Set PCI device into full-power state, restore context, enable I2C adapter
+ * and GPIO chip.
+ */
+static int cln_gip_resume(struct device *dev)
+{
+ int err = 0;
+ struct intel_cln_gip_data *data = NULL;
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ data = (struct intel_cln_gip_data *)pci_get_drvdata(pdev);
+
+ err = pci_set_power_state(pdev, PCI_D0);
+ if (err) {
+ dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+ return err;
+ }
+
+ pci_restore_state(pdev);
+
+ intel_cln_gpio_restore_state();
+ i2c_dw_init(data->i2c_drvdata);
+
+ return 0;
+}
+
+#else
+#define cln_gip_suspend NULL
+#define cln_gip_resume NULL
+#endif
+
+static const struct dev_pm_ops cln_gip_pm_ops = {
+ .resume = cln_gip_resume,
+ .suspend = cln_gip_suspend,
+};
+
+/**
+ * intel_cln_gip_probe
+ *
+ * @param pdev: Pointer to GIP PCI device
+ * @param id: GIP PCI Device ID
+ * @return 0 success < 0 failure
+ *
+ * GIP PCI driver probing. Calls into the appropriate probe routines for GPIO
+ * and I2C too.
+ */
+static int intel_cln_gip_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int retval = 0;
+ struct intel_cln_gip_data *gip_drvdata = NULL;
+
+ retval = pci_enable_device(pdev);
+ if (retval)
+ return retval;
+
+ retval = pci_request_regions(pdev, "cln-gip");
+ if (retval) {
+ dev_err(&pdev->dev, "error requesting PCI region\n");
+ goto err_pcidev_disable;
+ }
+
+ gip_drvdata = kzalloc(sizeof(struct intel_cln_gip_data), GFP_KERNEL);
+ if (NULL == gip_drvdata) {
+ retval = -ENOMEM;
+ goto err_pciregions_release;
+ }
+ pci_set_drvdata(pdev, gip_drvdata);
+
+ gip_drvdata->pci_device = pdev;
+
+ if (gpio) {
+ retval = intel_cln_gpio_probe(pdev);
+ if (retval)
+ goto err_release_drvdata;
+ }
+
+ if (i2c) {
+ retval = intel_cln_i2c_probe(pdev,
+ (struct dw_i2c_dev **)&gip_drvdata->i2c_drvdata);
+ if (retval)
+ goto err_release_drvdata;
+ }
+
+ if (enable_msi) {
+ pci_set_master(pdev);
+ retval = pci_enable_msi(pdev);
+ if (retval)
+ goto err_release_drvdata;
+ }
+
+ /*
+ * Request a shared IRQ.
+ * Since the dev_id cannot be NULL, it points to PCI device descriptor
+ * if I2C is not registered.
+ */
+ retval = request_irq(pdev->irq, intel_cln_gip_handler, IRQF_SHARED,
+ "intel_cln_gip", gip_drvdata);
+ if (retval) {
+ dev_err(&pdev->dev, "error requesting IRQ\n");
+ goto err;
+ }
+
+ return 0;
+
+err_release_drvdata:
+ pci_set_drvdata(pdev, NULL);
+ kfree(gip_drvdata);
+err:
+ if (enable_msi)
+ pci_disable_msi(pdev);
+err_pciregions_release:
+ pci_release_regions(pdev);
+err_pcidev_disable:
+ pci_disable_device(pdev);
+
+ return retval;
+}
+
+/**
+ * intel_cln_gip_remove
+ *
+ * @param pdev: Pointer to GIP PCI device
+ *
+ * Release resources. Calls into GPIO/I2C dedicate routines too.
+ */
+static void intel_cln_gip_remove(struct pci_dev *pdev)
+{
+ struct intel_cln_gip_data *data = NULL;
+
+ data = (struct intel_cln_gip_data *)pci_get_drvdata(pdev);
+
+ if (NULL == data) {
+ dev_err(&pdev->dev, "%s: failure getting driver data\n",
+ __func__);
+ return;
+ }
+
+ free_irq(pdev->irq, data);
+
+ if (enable_msi) {
+ pci_clear_master(pdev);
+ if (pci_dev_msi_enabled(pdev))
+ pci_disable_msi(pdev);
+ }
+
+ if (i2c)
+ intel_cln_i2c_remove(pdev, data->i2c_drvdata);
+
+ if (gpio)
+ intel_cln_gpio_remove(pdev);
+
+ pci_set_drvdata(pdev, NULL);
+ kfree(data);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static struct pci_driver intel_cln_gip_driver = {
+ .name = "intel_cln_gip",
+ .id_table = intel_cln_gip_ids,
+ .probe = intel_cln_gip_probe,
+ .remove = intel_cln_gip_remove,
+ .driver = {
+ .pm = &cln_gip_pm_ops,
+ },
+};
+
+static int intel_cln_gip_init(void)
+{
+ return pci_register_driver(&intel_cln_gip_driver);
+}
+
+static void intel_cln_gip_exit(void)
+{
+ pci_unregister_driver(&intel_cln_gip_driver);
+}
+
+module_init(intel_cln_gip_init);
+module_exit(intel_cln_gip_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Clanton GIP driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/mfd/intel_cln_gip_gpio.c b/drivers/mfd/intel_cln_gip_gpio.c
new file mode 100644
index 0000000..15d4058
--- /dev/null
+++ b/drivers/mfd/intel_cln_gip_gpio.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton GIP (GPIO/I2C) - GPIO-specific PCI and core driver
+ *
+ * PCI glue logic and core driver for Clanton GIP/GPIO.
+ * The GIP GPIO device is the DesignWare GPIO. This file defines the PCI glue
+ * for this driver and as well as the core logic for the device.
+ * Please note only a single instance of the GPIO device is supported.
+ * The default number of GPIO is 8, all interrupt-capable.
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include "intel_cln_gip.h"
+
+static void cln_gpio_restrict_release(struct device *dev) {}
+static struct platform_device cln_gpio_restrict_pdev =
+{
+ .name = "cln-gpio-restrict-sc",
+ .dev.release = cln_gpio_restrict_release,
+};
+struct uio_info *info;
+
+/* The base GPIO number under GPIOLIB framework */
+#define INTEL_CLN_GIP_GPIO_BASE 8
+
+/* The default number of South-Cluster GPIO on Clanton. */
+#define INTEL_CLN_GIP_NGPIO 8
+
+/*
+ * The default base IRQ for searching and allocating the range of GPIO IRQ
+ * descriptors.
+ */
+#define INTEL_CLN_GIP_GPIO_IRQBASE 56
+
+/* The GPIO private data. */
+static struct gpio_chip *gc;
+static struct irq_chip_generic *igc;
+static void __iomem *reg_base;
+static spinlock_t lock;
+static int irq_base;
+static unsigned int n_gpio = INTEL_CLN_GIP_NGPIO;
+static unsigned int gpio_irqbase = INTEL_CLN_GIP_GPIO_IRQBASE;
+
+/* Store GPIO context across system-wide suspend/resume transitions */
+static struct gpio_saved_regs {
+ u32 data;
+ u32 dir;
+ u32 int_en;
+ u32 int_mask;
+ u32 int_type;
+ u32 int_pol;
+ u32 int_deb;
+} saved_regs;
+
+/* PortA registers set. Note other ports are unused */
+#define PORTA_DATA 0x00 /* Data */
+#define PORTA_DIR 0x04 /* Direction */
+#define PORTA_INT_EN 0x30 /* Interrupt enable */
+#define PORTA_INT_MASK 0x34 /* Interrupt mask */
+#define PORTA_INT_TYPE_LEVEL 0x38 /* Interrupt level*/
+#define PORTA_INT_POLARITY 0x3c /* Interrupt polarity */
+#define PORTA_INT_STATUS 0x40 /* Interrupt status */
+#define PORTA_INT_RAW_STATUS 0x44 /* Interrupt raw status */
+#define PORTA_DEBOUNCE 0x48 /* Debounce enable */
+#define PORTA_INT_EOI 0x4c /* Clear interrupt */
+#define PORTA_EXT 0x50 /* External */
+
+module_param(n_gpio, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(n_gpio, "Number of GPIO");
+
+module_param(gpio_irqbase, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(gpio_irqbase, "Base IRQ for GPIO range");
+
+/**
+ * intel_cln_gpio_get
+ * @param chip: Pointer to GPIO chip registered by GPIOLIB
+ * @param offset: the GPIO number within the GPIOLIB chip
+ * @return 0 if GPIO is deasserted, 1 if GPIO is asserted
+ *
+ * Read back the value of a GPIO.
+ */
+static int intel_cln_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ void __iomem *reg_ext = reg_base + PORTA_EXT;
+ u32 val_ext = ioread32(reg_ext);
+
+ val_ext &= BIT(offset % 32);
+ return (val_ext > 0);
+}
+
+/**
+ * intel_cln_gpio_set
+ * @param chip: Pointer to GPIO chip registered by GPIOLIB
+ * @param offset: the GPIO number within the GPIOLIB chip
+ *
+ * Set value of a GPIO.
+ */
+static void intel_cln_gpio_set(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ void __iomem *reg_data = reg_base + PORTA_DATA;
+ u32 val_data = 0;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&lock, flags);
+
+ val_data = ioread32(reg_data);
+ if (value)
+ iowrite32(val_data | BIT(offset % 32), reg_data);
+ else
+ iowrite32(val_data & ~BIT(offset % 32), reg_data);
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_direction_input
+ * @param chip: Pointer to GPIO chip registered by GPIOLIB
+ * @param offset: the GPIO number within the GPIOLIB chip
+ * @return always 0 (success)
+ *
+ * Set direction of a GPIO as input.
+ */
+static int intel_cln_gpio_direction_input(struct gpio_chip *chip,
+ unsigned offset)
+{
+ u32 val_dir = 0;
+ void __iomem *reg_dir = reg_base + PORTA_DIR;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&lock, flags);
+
+ val_dir = ioread32(reg_dir);
+ iowrite32(val_dir & ~BIT(offset % 32), reg_dir);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ return 0;
+}
+
+/**
+ * intel_cln_gpio_direction_output
+ * @param chip: Pointer to GPIO chip registered by GPIOLIB
+ * @param offset: the GPIO number within the GPIOLIB chip
+ * @param value: value to be driven to the GPIO
+ * @return always 0 (success)
+ *
+ * Set the default value of a GPIO, and then set direction as output.
+ */
+static int intel_cln_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ u32 val_dir = 0;
+ void __iomem *reg_dir = reg_base + PORTA_DIR;
+ unsigned long flags = 0;
+
+ /* Ensure glitch-free operation. */
+ intel_cln_gpio_set(chip, offset, value);
+
+ spin_lock_irqsave(&lock, flags);
+
+ val_dir = ioread32(reg_dir);
+ iowrite32(val_dir | BIT(offset % 32), reg_dir);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ return 0;
+}
+
+/**
+ * intel_cln_gpio_set_debounce
+ * @param chip: Pointer to GPIO chip registered by GPIOLIB
+ * @param offset: the GPIO number within the GPIOLIB chip
+ * @param debounce: 1 to enable, 0 to disable
+ * @return always 0 (success)
+ *
+ * Enable/disable interrupt debounce logic for a GPIO.
+ */
+static int intel_cln_gpio_set_debounce(struct gpio_chip *chip,
+ unsigned offset, unsigned debounce)
+{
+ u32 val_deb = 0;
+ void __iomem *reg_deb = reg_base + PORTA_DEBOUNCE;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&lock, flags);
+
+ val_deb = ioread32(reg_deb);
+ if (debounce)
+ iowrite32(val_deb | BIT(offset % 32), reg_deb);
+ else
+ iowrite32(val_deb & ~BIT(offset % 32), reg_deb);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ return 0;
+}
+
+/**
+ * intel_cln_gpio_irq_type
+ * @param irq_data: Pointer to information about the IRQ
+ * @param type: set the triggering type of the interrupt
+ * @return always 0 (success)
+ *
+ * Set interrupt triggering type for a GPIO.
+ */
+static int intel_cln_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+ int ret = 0;
+ unsigned long flags = 0;
+ void __iomem *reg_level = reg_base + PORTA_INT_TYPE_LEVEL;
+ void __iomem *reg_pol = reg_base + PORTA_INT_POLARITY;
+ u32 val_level = 0;
+ u32 val_pol = 0;
+ u32 gpio = 0;
+
+ if (NULL == d) {
+ pr_err("%s(): null irq_data\n", __func__);
+ return -EFAULT;
+ }
+
+ gpio = d->irq - irq_base;
+
+ spin_lock_irqsave(&lock, flags);
+
+ val_level = ioread32(reg_level);
+ val_pol = ioread32(reg_pol);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ iowrite32(val_level | BIT(gpio % 32), reg_level);
+ iowrite32(val_pol | BIT(gpio % 32), reg_pol);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ iowrite32(val_level | BIT(gpio % 32), reg_level);
+ iowrite32(val_pol & ~BIT(gpio % 32), reg_pol);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ iowrite32(val_level & ~BIT(gpio % 32), reg_level);
+ iowrite32(val_pol | BIT(gpio % 32), reg_pol);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ iowrite32(val_level & ~BIT(gpio % 32), reg_level);
+ iowrite32(val_pol & ~BIT(gpio % 32), reg_pol);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ return ret;
+}
+
+/**
+ * intel_cln_gpio_irq_unmask
+ * @param irq_data: Pointer to information about the IRQ
+ *
+ * Unmask interrupts for a GPIO.
+ */
+static void intel_cln_gpio_irq_unmask(struct irq_data *d)
+{
+ unsigned long flags = 0;
+ void __iomem *reg_mask = reg_base + PORTA_INT_MASK;
+ u32 val_mask = 0;
+ unsigned gpio = 0;
+
+ if (NULL == d) {
+ pr_err("%s(): null irq_data\n", __func__);
+ return;
+ }
+
+ gpio = d->irq - irq_base;
+
+ spin_lock_irqsave(&lock, flags);
+ val_mask = ioread32(reg_mask);
+ iowrite32(val_mask | BIT(gpio % 32), reg_mask);
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_irq_mask
+ * @param irq_data: Pointer to information about the IRQ
+ *
+ * Mask interrupts for a GPIO.
+ */
+static void intel_cln_gpio_irq_mask(struct irq_data *d)
+{
+ unsigned long flags = 0;
+ void __iomem *reg_mask = reg_base + PORTA_INT_MASK;
+ u32 val_mask = 0;
+ unsigned gpio = 0;
+
+ if (NULL == d) {
+ pr_err("%s(): null irq_data\n", __func__);
+ return;
+ }
+
+ gpio = d->irq - irq_base;
+
+ spin_lock_irqsave(&lock, flags);
+ val_mask = ioread32(reg_mask);
+ iowrite32(val_mask & ~BIT(gpio % 32), reg_mask);
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_irq_enable
+ * @param irq_data: Pointer to information about the IRQ
+ *
+ * Enable interrupts for a GPIO.
+ */
+static void intel_cln_gpio_irq_enable(struct irq_data *d)
+{
+ unsigned long flags = 0;
+ void __iomem *reg_inte = reg_base + PORTA_INT_EN;
+ u32 val_inte = 0;
+ unsigned gpio = 0;
+
+ if (NULL == d) {
+ pr_err("%s(): null irq_data\n", __func__);
+ return;
+ }
+
+ gpio = d->irq - irq_base;
+
+ spin_lock_irqsave(&lock, flags);
+ val_inte = ioread32(reg_inte);
+ iowrite32(val_inte | BIT(gpio % 32), reg_inte);
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_irq_disable
+ * @param irq_data: Pointer to information about the IRQ
+ *
+ * Disable interrupts for a GPIO.
+ */
+static void intel_cln_gpio_irq_disable(struct irq_data *d)
+{
+ unsigned long flags = 0;
+ void __iomem *reg_inte = reg_base + PORTA_INT_EN;
+ u32 val_inte = 0;
+ unsigned gpio = 0;
+
+ if (NULL == d) {
+ pr_err("%s(): null irq_data\n", __func__);
+ return;
+ }
+
+ gpio = d->irq - irq_base;
+
+ spin_lock_irqsave(&lock, flags);
+ val_inte = ioread32(reg_inte);
+ iowrite32(val_inte & ~BIT(gpio % 32), reg_inte);
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_to_irq
+ * @param chip: Pointer to GPIO chip registered by GPIOLIB
+ * @param offset: the GPIO number within the GPIOLIB chip
+ * @return IRQ associated to GPIO
+ *
+ * Compute the IRQ number based on the GPIO.
+ */
+static int intel_cln_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return irq_base + offset;
+}
+
+/**
+ * intel_cln_gpio_isr
+ * @param irq: IRQ number
+ * @param dev_id: cookie used to tell what instance of the driver the interrupt
+ * belongs to
+ * @return IRQ_HANDLED if interrupt served, IRQ_NONE if no interrupt pending
+ *
+ * Interrupt Service Routine for GPIO. Identify which GPIOs (if any) is pending
+ * for interrupt to be served, acknowledge the interrupt and serve it.
+ */
+irqreturn_t intel_cln_gpio_isr(int irq, void *dev_id)
+{
+ irqreturn_t ret = IRQ_NONE;
+ u32 pending = 0, gpio = 0;
+ void __iomem *reg_pending = reg_base + PORTA_INT_STATUS;
+ void __iomem *reg_eoi = reg_base + PORTA_INT_EOI;
+
+ /* Which pin (if any) triggered the interrupt */
+ while ((pending = ioread32(reg_pending))) {
+ /*
+ * Acknowledge all the asserted GPIO interrupt lines before
+ * serving them, so that we don't lose an edge.
+ * This has only effect on edge-triggered interrupts.
+ */
+ iowrite32(pending, reg_eoi);
+
+ /* Serve each asserted interrupt */
+ do {
+ gpio = __ffs(pending);
+ generic_handle_irq(
+ gpio_to_irq(INTEL_CLN_GIP_GPIO_BASE + gpio));
+ pending &= ~BIT(gpio);
+ ret = IRQ_HANDLED;
+ } while(pending);
+ }
+
+ return ret;
+}
+
+/**
+ * intel_cln_gpio_save_state
+ *
+ * Save GPIO register state for system-wide suspend events and mask out
+ * interrupts.
+ */
+void intel_cln_gpio_save_state(void)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&lock, flags);
+
+ saved_regs.int_mask = ioread32(reg_base + PORTA_INT_MASK);
+ saved_regs.int_en = ioread32(reg_base + PORTA_INT_EN);
+ saved_regs.int_deb = ioread32(reg_base + PORTA_DEBOUNCE);
+ saved_regs.int_pol = ioread32(reg_base + PORTA_INT_POLARITY);
+ saved_regs.int_type = ioread32(reg_base + PORTA_INT_TYPE_LEVEL);
+ saved_regs.dir = ioread32(reg_base + PORTA_DIR);
+ saved_regs.data = ioread32(reg_base + PORTA_DATA);
+
+ /* Mask out interrupts */
+ iowrite32(0xffffffff, reg_base + PORTA_INT_MASK);
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_restore_state
+ *
+ * Restore GPIO register state for system-wide resume events and clear out
+ * spurious interrupts.
+ */
+void intel_cln_gpio_restore_state(void)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&lock, flags);
+
+ iowrite32(saved_regs.data, reg_base + PORTA_DATA);
+ iowrite32(saved_regs.dir, reg_base + PORTA_DIR);
+ iowrite32(saved_regs.int_type, reg_base + PORTA_INT_TYPE_LEVEL);
+ iowrite32(saved_regs.int_pol, reg_base + PORTA_INT_POLARITY);
+ iowrite32(saved_regs.int_deb, reg_base + PORTA_DEBOUNCE);
+ iowrite32(saved_regs.int_en, reg_base + PORTA_INT_EN);
+ iowrite32(saved_regs.int_mask, reg_base + PORTA_INT_MASK);
+
+ /* Clear out spurious interrupts */
+ iowrite32(0xffffffff, reg_base + PORTA_INT_EOI);
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/**
+ * intel_cln_gpio_probe
+ * @param pdev: Pointer to GIP PCI device
+ * @return 0 success < 0 failure
+ *
+ * Perform GPIO-specific probing on behalf of the top-level GIP driver.
+ * Initiate the GPIO device.
+ */
+int intel_cln_gpio_probe(struct pci_dev *pdev)
+{
+ int retval = 0;
+ resource_size_t start = 0, len = 0;
+
+ /* Get UIO memory */
+ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ /* Determine the address of the GPIO area */
+ start = pci_resource_start(pdev, GIP_GPIO_BAR);
+ len = pci_resource_len(pdev, GIP_GPIO_BAR);
+ if (!start || len == 0) {
+ dev_err(&pdev->dev, "bar%d not set\n", GIP_GPIO_BAR);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ reg_base = ioremap_nocache(start, len);
+ if (NULL == reg_base) {
+ dev_err(&pdev->dev, "I/O memory remapping failed\n");
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ memset(&saved_regs, 0x0, sizeof(saved_regs));
+
+ gc = kzalloc(sizeof(struct gpio_chip), GFP_KERNEL);
+ if (!gc) {
+ retval = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ if (n_gpio == 0 || n_gpio > INTEL_CLN_GIP_NGPIO) {
+ dev_err(&pdev->dev, "n_gpio outside range [1,%d]\n",
+ INTEL_CLN_GIP_NGPIO);
+ retval = -EINVAL;
+ goto err_free_gpiochip;
+ }
+
+ gc->label = "intel_cln_gip_gpio";
+ gc->owner = THIS_MODULE;
+ gc->direction_input = intel_cln_gpio_direction_input;
+ gc->direction_output = intel_cln_gpio_direction_output;
+ gc->get = intel_cln_gpio_get;
+ gc->set = intel_cln_gpio_set;
+ gc->set_debounce = intel_cln_gpio_set_debounce;
+ gc->to_irq = intel_cln_gpio_to_irq;
+ gc->base = INTEL_CLN_GIP_GPIO_BASE;
+ gc->ngpio = n_gpio;
+ gc->can_sleep = 0;
+ retval = gpiochip_add(gc);
+ if (retval) {
+ dev_err(&pdev->dev, "failure adding GPIO chip\n");
+ goto err_free_gpiochip;
+ }
+
+ spin_lock_init(&lock);
+
+ /*
+ * Allocate a range of IRQ descriptor for the available GPIO.
+ * IRQs are allocated dynamically.
+ */
+ irq_base = irq_alloc_descs(-1, gpio_irqbase, n_gpio, NUMA_NO_NODE);
+ if (irq_base < 0) {
+ dev_err(&pdev->dev, "failure adding GPIO IRQ descriptors\n");
+ goto err_remove_gpiochip;
+ }
+
+ retval = platform_device_register(&cln_gpio_restrict_pdev);
+ if (retval < 0){
+ goto err_free_irq_descs;
+ }
+
+ igc = irq_alloc_generic_chip("intel_cln_gip_gpio", 1, irq_base,
+ reg_base, handle_simple_irq);
+ if (NULL == igc) {
+ retval = -ENOMEM;
+ goto err_free_irq_descs;
+ }
+
+ /* UIO */
+ info->mem[0].addr = start;
+ info->mem[0].internal_addr = reg_base;
+ info->mem[0].size = len;
+ info->mem[0].memtype = UIO_MEM_PHYS;
+ info->mem[0].name = "gpio_regs";
+ info->name = "gpio uio";
+ info->version = "0.0.1";
+
+ if (uio_register_device(&pdev->dev, info))
+ goto err_free_irq_descs;
+
+ pr_info("%s UIO addr 0x%08x internal_addr 0x%08x size %lu memtype %d\n",
+ __func__, info->mem[0].addr, info->mem[0].internal_addr,
+ info->mem[0].size, info->mem[0].memtype);
+ igc->chip_types->chip.irq_mask = intel_cln_gpio_irq_mask;
+ igc->chip_types->chip.irq_unmask = intel_cln_gpio_irq_unmask;
+ igc->chip_types->chip.irq_set_type = intel_cln_gpio_irq_type;
+ igc->chip_types->chip.irq_enable = intel_cln_gpio_irq_enable;
+ igc->chip_types->chip.irq_disable = intel_cln_gpio_irq_disable;
+
+ irq_setup_generic_chip(igc, IRQ_MSK(n_gpio), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+
+ return 0;
+
+err_free_irq_descs:
+ irq_free_descs(irq_base, n_gpio);
+err_remove_gpiochip:
+ if (0 != gpiochip_remove(gc))
+ dev_err(&pdev->dev, "failed removing gpio_chip\n");
+err_free_gpiochip:
+ kfree(gc);
+err_iounmap:
+ iounmap(reg_base);
+exit:
+ if (info != NULL)
+ kfree(info);
+ return retval;
+}
+
+/**
+ * intel_cln_gpio_remove
+ * @param pdev: Pointer to GIP PCI device
+ *
+ * Perform GPIO-specific resource release on behalf of the top-level GIP
+ * driver.
+ */
+void intel_cln_gpio_remove(struct pci_dev *pdev)
+{
+ if (NULL == igc) {
+ dev_err(&pdev->dev, "null pointer to irq_generic_chip\n");
+ return;
+ }
+ if (NULL == gc) {
+ dev_err(&pdev->dev, "null pointer to gpio_chip\n");
+ return;
+ }
+
+ /* Tear down IRQ descriptors */
+ irq_remove_generic_chip(igc, IRQ_MSK(n_gpio), 0,
+ IRQ_NOREQUEST | IRQ_NOPROBE);
+ kfree(igc);
+ irq_free_descs(irq_base, n_gpio);
+
+ platform_device_unregister(&cln_gpio_restrict_pdev);
+
+ /* Release GPIO chip */
+ if (0 != gpiochip_remove(gc))
+ dev_err(&pdev->dev, "failed removing gpio_chip\n");
+
+
+ if (info != NULL){
+ uio_unregister_device(info);
+ iounmap(info->mem[0].internal_addr);
+ kfree(info);
+ }
+
+ kfree(gc);
+ iounmap(reg_base);
+}
diff --git a/drivers/mfd/intel_cln_gip_i2c.c b/drivers/mfd/intel_cln_gip_i2c.c
new file mode 100644
index 0000000..f2fa6a5
--- /dev/null
+++ b/drivers/mfd/intel_cln_gip_i2c.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton GIP (GPIO/I2C) - I2C-specific PCI driver
+ *
+ * PCI glue logic for Clanton GIP/I2C.
+ * The GIP I2C device is the DesignWare I2C. This file defines the PCI glue
+ * for this driver and is heavily based on
+ * on drivers/i2c/busses/i2c-designware-pcidrv.c. Also, it relies on
+ * drivers/i2c/busses/i2c-designware-core.c for the core logic.
+ * Please note only a single instance of the I2C device is supported.
+ */
+
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "intel_cln_gip.h"
+
+enum dw_pci_ctl_id_t {
+ clanton_0,
+};
+
+static unsigned int i2c_std_mode;
+module_param(i2c_std_mode, uint, S_IRUSR);
+MODULE_PARM_DESC(i2c_std_mode, "Force I2C standard mode");
+
+#define INTEL_CLN_STD_CFG (DW_IC_CON_MASTER | \
+ DW_IC_CON_SLAVE_DISABLE | \
+ DW_IC_CON_RESTART_EN)
+
+static struct dw_pci_controller cln_gip_i2c_controller = {
+ .bus_num = 0,
+ .bus_cfg = INTEL_CLN_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 16,
+ .rx_fifo_depth = 16,
+ .clk_khz =
+#ifdef CONFIG_INTEL_CLN_SOC_FPGAEMU
+ 14000,
+#else
+ 33000,
+#endif
+ .explicit_stop = 1,
+};
+
+static struct i2c_algorithm i2c_dw_algo = {
+ .master_xfer = i2c_dw_xfer,
+ .functionality = i2c_dw_func,
+};
+
+/**
+ * i2c_dw_get_clk_rate_khz
+ * @param dev: Pointer to I2C device private data
+ * @return clock rate in kHz
+ *
+ * Ancillary function returning the frequency of the clock supplied to the
+ * interface.
+ */
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+ return dev->controller->clk_khz;
+}
+
+/**
+ * intel_cln_i2c_probe
+ * @param pdev: Pointer to GIP PCI device
+ * @param drvdata: private driver data
+ * @return 0 success < 0 failure
+ *
+ * Perform I2C-specific probing on behalf of the top-level GIP driver.
+ * Also call into I2C core driver routines for initiating the device.
+ */
+int intel_cln_i2c_probe(struct pci_dev *pdev,
+ struct dw_i2c_dev **drvdata)
+{
+ int retval = 0;
+ resource_size_t start = 0, len = 0;
+ struct dw_i2c_dev *dev = NULL;
+ struct i2c_adapter *adap = NULL;
+ void __iomem *reg_base = NULL;
+ struct dw_pci_controller *controller = NULL;
+
+ controller = &cln_gip_i2c_controller;
+
+ /* Clanton default configuration is fast mode, unless otherwise asked */
+ if (i2c_std_mode)
+ controller->bus_cfg = INTEL_CLN_STD_CFG | DW_IC_CON_SPEED_STD;
+
+ /* Determine the address of the I2C area */
+ start = pci_resource_start(pdev, GIP_I2C_BAR);
+ len = pci_resource_len(pdev, GIP_I2C_BAR);
+ if (!start || len == 0) {
+ dev_err(&pdev->dev, "bar%d not set\n", GIP_I2C_BAR);
+ retval = -ENODEV;
+ goto err;
+ }
+
+ reg_base = ioremap_nocache(start, len);
+ if (!reg_base) {
+ dev_err(&pdev->dev, "I/O memory remapping failed\n");
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+ if (!dev) {
+ retval = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ init_completion(&dev->cmd_complete);
+ mutex_init(&dev->lock);
+ dev->clk = NULL;
+ dev->controller = controller;
+ dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+ dev->base = reg_base;
+ dev->dev = get_device(&pdev->dev);
+ dev->functionality =
+ I2C_FUNC_I2C |
+ I2C_FUNC_10BIT_ADDR |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK;
+ dev->master_cfg = controller->bus_cfg;
+
+ *drvdata = dev;
+
+ dev->tx_fifo_depth = controller->tx_fifo_depth;
+ dev->rx_fifo_depth = controller->rx_fifo_depth;
+ dev->explicit_stop = controller->explicit_stop;
+ retval = i2c_dw_init(dev);
+ if (retval)
+ goto err_release_drvdata;
+
+ adap = &dev->adapter;
+ i2c_set_adapdata(adap, dev);
+ adap->owner = THIS_MODULE;
+ adap->class = 0;
+ adap->algo = &i2c_dw_algo;
+ adap->dev.parent = &pdev->dev;
+ adap->nr = controller->bus_num;
+ snprintf(adap->name, sizeof(adap->name), "intel_cln_gip_i2c");
+
+ i2c_dw_disable_int(dev);
+ i2c_dw_clear_int(dev);
+ retval = i2c_add_numbered_adapter(adap);
+ if (retval) {
+ dev_err(&pdev->dev, "failure adding I2C adapter\n");
+ goto err_release_drvdata;
+ }
+
+ return 0;
+
+err_release_drvdata:
+ put_device(&pdev->dev);
+ kfree(dev);
+err_iounmap:
+ iounmap(reg_base);
+err:
+ return retval;
+}
+
+/**
+ * intel_cln_i2c_remove
+ * @param pdev: Pointer to GIP PCI device
+ * @param dev: Pointer to I2C private data
+ *
+ * Perform I2C-specific resource release on behalf of the top-level GIP driver.
+ */
+void intel_cln_i2c_remove(struct pci_dev *pdev,
+ struct dw_i2c_dev *dev)
+{
+
+ if (NULL == dev) {
+ dev_err(&pdev->dev, "%s: failure getting driver data\n",
+ __func__);
+ return;
+ }
+
+ i2c_dw_disable(dev);
+ i2c_del_adapter(&dev->adapter);
+ iounmap(dev->base);
+
+ kfree(dev);
+}
diff --git a/drivers/mfd/intel_cln_gip_test.c b/drivers/mfd/intel_cln_gip_test.c
new file mode 100644
index 0000000..ea8d846
--- /dev/null
+++ b/drivers/mfd/intel_cln_gip_test.c
@@ -0,0 +1,1202 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton GIP (GPIO/I2C) Test module
+ *
+ * Clanton GIP + North-Cluster GPIO test module.
+ */
+
+#include <asm/tsc.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define DRIVER_NAME "intel_cln_gip_test"
+
+/**************************** Exported to LISA *******************************/
+
+/*
+ * Internally-used ioctl code. At the moment it is not reserved by any mainline
+ * driver.
+ */
+#define GIP_TEST_IOCTL_CODE 0xE0
+
+/*
+ * Integers for ioctl operation.
+ */
+#define IOCTL_CLN_GPIO_11 _IO(GIP_TEST_IOCTL_CODE, 0x00)
+#define IOCTL_CLN_GPIO_11_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x01)
+#define IOCTL_CLN_GPIO_12 _IO(GIP_TEST_IOCTL_CODE, 0x02)
+#define IOCTL_CLN_GPIO_12_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x03)
+#define IOCTL_CLN_GPIO_13 _IO(GIP_TEST_IOCTL_CODE, 0x04)
+#define IOCTL_CLN_GPIO_13_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x05)
+#define IOCTL_CLN_GPIO_14 _IO(GIP_TEST_IOCTL_CODE, 0x06)
+#define IOCTL_CLN_GPIO_14_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x07)
+#define IOCTL_CLN_GPIO_15 _IO(GIP_TEST_IOCTL_CODE, 0x08)
+#define IOCTL_CLN_GPIO_15_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x09)
+#define IOCTL_CLN_GPIO_16 _IO(GIP_TEST_IOCTL_CODE, 0x0A)
+#define IOCTL_CLN_GPIO_16_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x0B)
+#define IOCTL_CLN_GPIO_17 _IO(GIP_TEST_IOCTL_CODE, 0x0C)
+#define IOCTL_CLN_GPIO_17_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x0D)
+#define IOCTL_CLN_GPIO_19 _IO(GIP_TEST_IOCTL_CODE, 0x0E)
+#define IOCTL_CLN_GPIO_19_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x0F)
+#define IOCTL_CLN_GPIO_20 _IO(GIP_TEST_IOCTL_CODE, 0x10)
+#define IOCTL_CLN_GPIO_20_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x11)
+#define IOCTL_CLN_GPIO_21 _IO(GIP_TEST_IOCTL_CODE, 0x12)
+#define IOCTL_CLN_GPIO_21_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x13)
+#define IOCTL_CLN_GPIO_24 _IO(GIP_TEST_IOCTL_CODE, 0x14)
+#define IOCTL_CLN_GPIO_26 _IO(GIP_TEST_IOCTL_CODE, 0x15)
+#define IOCTL_CLN_GPIO_26_CLEANUP _IO(GIP_TEST_IOCTL_CODE, 0x16)
+/* Exercise callbacks for S0/S3 power-state transitions and vice-versa */
+#define IOCTL_CLN_GIP_SYSTEM_SUSPEND _IO(GIP_TEST_IOCTL_CODE, 0x17)
+#define IOCTL_CLN_GIP_SYSTEM_RESUME _IO(GIP_TEST_IOCTL_CODE, 0x18)
+
+#define GPIO_INT_EDGE_POS_LABEL "gpio-edge-pos"
+#define GPIO_INT_EDGE_NEG_LABEL "gpio-edge-neg"
+#define GPIO_INT_LEVEL_HIGH_LABEL "gpio-level-hi"
+#define GPIO_INT_LEVEL_LOW_LABEL "gpio-level-lo"
+#define GPIO_INT_BASIC_LABEL "gpio-edge-pos-basic"
+#define GPIO_PM_TEST_IRQ_LABEL "gpio_pm_test_irq"
+
+/*
+ * Board GPIO numbers.
+ * Mapping between the North/South cluster GPIO and GPIOLIB IDs.
+ */
+#define SUT_GPIO_NC_0 0x00
+#define SUT_GPIO_NC_1 0x01
+#define SUT_GPIO_NC_2 0x02
+#define SUT_GPIO_NC_3 0x03
+#define SUT_GPIO_NC_4 0x04
+#define SUT_GPIO_NC_5 0x05
+#define SUT_GPIO_NC_6 0x06
+#define SUT_GPIO_NC_7 0x07
+#define SUT_GPIO_SC_0 0x08
+#define SUT_GPIO_SC_1 0x09
+#define SUT_GPIO_SC_2 0x0A
+#define SUT_GPIO_SC_3 0x0B
+#define SUT_GPIO_SC_4 0x0C
+#define SUT_GPIO_SC_5 0x0D
+#define SUT_GPIO_SC_6 0x0E
+#define SUT_GPIO_SC_7 0x0F
+
+/*
+ * Bitbanged SPI bus numbers.
+ */
+#define GPIO_NC_BITBANG_SPI_BUS 0x0
+#define GPIO_SC_BITBANG_SPI_BUS 0x1
+
+/*****************************************************************************/
+
+/**
+ * struct intel_cln_gip_dev
+ *
+ * Structure to represent module state/data/etc
+ */
+struct intel_cln_gip_test_dev {
+ unsigned int opened;
+ struct platform_device *pldev; /* Platform device */
+ struct cdev cdev;
+ struct mutex open_lock;
+};
+
+static struct intel_cln_gip_test_dev gip_test_dev;
+static struct class *gip_test_class;
+static DEFINE_MUTEX(gip_test_mutex);
+static int gip_test_major;
+
+/* Private pointers to NC/SC bitbanged SPI devices */
+static struct platform_device *spi_gpio_nc_pdev = NULL;
+static struct platform_device *spi_gpio_sc_pdev = NULL;
+
+/*
+ * Level-triggered interrupt variables
+ */
+/* Level-triggered GPIO workqueue */
+static struct delayed_work work;
+/* Level-triggered interrupt counter */
+static unsigned int level_int_count;
+/* By default, a level-triggered interrupt is a low-level triggered */
+static int level_high_triggered = 0;
+
+/*
+ * Interrupt performance metrics variables and parameters
+ */
+/* How many captures */
+#define INT_PERF_TEST_CAPTURES 10000
+/* Timestamp for latency test interrupt handler */
+static cycles_t perf_t1;
+/* Captures to be returned to user space */
+static cycles_t deltas[INT_PERF_TEST_CAPTURES];
+/* Couldn't find the actual define for this */
+#define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
+
+static irqreturn_t gpio_pm_test_handler(int irq, void *dev_id)
+{
+ /* Do nothing, just acknowledge the IRQ subsystem */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_latency_handler(int irq, void *dev_id)
+{
+ /* t0 */
+ perf_t1 = get_cycles();
+
+ gpio_set_value(SUT_GPIO_SC_0, 0);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_basic_handler(int irq, void *dev_id)
+{
+ /* Do nothing, just acknowledge the IRQ subsystem */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_pos_edge_handler(int irq, void *dev_id)
+{
+ /* Do nothing, just acknowledge the IRQ subsystem */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_neg_edge_handler(int irq, void *dev_id)
+{
+ /* Do nothing, just acknowledge the IRQ subsystem */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gpio_level_handler(int irq, void *dev_id)
+{
+ /* Untrigger the interrupt */
+ gpio_set_value(SUT_GPIO_SC_7, level_high_triggered ? 0 : 1);
+
+ level_int_count ++;
+ if (level_int_count < 1000) {
+ /* Next task due in a jiffy */
+ schedule_delayed_work(&work, 1);
+ } else if (level_int_count == 1000){
+ /* OK */
+ } else {
+ /*
+ * We may get spurious interrupts. This because the TE requires
+ * some time to drive the actual value to the GPIO.
+ */
+ pr_info("Spurious interrupt\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void gpio_level_drive(struct work_struct *work)
+{
+ /* TE to trigger the interrupt */
+ gpio_set_value(SUT_GPIO_SC_7, level_high_triggered ? 1 : 0);
+}
+
+/*
+ * Define bitbanged SPI interface over Nort-Cluster South-Cluster GPIO blocks.
+ * Assign GPIO to SCK/MOSI/MISO
+ */
+static struct spi_gpio_platform_data spi_gpio_nc_data = {
+ .sck = SUT_GPIO_NC_3,
+ .mosi = SUT_GPIO_NC_4,
+ .miso = SUT_GPIO_NC_5,
+ .num_chipselect = 1,
+};
+static struct spi_gpio_platform_data spi_gpio_sc_data = {
+ .sck = SUT_GPIO_SC_2,
+ .mosi = SUT_GPIO_SC_3,
+ .miso = SUT_GPIO_SC_4,
+ .num_chipselect = 1,
+};
+
+/*
+ * Board information for SPI devices.
+ */
+static struct spi_board_info spi_gpio_nc_board_info[] = {
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 1000,
+ .bus_num = GPIO_NC_BITBANG_SPI_BUS,
+ .mode = SPI_MODE_0,
+ .platform_data = &spi_gpio_nc_data,
+ /* Assign GPIO to CS */
+ .controller_data = (void *)SUT_GPIO_NC_6,
+ },
+};
+static struct spi_board_info spi_gpio_sc_board_info[] = {
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 1000,
+ .bus_num = GPIO_SC_BITBANG_SPI_BUS,
+ .mode = SPI_MODE_0,
+ .platform_data = &spi_gpio_sc_data,
+ /* Assign GPIO to CS */
+ .controller_data = (void *)SUT_GPIO_SC_5,
+ },
+};
+
+/**
+ * gpio_sc_level_int
+ *
+ * Request level triggered IRQ for SUT_GPIO_SC_6 and register
+ * SUT_GPIO_SC_7 as output GPIO.
+ * If positive equals to 0, the IRQ is high-level triggered.
+ * Otherwise, low-level triggered.
+ * Mask the IRQ if requested.
+ */
+static int gpio_sc_level_int(int positive, int masking)
+{
+ int ret = 0;
+ int irq = -1;
+
+ unsigned long out_init_val =
+ (positive ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
+
+ level_high_triggered = positive;
+
+ /* Initialise workqueue task */
+ INIT_DELAYED_WORK(&work, gpio_level_drive);
+
+ if (!gpio_is_valid(SUT_GPIO_SC_6)) {
+ pr_err("gpio%d is invalid\n", SUT_GPIO_SC_6);
+ ret = -1;
+ goto fail;
+ }
+ if (!gpio_is_valid(SUT_GPIO_SC_7)) {
+ pr_err("gpio%d is invalid\n", SUT_GPIO_SC_7);
+ ret = -1;
+ goto fail;
+ }
+
+ ret = gpio_request_one(SUT_GPIO_SC_6, GPIOF_IN, "gpio_hi_level");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", SUT_GPIO_SC_6, ret);
+ goto fail;
+ }
+ ret = gpio_request_one(SUT_GPIO_SC_7, out_init_val, "gpio_output");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", SUT_GPIO_SC_7, ret);
+ goto fail_release_first_gpio;
+ }
+
+ irq = gpio_to_irq(SUT_GPIO_SC_6);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_6);
+ goto fail_release_second_gpio;
+ }
+
+ if (0 != (ret = request_irq(irq, gpio_level_handler,
+ positive ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW,
+ positive ? GPIO_INT_LEVEL_HIGH_LABEL : GPIO_INT_LEVEL_LOW_LABEL,
+ NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", SUT_GPIO_SC_6);
+ goto fail_release_second_gpio;
+ }
+
+ level_int_count = 0;
+
+ pr_info("Registered output gpio%d and IRQ for gpio%d\n", SUT_GPIO_SC_7,
+ SUT_GPIO_SC_6);
+
+ if (masking) {
+ disable_irq(gpio_to_irq(SUT_GPIO_SC_6));
+ pr_info("Masked gpio%d IRQ\n", SUT_GPIO_SC_6);
+ }
+
+ /*
+ * Submit task to workqueue to drive the external Test Equipment.
+ * Note the task is delayed long enough to have Aarvark already set up.
+ * This because Aardvark has to ignore the initial glitches during the
+ * previous GPIO setup phase.
+ */
+ schedule_delayed_work(&work, 20 * HZ);
+
+ return 0;
+
+fail_release_second_gpio:
+ gpio_free(SUT_GPIO_SC_7);
+fail_release_first_gpio:
+ gpio_free(SUT_GPIO_SC_6);
+fail:
+ pr_err("%s() failed\n", __func__);
+
+ return ret;
+}
+
+/**
+ * gpio_sc_level_int_teardown
+ *
+ * Release resources reserved by gpio_sc_level_int().
+ */
+static int gpio_sc_level_int_teardown(void)
+{
+ int irq = -1;
+
+ if (0 != cancel_delayed_work_sync(&work))
+ pr_warn("delayed work was still pending\n");
+
+ irq = gpio_to_irq(SUT_GPIO_SC_6);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_6);
+ } else {
+ free_irq(irq, NULL);
+ }
+
+ /* Make sure no handler is still running by this time */
+ mdelay(20);
+
+ gpio_free(SUT_GPIO_SC_7);
+ gpio_free(SUT_GPIO_SC_6);
+
+ return 0;
+}
+
+/*
+ * gpio_sc_interrupt_perf
+ *
+ * Performs a basic GPIO interrupt latency test by timestamping delta between
+ * interrupt driven and handled over a GPIO loopback.
+ *
+ * Returns to userspace the array of deltas obtained during each capture.
+ * A total amount of INT_PERF_TEST_CAPTURES captures is performed.
+ *
+ */
+static int gpio_sc_interrupt_perf(unsigned long user_memloc)
+{
+ int ret = 0;
+ int irq = -1;
+ int gpio_input = SUT_GPIO_SC_1;
+ int gpio_output = SUT_GPIO_SC_0;
+ unsigned int i = 0;
+ cycles_t perf_t0 = 0;
+ cycles_t delta = 0;
+
+ /* Casting pointer to user-space location to write */
+ cycles_t __user *user_ptr = (cycles_t __user *)user_memloc;
+
+ /* Can we copy the captures array into user-space location? */
+ if (!access_ok(VERIFY_WRITE, user_ptr, sizeof(deltas))) {
+ pr_err("can't copy 0x%x bytes to user-space address 0x%p\n",
+ sizeof(deltas),user_ptr);
+ return -EFAULT;
+ }
+
+ /* Setup the GPIO */
+ if (!gpio_is_valid(gpio_input)) {
+ pr_err("gpio%d is invalid\n", gpio_input);
+ ret = -1;
+ goto fail;
+ }
+ if (!gpio_is_valid(gpio_output)) {
+ pr_err("gpio%d is invalid\n", gpio_output);
+ ret = -1;
+ goto fail;
+ }
+ ret = gpio_request_one(gpio_input, GPIOF_IN, "gpio_intperf_in");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", gpio_input, ret);
+ goto fail;
+ }
+ ret = gpio_request_one(gpio_output, GPIOF_OUT_INIT_LOW, "gpio_intperf_out");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", gpio_output, ret);
+ goto fail_release_input_gpio;
+ }
+
+ /* Setup IRQ handler for input GPIO */
+ irq = gpio_to_irq(gpio_input);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", gpio_input);
+ goto fail_release_output_gpio;
+ }
+ if (0 != (ret = request_irq(irq, gpio_latency_handler,
+ IRQF_TRIGGER_RISING, "gpio_latency_handler", NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", gpio_input);
+ goto fail_release_output_gpio;
+ }
+
+ /* Perform test */
+ for (i = 0; i < INT_PERF_TEST_CAPTURES; i ++) {
+ /* t0 */
+ perf_t0 = get_cycles();
+
+ /* Trigger interrupt */
+ gpio_set_value(gpio_output, 1);
+ mdelay(2);
+
+ /* Check for wrap-around and store delta */
+ if(perf_t0 < perf_t1) {
+ delta = perf_t1 - perf_t0;
+ } else {
+ delta = perf_t1 + (UINT64_MAX - perf_t0);
+ }
+ deltas[i] = delta;
+ }
+
+ /* Expose results to userspace */
+ ret = copy_to_user(user_ptr, &deltas, sizeof(deltas));
+
+ /* Release resources */
+
+ free_irq(irq, NULL);
+
+fail_release_output_gpio:
+ gpio_free(gpio_output);
+fail_release_input_gpio:
+ gpio_free(gpio_input);
+fail:
+ if (0 != ret) {
+ pr_err("%s() failed\n", __func__);
+ }
+
+ return ret;
+}
+
+/**
+ * gpio_sc_pm_test_int
+ *
+ * Request rising edge-triggered IRQ for SUT_GPIO_SC_0
+ */
+static int gpio_sc_pm_test_int(void)
+{
+ int ret = 0;
+ int irq = -1;
+ int gpio_input = SUT_GPIO_SC_0;
+
+ /* Setup the GPIO */
+ if (!gpio_is_valid(gpio_input)) {
+ pr_err("gpio%d is invalid\n", gpio_input);
+ ret = -1;
+ goto fail;
+ }
+ ret = gpio_request_one(gpio_input, GPIOF_IN, "gpio_pm_test_in");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", gpio_input, ret);
+ goto fail;
+ }
+
+ /* Setup IRQ handler for input GPIO */
+ irq = gpio_to_irq(gpio_input);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", gpio_input);
+ goto fail_release_input_gpio;
+ }
+ if (0 != (ret = request_irq(irq, gpio_pm_test_handler,
+ IRQF_TRIGGER_RISING, GPIO_PM_TEST_IRQ_LABEL, NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", gpio_input);
+ goto fail_release_input_gpio;
+ }
+
+ return 0;
+
+fail_release_input_gpio:
+ gpio_free(gpio_input);
+fail:
+ return ret;
+}
+
+/**
+ * gpio_sc_pm_test_int
+ *
+ * Release resources reserved by gpio_sc_edge_int()
+ */
+static int gpio_sc_pm_test_int_teardown(void)
+{
+ int irq = -1;
+
+ irq = gpio_to_irq(SUT_GPIO_SC_0);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_0);
+ } else {
+ free_irq(irq, NULL);
+ }
+
+ gpio_free(SUT_GPIO_SC_0);
+
+ return 0;
+}
+
+/**
+ * gpio_sc_edge_int
+ *
+ * Request IRQ for SUT_GPIO_SC_6 and SUT_GPIO_SC_7, respectively positive-edge
+ * and negative edge-triggered.
+ * Mask the IRQs if requested.
+ */
+static int gpio_sc_edge_int(int masking)
+{
+ int ret = 0;
+ int irq_pos = -1, irq_neg = -1;
+
+ if (!gpio_is_valid(SUT_GPIO_SC_6)) {
+ pr_err("gpio%d is invalid\n", SUT_GPIO_SC_6);
+ ret = -1;
+ goto fail;
+ }
+ if (!gpio_is_valid(SUT_GPIO_SC_7)) {
+ pr_err("gpio%d is invalid\n", SUT_GPIO_SC_7);
+ ret = -1;
+ goto fail;
+ }
+
+ ret = gpio_request_one(SUT_GPIO_SC_6, GPIOF_IN, "gpio_pos_edge");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", SUT_GPIO_SC_6, ret);
+ goto fail;
+ }
+ ret = gpio_request_one(SUT_GPIO_SC_7, GPIOF_IN, "gpio_neg_edge");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", SUT_GPIO_SC_7, ret);
+ goto fail_release_first_gpio;
+ }
+
+ irq_pos = gpio_to_irq(SUT_GPIO_SC_6);
+ if (irq_pos < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_6);
+ goto fail_release_second_gpio;
+ }
+ irq_neg = gpio_to_irq(SUT_GPIO_SC_7);
+ if (irq_neg < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_7);
+ goto fail_release_second_gpio;
+ }
+
+ if (0 != (ret = request_irq(irq_pos, gpio_pos_edge_handler,
+ IRQF_TRIGGER_RISING, GPIO_INT_EDGE_POS_LABEL, NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", SUT_GPIO_SC_6);
+ goto fail_release_second_gpio;
+ }
+ if (0 != (ret = request_irq(irq_neg, gpio_neg_edge_handler,
+ IRQF_TRIGGER_FALLING, GPIO_INT_EDGE_NEG_LABEL, NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", SUT_GPIO_SC_7);
+ goto fail_release_first_gpio_irq;
+ }
+
+ pr_info("Registered gpio%d and gpio%d IRQs\n", SUT_GPIO_SC_6,
+ SUT_GPIO_SC_7);
+
+ if (masking) {
+ disable_irq(gpio_to_irq(SUT_GPIO_SC_6));
+ disable_irq(gpio_to_irq(SUT_GPIO_SC_7));
+ pr_info("Masked gpio%d and gpio%d IRQs\n", SUT_GPIO_SC_6,
+ SUT_GPIO_SC_7);
+ }
+
+ return 0;
+
+fail_release_first_gpio_irq:
+ free_irq(irq_pos, NULL);
+fail_release_second_gpio:
+ gpio_free(SUT_GPIO_SC_7);
+fail_release_first_gpio:
+ gpio_free(SUT_GPIO_SC_6);
+fail:
+ pr_err("%s() failed\n", __func__);
+
+ return ret;
+}
+
+/**
+ * gpio_sc_edge_int_teardown
+ *
+ * Release resources reserved by gpio_sc_edge_int()
+ */
+static int gpio_sc_edge_int_teardown(void)
+{
+ int irq_pos = -1, irq_neg = -1;
+
+ irq_neg = gpio_to_irq(SUT_GPIO_SC_7);
+ if (irq_neg < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_7);
+ } else {
+ free_irq(irq_neg, NULL);
+ }
+ irq_pos = gpio_to_irq(SUT_GPIO_SC_6);
+ if (irq_pos < 0) {
+ pr_err("can't map gpio%d to IRQ\n", SUT_GPIO_SC_6);
+ } else {
+ free_irq(irq_pos, NULL);
+ }
+
+ gpio_free(SUT_GPIO_SC_7);
+ gpio_free(SUT_GPIO_SC_6);
+
+ return 0;
+}
+
+/**
+ * gpio_sc_basic_int
+ *
+ * Register rising-edge interrupt handler on SUT_GPIO_SC_1
+ */
+static int gpio_sc_basic_int(void)
+{
+ int ret = 0;
+ int irq = -1;
+ unsigned int gpio = SUT_GPIO_SC_1;
+
+ if (!gpio_is_valid(gpio)) {
+ pr_err("gpio%d is invalid\n", gpio);
+ ret = -1;
+ goto fail;
+ }
+
+ ret = gpio_request_one(gpio, GPIOF_IN, "gpio_pos_edge_basic");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", gpio, ret);
+ goto fail;
+ }
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", gpio);
+ goto fail_release_gpio;
+ }
+
+ if (0 != (ret = request_irq(irq, gpio_basic_handler,
+ IRQF_TRIGGER_RISING, GPIO_INT_BASIC_LABEL, NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", gpio);
+ goto fail_release_gpio;
+ }
+
+ pr_info("Registered gpio%d IRQ\n", gpio);
+
+ return 0;
+
+fail_release_gpio:
+ gpio_free(gpio);
+fail:
+ pr_err("%s() failed\n", __func__);
+
+ return ret;
+}
+
+/**
+ * gpio_sc_basic_int_teardown
+ *
+ * Release resources reserved by gpio_sc_basic_int()
+ */
+static int gpio_sc_basic_int_teardown(void)
+{
+ int irq = -1;
+ unsigned int gpio = SUT_GPIO_SC_1;
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", gpio);
+ } else {
+ free_irq(irq, NULL);
+ }
+
+ gpio_free(gpio);
+
+ return 0;
+}
+
+/**
+ * gpio_spidev_register
+ *
+ * Register a bitbanged SPI platform device and export a `spidev' to userspace.
+ * For North Cluster and South Cluster.
+ */
+static int gpio_spidev_register(int north_cluster)
+{
+ int err = -ENOMEM;
+ struct platform_device *pdev = NULL;
+ struct spi_gpio_platform_data *pdata =
+ north_cluster ? &spi_gpio_nc_data : &spi_gpio_sc_data;
+ struct spi_board_info *gpio_spi_board_info =
+ (north_cluster ? spi_gpio_nc_board_info : spi_gpio_sc_board_info);
+
+ if (north_cluster) {
+ spi_gpio_nc_pdev = NULL;
+ } else {
+ spi_gpio_sc_pdev = NULL;
+ }
+
+ pdev = platform_device_alloc("spi_gpio",
+ north_cluster ? GPIO_NC_BITBANG_SPI_BUS : GPIO_SC_BITBANG_SPI_BUS);
+ if (NULL == pdev) {
+ goto err_out;
+ }
+ err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (err) {
+ goto err_put_pd;
+ }
+ err = platform_device_add(pdev);
+ if (err) {
+ goto err_put_pd;
+ }
+
+ err = spi_register_board_info(gpio_spi_board_info,
+ /*
+ * Note I pass an array here instead of a pointer in order not
+ * to break ARRAY_SIZE.
+ */
+ ARRAY_SIZE(spi_gpio_sc_board_info));
+ if (err) {
+ goto err_del_pd;
+ }
+
+ if (north_cluster) {
+ spi_gpio_nc_pdev = pdev;
+ } else {
+ spi_gpio_sc_pdev = pdev;
+ }
+
+ return 0;
+
+err_del_pd:
+ platform_device_del(pdev);
+err_put_pd:
+ platform_device_put(pdev);
+err_out:
+ return err;
+}
+
+/**
+ * gpio_spidev_unregister
+ *
+ * Release a bitbanged SPI platform device and its `spidev' interface.
+ * For North Cluster and South Cluster.
+ */
+static int gpio_spidev_unregister(int north_cluster)
+{
+ int ret = 0;
+
+ struct platform_device *pdev =
+ (north_cluster ? spi_gpio_nc_pdev : spi_gpio_sc_pdev);
+ struct spi_board_info *gpio_spi_board_info =
+ (north_cluster ? spi_gpio_nc_board_info : spi_gpio_sc_board_info);
+
+ ret = spi_unregister_board_info(gpio_spi_board_info,
+ /*
+ * Note I pass an array here instead of a pointer in order not
+ * to break ARRAY_SIZE.
+ */
+ ARRAY_SIZE(spi_gpio_sc_board_info));
+
+ if (0 == ret) {
+ platform_device_unregister(pdev);
+ }
+
+ if (north_cluster) {
+ spi_gpio_nc_pdev = NULL;
+ } else {
+ spi_gpio_sc_pdev = NULL;
+ }
+
+ return ret;
+}
+
+/**
+ * gip_system_power_transition
+ *
+ * @param state: 0 if transition to S3, !0 if transition to S0
+ * @return 0 success < 0 failure
+ *
+ * Exercise system-wide suspend/resume power management transitions.
+ *
+ */
+static int gip_system_power_transition(int state)
+{
+ struct pci_dev *gip = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0934, NULL);
+ if (NULL == gip) {
+ pr_err("can't find GIP PCI device\n");
+ return -ENOENT;
+ }
+
+ if (0 == state) {
+ gip->driver->driver.pm->suspend(&gip->dev);
+ } else {
+ gip->driver->driver.pm->resume(&gip->dev);
+ }
+
+ /* Decrement reference count of PCI device */
+ if (NULL != pci_get_device(PCI_VENDOR_ID_INTEL, 0x0934, gip)) {
+ pr_warn("found duplicate of GIP PCI device?!\n");
+ }
+
+ return 0;
+}
+
+/**
+ * gpio_sc_debounce
+ *
+ * Enable GPIO debounce functionality for SC_GPIO_1 (edge and level triggered)
+ *
+ */
+static int gpio_sc_debounce(int level)
+{
+ int ret = 0;
+ int irq = -1;
+ int gpio = SUT_GPIO_SC_0;
+
+ if (!gpio_is_valid(gpio)) {
+ pr_err("gpio%d is invalid\n", gpio);
+ ret = -1;
+ goto fail;
+ }
+
+ ret = gpio_request_one(gpio, GPIOF_IN,
+ level ? "gpio_level_mask" : "gpio_edge_mask");
+ if (ret) {
+ pr_err("can't request gpio%d (error %d)\n", gpio, ret);
+ goto fail;
+ }
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", gpio);
+ goto fail_release_gpio;
+ }
+
+ /*
+ * Register IRQ. gpio_pos_edge_handler will do for both level and edge
+ * interrupts, as it's nooping.
+ */
+ if (0 != (ret = request_irq(irq, gpio_pos_edge_handler,
+ level ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_RISING,
+ level ? GPIO_INT_LEVEL_HIGH_LABEL : GPIO_INT_EDGE_POS_LABEL,
+ NULL))) {
+ pr_err("can't request IRQ for gpio%d\n", gpio);
+ goto fail_release_gpio;
+ }
+
+ /* Set debounce */
+ if (0 != (ret = gpio_set_debounce(gpio, 1))) {
+ pr_err("can't set debounce for gpio%d\n", gpio);
+ goto fail_free_irq;
+ }
+
+ return 0;
+
+fail_free_irq:
+ free_irq(irq, NULL);
+fail_release_gpio:
+ gpio_free(gpio);
+fail:
+ pr_err("%s() failed\n", __func__);
+
+ return ret;
+}
+
+/**
+ * gpio_sc_debounce_teardown
+ *
+ * Undo gpio_sc_debounce
+ *
+ */
+static int gpio_sc_debounce_teardown(int level)
+{
+ int irq = -1;
+ unsigned int gpio = SUT_GPIO_SC_0;
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0) {
+ pr_err("can't map gpio%d to IRQ\n", gpio);
+ } else {
+ free_irq(irq, NULL);
+ }
+
+ gpio_free(gpio);
+
+ return 0;
+}
+
+/*
+ * File ops
+ */
+static long gip_test_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -EINVAL;
+
+ switch (cmd) {
+ case IOCTL_CLN_GPIO_11:
+ /* Edge-triggered interrupts */
+ ret = gpio_sc_edge_int(0);
+ break;
+ case IOCTL_CLN_GPIO_11_CLEANUP:
+ /* Edge-triggered interrupts cleanup */
+ ret = gpio_sc_edge_int_teardown();
+ break;
+ case IOCTL_CLN_GPIO_12:
+ /* Edge-triggered interrupts (masking) */
+ ret = gpio_sc_edge_int(1);
+ break;
+ case IOCTL_CLN_GPIO_12_CLEANUP:
+ /* Edge-triggered interrupts (masking) cleanup */
+ ret = gpio_sc_edge_int_teardown();
+ break;
+ case IOCTL_CLN_GPIO_13:
+ /* GPIO debounce (edge) */
+ ret = gpio_sc_debounce(0);
+ break;
+ case IOCTL_CLN_GPIO_13_CLEANUP:
+ /* GPIO debounce cleanup (edge) */
+ ret = gpio_sc_debounce_teardown(0);
+ break;
+ case IOCTL_CLN_GPIO_14:
+ /* High-level triggered interrupts */
+ ret = gpio_sc_level_int(1, 0);
+ break;
+ case IOCTL_CLN_GPIO_14_CLEANUP:
+ /* High-level triggered interrupts cleanup */
+ ret = gpio_sc_level_int_teardown();
+ break;
+ case IOCTL_CLN_GPIO_15:
+ /* Low-level triggered interrupts */
+ ret = gpio_sc_level_int(0, 0);
+ break;
+ case IOCTL_CLN_GPIO_15_CLEANUP:
+ /*Low-level triggered interrupts cleanup */
+ ret = gpio_sc_level_int_teardown();
+ break;
+ case IOCTL_CLN_GPIO_16:
+ /* Level triggered interrupts (masking) */
+ ret = gpio_sc_level_int(1, 1);
+ break;
+ case IOCTL_CLN_GPIO_16_CLEANUP:
+ /* Level triggered interrupts (masking) cleanup */
+ ret = gpio_sc_level_int_teardown();
+ break;
+ case IOCTL_CLN_GPIO_17:
+ /* GPIO debounce (level) */
+ ret = gpio_sc_debounce(1);
+ break;
+ case IOCTL_CLN_GPIO_17_CLEANUP:
+ /* GPIO debounce cleanup (level) */
+ ret = gpio_sc_debounce_teardown(1);
+ break;
+ case IOCTL_CLN_GPIO_19:
+ /* Register IRQ for SC_GPIO0 (PM transitions test) */
+ ret = gpio_sc_pm_test_int();
+ break;
+ case IOCTL_CLN_GPIO_19_CLEANUP:
+ /* Free IRQ for SC_GPIO0 (PM transitions test) */
+ ret = gpio_sc_pm_test_int_teardown();
+ break;
+ case IOCTL_CLN_GPIO_20:
+ /* NC bitbanged SPI */
+ ret = gpio_spidev_register(1);
+ break;
+ case IOCTL_CLN_GPIO_20_CLEANUP:
+ /* NC bitbanged SPI cleanup */
+ ret = gpio_spidev_unregister(1);
+ break;
+ case IOCTL_CLN_GPIO_21:
+ /* SC bitbanged SPI */
+ ret = gpio_spidev_register(0);
+ break;
+ case IOCTL_CLN_GPIO_21_CLEANUP:
+ /* SC bitbanged SPI cleanup */
+ ret = gpio_spidev_unregister(0);
+ break;
+ case IOCTL_CLN_GPIO_24:
+ /*
+ * SC GPIO interrupt performance test.
+ * Note it's shared between CLN_GPIO_24 and CLN_GPIO_25
+ * plus it doesn't need any cleanup call.
+ */
+ ret = gpio_sc_interrupt_perf(arg);
+ break;
+ case IOCTL_CLN_GPIO_26:
+ /* Interrupt for basic loopback test */
+ ret = gpio_sc_basic_int();
+ break;
+ case IOCTL_CLN_GPIO_26_CLEANUP:
+ /* Interrupt for basic loopback test cleanup */
+ ret = gpio_sc_basic_int_teardown();
+ break;
+ case IOCTL_CLN_GIP_SYSTEM_SUSPEND:
+ ret = gip_system_power_transition(0);
+ break;
+ case IOCTL_CLN_GIP_SYSTEM_RESUME:
+ ret = gip_system_power_transition(1);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int gip_test_open(struct inode *inode, struct file *file)
+{
+ mutex_lock(&gip_test_mutex);
+ nonseekable_open(inode, file);
+
+ if (mutex_lock_interruptible(&gip_test_dev.open_lock)) {
+ mutex_unlock(&gip_test_mutex);
+ return -ERESTARTSYS;
+ }
+
+ if (gip_test_dev.opened) {
+ mutex_unlock(&gip_test_dev.open_lock);
+ mutex_unlock(&gip_test_mutex);
+ return -EINVAL;
+ }
+
+ gip_test_dev.opened++;
+ mutex_unlock(&gip_test_dev.open_lock);
+ mutex_unlock(&gip_test_mutex);
+ return 0;
+}
+
+static int gip_test_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&gip_test_dev.open_lock);
+ gip_test_dev.opened = 0;
+ mutex_unlock(&gip_test_dev.open_lock);
+
+ return 0;
+}
+
+static const struct file_operations gip_test_file_ops = {
+ .open = gip_test_open,
+ .release = gip_test_release,
+ .unlocked_ioctl = gip_test_ioctl,
+ .llseek = no_llseek,
+};
+
+/**
+ * intel_cln_gip_test_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ */
+static int intel_cln_gip_test_probe(struct platform_device * pdev)
+{
+ int retval = 0;
+ unsigned int minor = 0;
+
+ mutex_init(&gip_test_dev.open_lock);
+ cdev_init(&gip_test_dev.cdev, &gip_test_file_ops);
+ gip_test_dev.cdev.owner = THIS_MODULE;
+
+ retval = cdev_add(&gip_test_dev.cdev, MKDEV(gip_test_major, minor), 1);
+ if (retval) {
+ printk(KERN_ERR "chardev registration failed\n");
+ return -EINVAL;
+ }
+ if (IS_ERR(device_create(gip_test_class, NULL,
+ MKDEV(gip_test_major, minor), NULL,
+ "giptest%u", minor))){
+ dev_err(&pdev->dev, "can't create device\n");
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
+
+static int intel_cln_gip_test_remove(struct platform_device * pdev)
+{
+ unsigned int minor = MINOR(gip_test_dev.cdev.dev);
+
+ device_destroy(gip_test_class, MKDEV(gip_test_major, minor));
+ cdev_del(&gip_test_dev.cdev);
+
+ class_destroy(gip_test_class);
+
+ return 0;
+}
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_gip_test_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = intel_cln_gip_test_remove,
+};
+
+/**
+ * intel_cln_gip_test_init
+ *
+ * Load module.
+ */
+static int __init intel_cln_gip_test_init(void)
+{
+ int retval = 0;
+ dev_t dev;
+
+ gip_test_class = class_create(THIS_MODULE,"cln_gip_test");
+ if (IS_ERR(gip_test_class)) {
+ retval = PTR_ERR(gip_test_class);
+ printk(KERN_ERR "gip_test: can't register gip_test class\n");
+ goto err;
+ }
+
+ retval = alloc_chrdev_region(&dev, 0, 1, "gip_test");
+ if (retval) {
+ printk(KERN_ERR "earam_test: can't register character device\n");
+ goto err_class;
+ }
+ gip_test_major = MAJOR(dev);
+
+ memset(&gip_test_dev, 0x00, sizeof(gip_test_dev));
+ gip_test_dev.pldev = platform_create_bundle(
+ &intel_cln_gip_test_driver, intel_cln_gip_test_probe, NULL, 0, NULL, 0);
+
+ if(IS_ERR(gip_test_dev.pldev)){
+ printk(KERN_ERR "platform_create_bundle fail!\n");
+ retval = PTR_ERR(gip_test_dev.pldev);
+ goto err_class;
+ }
+
+ return 0;
+
+err_class:
+ class_destroy(gip_test_class);
+err:
+ return retval;
+}
+
+static void __exit intel_cln_gip_test_exit(void)
+{
+ platform_device_unregister(gip_test_dev.pldev);
+ platform_driver_unregister(&intel_cln_gip_test_driver);
+}
+
+module_init(intel_cln_gip_test_init);
+module_exit(intel_cln_gip_test_exit);
+
+MODULE_AUTHOR("Josef Ahmad <josef.ahmad@intel.com>");
+MODULE_DESCRIPTION("Clanton GIP test module");
+MODULE_LICENSE("Dual BSD/GPL");
+
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index 5624fcb..98b1281 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -41,21 +41,41 @@
#define WDTBASE 0x84
#define WDT_IO_SIZE 64
+/* BIOS control reg */
+#define LPC_BIOS_CNTL 0xD8
+#define LPC_BIOS_CNTL_WE 0x01
+
+/* Root complex base address derived registers */
+#define RCBA_BASE 0xF0
+
static struct resource smbus_sch_resource = {
.flags = IORESOURCE_IO,
};
-
static struct resource gpio_sch_resource = {
.flags = IORESOURCE_IO,
};
+static struct resource spi_res = {
+ .flags = IORESOURCE_MEM,
+ .start = 0,
+ .end = 0,
+};
+
+static struct platform_device lpc_sch_spi = {
+ .name = "spi-lpc-sch",
+ .id = -1,
+ .resource = &spi_res,
+};
+
static struct mfd_cell lpc_sch_cells[] = {
+#ifndef CONFIG_INTEL_CLN_SOC
{
.name = "isch_smbus",
.num_resources = 1,
.resources = &smbus_sch_resource,
},
+#endif
{
.name = "sch_gpio",
.num_resources = 1,
@@ -79,6 +99,7 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CLANTON_ILB) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
@@ -88,22 +109,26 @@ static int lpc_sch_probe(struct pci_dev *dev,
{
unsigned int base_addr_cfg;
unsigned short base_addr;
+ u32 rcba_base, bios_cntl;
int i;
int ret;
- pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
- if (!(base_addr_cfg & (1 << 31))) {
- dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n");
- return -ENODEV;
- }
- base_addr = (unsigned short)base_addr_cfg;
- if (base_addr == 0) {
- dev_err(&dev->dev, "I/O space for SMBus uninitialized\n");
- return -ENODEV;
- }
+ /* Clanton does not support iLB SMBUS */
+ if (id->device != PCI_DEVICE_ID_INTEL_CLANTON_ILB) {
+ pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
+ if (!(base_addr_cfg & (1 << 31))) {
+ dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n");
+ return -ENODEV;
+ }
+ base_addr = (unsigned short)base_addr_cfg;
+ if (base_addr == 0) {
+ dev_err(&dev->dev, "I/O space for SMBus uninitialized\n");
+ return -ENODEV;
+ }
- smbus_sch_resource.start = base_addr;
- smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
+ smbus_sch_resource.start = base_addr;
+ smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
+ }
pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
if (!(base_addr_cfg & (1 << 31))) {
@@ -132,6 +157,31 @@ static int lpc_sch_probe(struct pci_dev *dev,
if (ret)
goto out_dev;
+ /* Add RCBA SPI device */
+ if (id->device == PCI_DEVICE_ID_INTEL_CLANTON_ILB) {
+ pci_read_config_dword(dev, LPC_BIOS_CNTL, &bios_cntl);
+ pr_info("%s BIOS_CNTL 0x%08x\n", __func__, bios_cntl);
+
+ /* Enable flash write */
+ bios_cntl |= LPC_BIOS_CNTL_WE;
+ pci_write_config_dword(dev, LPC_BIOS_CNTL, bios_cntl);
+
+ /* Verify */
+ pci_read_config_dword(dev, LPC_BIOS_CNTL, &bios_cntl);
+ pr_info("%s new BIOS_CNTL 0x%08x\n", __func__, bios_cntl);
+ }
+
+ pci_read_config_dword(dev, RCBA_BASE, &rcba_base);
+ rcba_base &= 0xFFFFC000;
+ spi_res.start = rcba_base + 0x3020;
+ spi_res.end = rcba_base + 0x3088;
+ pr_info("%s RCBA @ 0x%08x\n", __func__, rcba_base);
+ ret = platform_device_register(&lpc_sch_spi);
+ if (ret < 0){
+ pr_err("unable to register %s plat dev\n", lpc_sch_spi.name);
+ goto out_dev;
+ }
+
if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC
|| id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) {
pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index c7dd0cb..4352c6a 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -162,6 +162,10 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
};
+static const struct sdhci_pci_fixes sdhci_intel_cln = {
+ .quirks = SDHCI_QUIRK_NO_HISPD_BIT,
+};
+
static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
@@ -777,6 +781,14 @@ static const struct pci_device_id pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_CLN_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_cln,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_MRST_SD0,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 46dcb54..7af4129 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -159,6 +159,11 @@ config MTD_MTDRAM
provide storage. You probably want to say 'N' unless you're
testing stuff.
+config MTD_MTD_CLN_ROM
+ bool "Simple R/O drive for SPI flash in Clanton x86 legacy block"
+ help
+ Driver to enable reading directly from legacy block SPI /sketch part
+
config MTDRAM_TOTAL_SIZE
int "MTDRAM device size in KiB"
depends on MTD_MTDRAM
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 395733a..4c8e399 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -20,5 +20,4 @@ obj-$(CONFIG_MTD_M25P80) += m25p80.o
obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o
obj-$(CONFIG_MTD_SST25L) += sst25l.o
obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o
-
-CFLAGS_docg3.o += -I$(src)
\ No newline at end of file
+CFLAGS_docg3.o += -I$(src)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 1164930..4e10f27 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -26,8 +26,8 @@ config STMMAC_PLATFORM
If unsure, say N.
config STMMAC_PCI
- bool "STMMAC PCI bus support (EXPERIMENTAL)"
- depends on STMMAC_ETH && PCI && EXPERIMENTAL
+ bool "STMMAC PCI bus support"
+ depends on STMMAC_ETH && PCI
---help---
This is to select the Synopsys DWMAC available on PCI devices,
if you have a controller with this interface, say Y or M here.
@@ -54,6 +54,27 @@ config STMMAC_DA
By default, the DMA arbitration scheme is based on Round-robin
(rx:tx priority is 1:1).
+config STMMAC_PTP
+ bool "STMMAC PTP (1588-2005) Clock Support"
+ default n
+ depends on EXPERIMENTAL
+ select PPS
+ select PTP_1588_CLOCK
+ ---help---
+ Say Y here if you want support for 1588 Timestamping with a
+ Clanton device, using the PTP 1588 Clock support. This is
+ required to enable timestamping support for the device.
+
+ If unsure, say N.
+
+config STMMAC_PTP_CLK_MHZ
+ depends on STMMAC_PTP
+ int "Reference clock in Mhz"
+ default 50
+ ---help---
+ Frequency if MHz of the reference clock used to derive PTP time
+ locally. Permissable values are 1 - 255 inclusive
+
choice
prompt "Select the DMA TX/RX descriptor operating modes"
depends on STMMAC_ETH
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index c8e8ea6..0995db5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -3,6 +3,7 @@ stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
+stmmac-$(CONFIG_STMMAC_PTP) += stmmac_ptp.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 186d148..26833ae 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -32,9 +32,15 @@
#include <linux/init.h>
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define STMMAC_VLAN_TAG_USED
+#if defined(CONFIG_INTEL_CLN_SOC)
+#define STMMAC_VLAN_HASH
+#endif
#include <linux/if_vlan.h>
#endif
+#if defined(STMMAC_VLAN_HASH) || defined(CONFIG_STMMAC_PTP)
+#define STMMAC_ATDS_USED
+#endif
#include "descs.h"
#include "mmc.h"
@@ -319,15 +325,16 @@ struct stmmac_dma_ops {
void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
};
+struct stmmac_priv;
struct stmmac_ops {
/* MAC core initialization */
void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
/* Enable and verify that the IPC module is supported */
- int (*rx_ipc) (void __iomem *ioaddr);
+ int (*set_rx_ipc) (void __iomem *ioaddr, bool on);
/* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */
- int (*host_irq_status) (void __iomem *ioaddr);
+ int (*host_irq_status) (struct stmmac_priv * priv);
/* Multicast filter setting */
void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */
@@ -340,6 +347,9 @@ struct stmmac_ops {
unsigned int reg_n);
void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n);
+ /* Enable/Disable VLAN Hash filters */
+ int (*vlan_rx_add_vid)(struct stmmac_priv *priv, unsigned short vid);
+ int (*vlan_rx_kill_vid)(struct stmmac_priv *priv, unsigned short vid);
void (*set_eee_mode) (void __iomem *ioaddr);
void (*reset_eee_mode) (void __iomem *ioaddr);
void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 223adf9..ce08163 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -25,8 +25,8 @@
#define __DESCS_H__
struct dma_desc {
- /* Receive descriptor */
union {
+ /* Receive descriptor */
struct {
/* RDES0 */
u32 payload_csum_error:1;
@@ -160,6 +160,49 @@ struct dma_desc {
} des01;
unsigned int des2;
unsigned int des3;
+
+ /* Enhanced mode - with VLAN/1588-2005/IPC CHKSUM offload */
+ #if defined(STMMAC_ATDS_USED)
+ union {
+ /* Receive descriptor */
+ struct {
+ /* RDES4 */
+ u32 ip_payload_type:3;
+ u32 ip_header_error:1;
+ u32 ip_payload_error:1;
+ u32 ip_checksum_bypassed:1;
+ u32 ipv4_packet_received:1;
+ u32 ipv6_packet_received:1;
+ u32 message_type:4;
+ u32 ptp_frame_type:1;
+ u32 ptp_version:1;
+ u32 timestamp_dropped:1;
+ u32 reserved1:1;
+ u32 av_packet_received:1;
+ u32 av_tagged_packet_received:1;
+ u32 vlan_tag_priority_value:3;
+ u32 reserved2:3;
+ u32 layer3_filter_match:1;
+ u32 layer4_filter_match:1;
+ u32 layer3_layer4_filter_num_matched:2;
+ u32 reserved3:4;
+
+ /* RDES5 */
+ u32 reserved4;
+ }erx;
+
+ /* Transmit descriptor */
+ struct {
+ /* TDES4 */
+ u32 reserved1;
+
+ /* TDES5 */
+ u32 reserved2;
+ } etx;
+ } des05;
+ unsigned int ts_lo; /* des6 Tx/Rx timestmp lo */
+ unsigned int ts_hi; /* des7 Tx/Rx timestamp hi */
+ #endif
};
/* Transmit checksum insertion control */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 7ad56af..3042098 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -50,7 +50,14 @@ enum dwmac1000_irq_status {
rgmii_irq = 0x0001,
};
#define GMAC_INT_MASK 0x0000003c /* interrupt mask register */
-
+#define GMAC_INT_MASK_LPIIM 0x00000200 /* LPI Interrupt Mask */
+#define GMAC_INT_MASK_TSIM 0x00000100 /* Timestamp Interrupt Mask */
+#define GMAC_INT_MASK_PMTIM 0x00000004 /* PMT Interrupt Mask */
+#define GMAC_INT_MASK_PCSANCIM 0x00000002 /* PCS AN Completion */
+#define GMAC_INT_MASK_PCSLCHGIM 0x00000001 /* PCS Link Status */
+#define GMAC_INT_MASK_DEFAULT GMAC_INT_MASK_PCSLCHGIM | GMAC_INT_MASK_PCSANCIM\
+ | GMAC_INT_MASK_PMTIM | GMAC_INT_MASK_TSIM\
+ | GMAC_INT_MASK_LPIIM
/* PMT Control and Status */
#define GMAC_PMT 0x0000002c
enum power_event {
@@ -135,6 +142,7 @@ enum inter_frame_gap {
#define GMAC_FRAME_FILTER_SAIF 0x00000100 /* Inverse Filtering */
#define GMAC_FRAME_FILTER_SAF 0x00000200 /* Source Address Filter */
#define GMAC_FRAME_FILTER_HPF 0x00000400 /* Hash or perfect Filter */
+#define GMAC_FRAME_FILTER_VTFE 0x00010000 /* VLAN Tag Filter Enable */
#define GMAC_FRAME_FILTER_RA 0x80000000 /* Receive all mode */
/* GMII ADDR defines */
#define GMAC_MII_ADDR_WRITE 0x00000002 /* MII Write */
@@ -145,11 +153,17 @@ enum inter_frame_gap {
#define GMAC_FLOW_CTRL_RFE 0x00000004 /* Rx Flow Control Enable */
#define GMAC_FLOW_CTRL_TFE 0x00000002 /* Tx Flow Control Enable */
#define GMAC_FLOW_CTRL_FCB_BPA 0x00000001 /* Flow Control Busy ... */
-
+/* GMAC VLAN TAG defines */
+#define GMAC_VLAN_TAG_VTHM 0x00080000 /* Hash Table Match Enable */
+#define GMAC_VLAN_TAG_ESVL 0x00040000 /* Enable S-VLAN */
+#define GMAC_VLAN_TAG_VTIM 0x00020000 /* VLAN Tag inverse match */
+#define GMAC_VLAN_TAG_ETV 0x00010000 /* Enable 12-bit tag comp */
+#define GMAC_VLAN_TAG_VLMASK 0x0000FFFF /* VLAN tag ID for Rx frames */
/*--- DMA BLOCK defines ---*/
/* DMA Bus Mode register defines */
#define DMA_BUS_MODE_SFT_RESET 0x00000001 /* Software Reset */
#define DMA_BUS_MODE_DA 0x00000002 /* Arbitration scheme */
+#define DMA_BUS_MODE_ATDS 0X00000080 /* Alternate Descriptor Size */
#define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */
#define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */
/* Programmable burst length (passed thorugh platform)*/
@@ -169,6 +183,7 @@ enum rx_tx_priority_ratio {
#define DMA_BUS_MODE_USP 0x00800000
#define DMA_BUS_MODE_PBL 0x01000000
#define DMA_BUS_MODE_AAL 0x02000000
+#define DMA_BUS_MODE_RIX 0x80000000
/* DMA CRS Control and Status Register Mapping */
#define DMA_HOST_TX_DESC 0x00001048 /* Current Host Tx descriptor */
@@ -230,5 +245,50 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
+/* VLAN Hash register offset */
+#define GMAC_VLAN_TAG_REP 0x584
+#define GMAC_VLAN_HASH 0x588
+#define GMAC_VLAN_HASH_MAXID 0x0F
+
+/***************** 1588 regs *****************/
+#define GMAC_TS_CTRL 0x700 /* Timestamp control reg */
+#define GMAC_TS_CTRL_TSENA 0x00000001 /* Timestamp enable */
+#define GMAC_TS_CTRL_TSCFUPDT 0x00000002 /* Timestamp fine/coarse */
+#define GMAC_TS_CTRL_TSINT 0x00000004 /* Timestamp initialise */
+#define GMAC_TS_CTRL_TSUPDT 0x00000008 /* Timestamp update */
+#define GMAC_TS_CTRL_TSTRIG 0x00000010 /* Timestamp trigger en */
+#define GMAC_TS_CTRL_TSADDREG 0x00000020 /* Timestamp addreg update */
+#define GMAC_TS_CTRL_TSENALL 0x00000100 /* Timestamp RX enable all */
+#define GMAC_TS_CTRL_TSCTRLSSR 0x00000200 /* Timestamp rollover ctr */
+#define GMAC_TS_CTRL_TSVER2ENA 0x00000400 /* Timestamp PTP v2 en */
+#define GMAC_TS_CTRL_TSIPENA 0x00000800 /* Timestamp PTP over eth */
+#define GMAC_TS_CTRL_TSIPV6ENA 0x00001000 /* Timestamp over IPV6 */
+#define GMAC_TS_CTRL_TSIPV4ENA 0x00002000 /* Timestamp over IPV4 */
+#define GMAC_TS_CTRL_TSEVNTENA 0x00004000 /* Timestamp event only */
+#define GMAC_TS_CTRL_TSMSTRENA 0x00008000 /* Timestamp master enable */
+#define GMAC_TS_CTRL_SNTYPSEL0 0x00000000 /* Timestamp type 0 snapshot */
+#define GMAC_TS_CTRL_SNTYPSEL1 0x00010000 /* Timestamp type 1 snapshot */
+#define GMAC_TS_CTRL_SNTYPSEL2 0x00020000 /* Timestamp type 2 snapshot */
+#define GMAC_TS_CTRL_SNTYPSEL3 0x00030000 /* Timestamp type 3 snapshot */
+#define GMAC_TS_CTRL_TSENMACADR 0x00040000 /* Timestamp mac filter en */
+#define GMAC_TS_CTRL_ATSFC 0x01000000 /* Timestamp aux fifo clear */
+#define GMAC_TS_CTRL_ATSEN0 0x02000000 /* Timestamp aux0 snap en */
+#define GMAC_TS_CTRL_ATSEN1 0x04000000 /* Timestamp aux1 snap en */
+#define GMAC_TS_CTRL_ATSEN2 0x08000000 /* Timestamp aux2 snap en */
+#define GMAC_TS_CTRL_ATSEN3 0x10000000 /* Timestamp aux3 enable */
+#define GMAC_SS_INC 0x704 /* Sub-second increment reg */
+#define GMAC_ST_SEC 0x708 /* System time seconds */
+#define GMAC_ST_NSEC 0x70C /* System time nseconds */
+#define GMAC_ST_SECUP 0x710 /* System time sec-update */
+#define GMAC_ST_NSECUP 0x714 /* System time nsec-update */
+#define GMAC_TS_APPEND 0x718 /* Timestamp append */
+#define GMAC_TT_SEC 0x71C /* Target time seconds */
+#define GMAC_TT_NSEC 0x720 /* Target time nseconds */
+#define GMAC_ST_HWSEC 0x724 /* System time high word sec */
+#define GMAC_ST_TS_STAT 0x728 /* Timestamp status */
+#define GMAC_PPS_CTRL 0x72C /* PPS signal output control */
+#define GMAC_AUXTS_NSEC 0x730 /* Aux timestamp counter nsec */
+#define GMAC_AUXTS_SEC 0x734 /* Aux timestamp counter sec */
+
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index bfe0226..b6d04ca 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <asm/io.h>
#include "dwmac1000.h"
+#include "stmmac.h"
static void dwmac1000_core_init(void __iomem *ioaddr)
{
@@ -38,7 +39,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
writel(value, ioaddr + GMAC_CONTROL);
/* Mask GMAC interrupts */
- writel(0x207, ioaddr + GMAC_INT_MASK);
+ writel(GMAC_INT_MASK_DEFAULT, ioaddr + GMAC_INT_MASK);
#ifdef STMMAC_VLAN_TAG_USED
/* Tag detection without filtering */
@@ -46,11 +47,15 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
#endif
}
-static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac1000_set_rx_ipc(void __iomem *ioaddr, bool on)
{
u32 value = readl(ioaddr + GMAC_CONTROL);
- value |= GMAC_CONTROL_IPC;
+ if(on == true){
+ value |= GMAC_CONTROL_IPC;
+ }else{
+ value &= ~GMAC_CONTROL_IPC;
+ }
writel(value, ioaddr + GMAC_CONTROL);
value = readl(ioaddr + GMAC_CONTROL);
@@ -87,6 +92,7 @@ static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
static void dwmac1000_set_filter(struct net_device *dev, int id)
{
void __iomem *ioaddr = (void __iomem *) dev->base_addr;
+ struct stmmac_priv *priv = netdev_priv(dev);
unsigned int value = 0;
unsigned int perfect_addr_number;
@@ -147,6 +153,10 @@ static void dwmac1000_set_filter(struct net_device *dev, int id)
/* Enable Receive all mode (to debug filtering_fail errors) */
value |= GMAC_FRAME_FILTER_RA;
#endif
+ if (priv->active_vlans != 0){
+ /* VLAN hash filtering is active on this interface */
+ value |= GMAC_FRAME_FILTER_VTFE;
+ }
writel(value, ioaddr + GMAC_FRAME_FILTER);
CHIP_DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: "
@@ -194,38 +204,42 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
}
-static int dwmac1000_irq_status(void __iomem *ioaddr)
+#ifndef CONFIG_STMMAC_PTP
+#define stmmac_ptp_check_pps_event(x){}
+#endif
+
+static int dwmac1000_irq_status(struct stmmac_priv *priv)
{
- u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+ u32 intr_status = readl(priv->ioaddr + GMAC_INT_STATUS);
int status = 0;
/* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
- readl(ioaddr + GMAC_MMC_TX_INTR));
+ readl(priv->ioaddr + GMAC_MMC_TX_INTR));
status |= core_mmc_tx_irq;
}
if (unlikely(intr_status & mmc_rx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
- readl(ioaddr + GMAC_MMC_RX_INTR));
+ readl(priv->ioaddr + GMAC_MMC_RX_INTR));
status |= core_mmc_rx_irq;
}
if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
- readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
+ readl(priv->ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
status |= core_mmc_rx_csum_offload_irq;
}
if (unlikely(intr_status & pmt_irq)) {
CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
/* clear the PMT bits 5 and 6 by reading the PMT
* status register. */
- readl(ioaddr + GMAC_PMT);
+ readl(priv->ioaddr + GMAC_PMT);
status |= core_irq_receive_pmt_irq;
}
/* MAC trx/rx EEE LPI entry/exit interrupts */
if (intr_status & lpiis_irq) {
/* Clean LPI interrupt by reading the Reg 12 */
- u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);
+ u32 lpi_status = readl(priv->ioaddr + LPI_CTRL_STATUS);
if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
@@ -244,10 +258,110 @@ static int dwmac1000_irq_status(void __iomem *ioaddr)
status |= core_irq_rx_path_exit_lpi_mode;
}
}
+ if (unlikely(intr_status & time_stamp_irq)){
+ stmmac_ptp_check_pps_event(priv);
+ }
return status;
}
+static unsigned int dwmac1000_calc_vlan_4bit_crc ( const char * vlan )
+{
+ int i = 0, j = 0, len = 0, bit = 0;
+ unsigned int crc = 0xFFFFFFFF;
+ unsigned int poly = 0x04C11DB7;
+ unsigned char data;
+
+ if(unlikely(vlan == NULL)){
+ return 0;
+ }
+
+ for( i = 0; i < 2; i++ ) {
+ data = vlan[i];
+
+ if (i==0){
+ len = 8;
+ }else{
+ len = 4;
+ }
+
+ for( bit = 0; bit < len; bit++ ) {
+
+ j = ((crc >> 31) ^ data) & 0x1;
+ crc <<= 1;
+
+ if( j != 0 ){
+ crc ^= poly;
+ }
+
+ data >>= 1;
+ }
+ }
+ return crc;
+
+}
+
+static int dwmac1000_vlan_rx_add_vid(struct stmmac_priv *priv, unsigned short vid)
+{
+ u32 reg = 0;
+ u32 bit_nr = 0;
+
+ if(unlikely(priv == NULL || vid > GMAC_VLAN_HASH_MAXID)){
+ return -EINVAL;
+ }
+
+ if(priv->active_vlans == 0){
+
+ /* Flip the VTFE bit in GMAC_FRAME_FILTER */
+ reg = readl(priv->ioaddr + GMAC_FRAME_FILTER);
+ reg |= GMAC_FRAME_FILTER_VTFE;
+ writel(reg, priv->ioaddr + GMAC_FRAME_FILTER);
+
+ /* Enable hash filtering - based on 12 bit vid */
+ reg = readl(priv->ioaddr + GMAC_VLAN_TAG);
+ reg |= GMAC_VLAN_TAG_VTHM | GMAC_VLAN_TAG_ETV | 0x0000FFFF;
+ writel(reg, priv->ioaddr + GMAC_VLAN_TAG);
+ }
+
+ bit_nr = (~dwmac1000_calc_vlan_4bit_crc((const char*)&vid)) >> 28;
+ priv->active_vlans |= 1 << bit_nr;
+
+ writel(priv->active_vlans, priv->ioaddr + GMAC_VLAN_HASH);
+
+ return 0;
+}
+
+static int dwmac1000_vlan_rx_kill_vid(struct stmmac_priv *priv, unsigned short vid)
+{
+ u32 reg = 0;
+ u32 bit_nr = 0;
+
+ if(unlikely(priv == NULL || vid > GMAC_VLAN_HASH_MAXID)){
+ return -EINVAL;
+ }
+
+ bit_nr = (~dwmac1000_calc_vlan_4bit_crc((const char*)&vid)) >> 28;
+
+ priv->active_vlans &= ~(1 << bit_nr);
+ writel(priv->active_vlans, priv->ioaddr + GMAC_VLAN_HASH);
+
+ if(priv->active_vlans == 0){
+
+ /* Disable hash filtering */
+ reg = readl(priv->ioaddr + GMAC_VLAN_TAG);
+ reg &= ~(GMAC_VLAN_TAG_VTHM | GMAC_VLAN_TAG_ETV | 0x00000001);
+ writel(reg, priv->ioaddr + GMAC_VLAN_TAG);
+
+ /* Flip the VTFE bit in GMAC_FRAME_FILTER */
+ reg = readl(priv->ioaddr + GMAC_FRAME_FILTER);
+ reg &= ~GMAC_FRAME_FILTER_VTFE;
+ writel(reg, priv->ioaddr + GMAC_FRAME_FILTER);
+
+ }
+
+ return 0;
+}
+
static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
{
u32 value;
@@ -297,9 +411,10 @@ static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
writel(value, ioaddr + LPI_TIMER_CTRL);
}
+
static const struct stmmac_ops dwmac1000_ops = {
.core_init = dwmac1000_core_init,
- .rx_ipc = dwmac1000_rx_ipc_enable,
+ .set_rx_ipc = dwmac1000_set_rx_ipc,
.dump_regs = dwmac1000_dump_regs,
.host_irq_status = dwmac1000_irq_status,
.set_filter = dwmac1000_set_filter,
@@ -307,6 +422,8 @@ static const struct stmmac_ops dwmac1000_ops = {
.pmt = dwmac1000_pmt,
.set_umac_addr = dwmac1000_set_umac_addr,
.get_umac_addr = dwmac1000_get_umac_addr,
+ .vlan_rx_add_vid = dwmac1000_vlan_rx_add_vid,
+ .vlan_rx_kill_vid = dwmac1000_vlan_rx_kill_vid,
.set_eee_mode = dwmac1000_set_eee_mode,
.reset_eee_mode = dwmac1000_reset_eee_mode,
.set_eee_timer = dwmac1000_set_eee_timer,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index bf83c03..34a0afc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -59,9 +59,12 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
* DMA transfers the data in 8, 16, 32, 64, 128 & 256 beats
* depending on pbl value.
*/
+#ifdef CONFIG_INTEL_CLN_SOC
+ value = DMA_BUS_MODE_RIX | (pbl << DMA_BUS_MODE_PBL_SHIFT);
+#else
value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
(pbl << DMA_BUS_MODE_RPBL_SHIFT));
-
+#endif
/* Set the Fixed burst mode */
if (fb)
value |= DMA_BUS_MODE_FB;
@@ -70,6 +73,10 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
if (mb)
value |= DMA_BUS_MODE_MB;
+#if defined(STMMAC_ATDS_USED)
+ value |= DMA_BUS_MODE_ATDS;
+#endif
+
#ifdef CONFIG_STMMAC_DA
value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */
#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index f83210e..43472c0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -67,12 +67,12 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
readl(ioaddr + MAC_VLAN2));
}
-static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac100_set_rx_ipc(void __iomem *ioaddr, bool on)
{
return 0;
}
-static int dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(struct stmmac_priv *priv)
{
return 0;
}
@@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
static const struct stmmac_ops dwmac100_ops = {
.core_init = dwmac100_core_init,
- .rx_ipc = dwmac100_rx_ipc_enable,
+ .set_rx_ipc = dwmac100_set_rx_ipc,
.dump_regs = dwmac100_dump_mac_regs,
.host_irq_status = dwmac100_irq_status,
.set_filter = dwmac100_set_filter,
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
index 0c74a70..50617c5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
@@ -149,6 +149,7 @@ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
{
writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK);
writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK);
+ writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_IPC_INTR_MASK);
}
/* This reads the MAC core counters (if actaully supported).
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b05df89..611f70e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -27,9 +27,11 @@
#define DRV_MODULE_VERSION "Nov_2012"
#include <linux/clk.h>
+#include <linux/clocksource.h>
#include <linux/stmmac.h>
#include <linux/phy.h>
#include <linux/pci.h>
+#include <linux/ptp_clock_kernel.h>
#include "common.h"
struct stmmac_priv {
@@ -72,8 +74,22 @@ struct stmmac_priv {
u32 msg_enable;
spinlock_t lock;
spinlock_t tx_lock;
+
+ /* PTP */
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_caps;
+ struct delayed_work overflow_work;
+ spinlock_t tmreg_lock;
+ struct cyclecounter ccnt;
+ struct timecounter tcnt;
+// struct timecompare tcmp;
+ int hwts;
+ struct stmmac_timer *tm;
+
int wolopts;
int wol_irq;
+
+ int active_vlans;
struct plat_stmmacenet_data *plat;
struct stmmac_counters mmc;
struct dma_features dma_cap;
@@ -81,6 +97,8 @@ struct stmmac_priv {
struct clk *stmmac_clk;
int clk_csr;
int synopsys_id;
+ int irqmode_msi;
+ struct pci_dev * pdev;
struct timer_list eee_ctrl_timer;
bool tx_path_in_lpi_mode;
int lpi_irq;
@@ -110,6 +128,63 @@ int stmmac_dvr_remove(struct net_device *ndev);
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat,
void __iomem *addr);
+#ifdef CONFIG_STMMAC_PTP
+
+#define STMMAC_PTP_OVERFLOW_CHECK_ENABLED (u32)(1)
+#define STMMAC_PTP_PPS_ENABLED (u32)(1 << 1)
+#define STMMAC_PTP_HWTS_TX_EN (u32)(1 << 2)
+#define STMMAC_PTP_HWTS_RX_EN (u32)(1 << 3)
+
+extern void stmmac_ptp_init(struct net_device *ndev, struct device * pdev);
+extern void stmmac_ptp_remove(struct stmmac_priv *priv);
+extern int stmmac_ptp_hwtstamp_ioctl(struct stmmac_priv *priv,
+ struct ifreq *ifr, int cmd);
+extern void stmmac_ptp_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *pdma,
+ struct sk_buff *skb);
+extern void stmmac_ptp_tx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *pdma,
+ struct sk_buff *skb);
+extern void stmmac_ptp_check_pps_event(struct stmmac_priv *priv);
+#endif
+
+#ifdef CONFIG_HAVE_CLK
+static inline int stmmac_clk_enable(struct stmmac_priv *priv)
+{
+ if (!IS_ERR(priv->stmmac_clk))
+ return clk_prepare_enable(priv->stmmac_clk);
+
+ return 0;
+}
+
+static inline void stmmac_clk_disable(struct stmmac_priv *priv)
+{
+ if (IS_ERR(priv->stmmac_clk))
+ return;
+
+ clk_disable_unprepare(priv->stmmac_clk);
+}
+static inline int stmmac_clk_get(struct stmmac_priv *priv)
+{
+ priv->stmmac_clk = clk_get(priv->device, NULL);
+
+ if (IS_ERR(priv->stmmac_clk))
+ return PTR_ERR(priv->stmmac_clk);
+
+ return 0;
+}
+#else
+static inline int stmmac_clk_enable(struct stmmac_priv *priv)
+{
+ return 0;
+}
+static inline void stmmac_clk_disable(struct stmmac_priv *priv)
+{
+}
+static inline int stmmac_clk_get(struct stmmac_priv *priv)
+{
+ return 0;
+}
+#endif /* CONFIG_HAVE_CLK */
+
void stmmac_disable_eee_mode(struct stmmac_priv *priv);
bool stmmac_eee_init(struct stmmac_priv *priv);
@@ -167,6 +242,7 @@ static inline int stmmac_register_pci(void)
static inline void stmmac_unregister_pci(void)
{
}
+
#endif /* CONFIG_STMMAC_PCI */
#endif /* __STMMAC_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 1372ce2..0644dcd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -31,6 +31,7 @@
#include "stmmac.h"
#include "dwmac_dma.h"
+#include "dwmac1000.h"
#define REG_SPACE_SIZE 0x1054
#define MAC100_ETHTOOL_NAME "st_mac100"
@@ -231,9 +232,7 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
return -EBUSY;
}
cmd->transceiver = XCVR_INTERNAL;
- spin_lock_irq(&priv->lock);
rc = phy_ethtool_gset(phy, cmd);
- spin_unlock_irq(&priv->lock);
return rc;
}
@@ -244,10 +243,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
struct phy_device *phy = priv->phydev;
int rc;
- spin_lock(&priv->lock);
rc = phy_ethtool_sset(phy, cmd);
- spin_unlock(&priv->lock);
-
return rc;
}
@@ -279,7 +275,7 @@ static int stmmac_ethtool_get_regs_len(struct net_device *dev)
static void stmmac_ethtool_gregs(struct net_device *dev,
struct ethtool_regs *regs, void *space)
{
- int i;
+ int i, offset = 0;
u32 *reg_space = (u32 *) space;
struct stmmac_priv *priv = netdev_priv(dev);
@@ -300,9 +296,20 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
/* MAC registers */
for (i = 0; i < 55; i++)
reg_space[i] = readl(priv->ioaddr + (i * 4));
+
+ /* VLAN registers */
+ offset = i;
+ reg_space[offset++] = readl(priv->ioaddr + GMAC_VLAN_TAG_REP);
+ reg_space[offset++] = readl(priv->ioaddr + GMAC_VLAN_HASH);
+
+ /* 1588 registers */
+ for(i = 0; i < 13; i++);
+ reg_space[i + offset] = readl(priv->ioaddr + (GMAC_TS_CTRL + (i * 4)));
+
/* DMA registers */
+ offset += i;
for (i = 0; i < 22; i++)
- reg_space[i + 55] =
+ reg_space[i + offset] =
readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b75f4b2..c767928 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -28,6 +28,9 @@
https://bugzilla.stlinux.com/
*******************************************************************************/
+#if defined(CONFIG_INTEL_CLN_SOC)
+#include <asm/cln.h>
+#endif
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@@ -135,6 +138,8 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
#ifdef CONFIG_STMMAC_DEBUG_FS
static int stmmac_init_fs(struct net_device *dev);
static void stmmac_exit_fs(void);
+static int debugfs_registered = 0;
+
#endif
#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
@@ -502,13 +507,29 @@ static int stmmac_set_bfsize(int mtu, int bufsize)
}
/**
+ * init_dma_err_cleanup
+ *
+ * @dev: net device to clean
+ * Description: Does a cleanup if kmalloc fails during init
+ */
+static void init_dma_err_cleanup(struct stmmac_priv * priv)
+{
+ if (priv->tx_skbuff != NULL)
+ kfree(priv->tx_skbuff);
+ if (priv->rx_skbuff_dma != NULL)
+ kfree (priv->rx_skbuff_dma);
+ if (priv->rx_skbuff != NULL)
+ kfree (priv->rx_skbuff);
+}
+
+/**
* init_dma_desc_rings - init the RX/TX descriptor rings
* @dev: net device structure
* Description: this function initializes the DMA RX/TX descriptors
* and allocates the socket buffers. It suppors the chained and ring
* modes.
*/
-static void init_dma_desc_rings(struct net_device *dev)
+static int init_dma_desc_rings(struct net_device *dev)
{
int i;
struct stmmac_priv *priv = netdev_priv(dev);
@@ -532,8 +553,16 @@ static void init_dma_desc_rings(struct net_device *dev)
txsize, rxsize, bfsize);
priv->rx_skbuff_dma = kmalloc(rxsize * sizeof(dma_addr_t), GFP_KERNEL);
+ if (priv->rx_skbuff_dma == NULL)
+ return -ENOMEM;
+
priv->rx_skbuff =
kmalloc(sizeof(struct sk_buff *) * rxsize, GFP_KERNEL);
+ if (priv->rx_skbuff == NULL){
+ init_dma_err_cleanup(priv);
+ return -ENOMEM;
+ }
+
priv->dma_rx =
(struct dma_desc *)dma_alloc_coherent(priv->device,
rxsize *
@@ -542,6 +571,11 @@ static void init_dma_desc_rings(struct net_device *dev)
GFP_KERNEL);
priv->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * txsize,
GFP_KERNEL);
+ if (priv->tx_skbuff == NULL){
+ init_dma_err_cleanup(priv);
+ return -ENOMEM;
+ }
+
priv->dma_tx =
(struct dma_desc *)dma_alloc_coherent(priv->device,
txsize *
@@ -550,8 +584,9 @@ static void init_dma_desc_rings(struct net_device *dev)
GFP_KERNEL);
if ((priv->dma_rx == NULL) || (priv->dma_tx == NULL)) {
+ init_dma_err_cleanup(priv);
pr_err("%s:ERROR allocating the DMA Tx/Rx desc\n", __func__);
- return;
+ return -ENOMEM;
}
DBG(probe, INFO, "stmmac (%s) DMA desc: virt addr (Rx %p, "
@@ -569,8 +604,9 @@ static void init_dma_desc_rings(struct net_device *dev)
skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
GFP_KERNEL);
if (unlikely(skb == NULL)) {
+ init_dma_err_cleanup(priv);
pr_err("%s: Rx init fails; skb is NULL\n", __func__);
- break;
+ return -ENOMEM;
}
skb_reserve(skb, NET_IP_ALIGN);
priv->rx_skbuff[i] = skb;
@@ -615,6 +651,8 @@ static void init_dma_desc_rings(struct net_device *dev)
pr_info("TX descriptor ring:\n");
display_ring(priv->dma_tx, txsize);
}
+
+ return 0;
}
static void dma_free_rx_skbufs(struct stmmac_priv *priv)
@@ -736,6 +774,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
DMA_TO_DEVICE);
priv->hw->ring->clean_desc3(p);
+#ifdef CONFIG_STMMAC_PTP
+ stmmac_ptp_tx_hwtstamp(priv, p, skb);
+#endif
+
if (likely(skb != NULL)) {
dev_kfree_skb(skb);
priv->tx_skbuff[entry] = NULL;
@@ -963,6 +1005,25 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
}
/**
+ * stmmac_hw_set_rx_ipc
+ * @priv : pointer to the private device structure.
+ * Enables RX IPC offload if the feature is supported in hardware
+ */
+static int stmmac_hw_set_rx_ipc(struct stmmac_priv *priv, bool on)
+{
+ int ret = 0;
+
+ /* Enable the IPC (Checksum Offload) and check if the feature has been
+ * enabled during the core configuration. */
+ ret = priv->hw->mac->set_rx_ipc(priv->ioaddr, on);
+ if (on == true && !ret) {
+ pr_warning(" RX IPC Checksum Offload not configured.\n");
+ priv->plat->rx_coe = STMMAC_RX_COE_NONE;
+ }
+ return ret;
+}
+
+/**
* stmmac_tx_timer:
* @data: data pointer
* Description:
@@ -1022,7 +1083,12 @@ static int stmmac_open(struct net_device *dev)
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
- init_dma_desc_rings(dev);
+ ret = init_dma_desc_rings(dev);
+ if (ret < 0){
+ pr_err("%s: DMA initialization failed\n", __func__);
+ goto open_error;
+ }
+
/* DMA initialization and SW reset */
ret = stmmac_init_dma_engine(priv);
@@ -1078,6 +1144,9 @@ static int stmmac_open(struct net_device *dev)
/* Set the HW DMA mode and the COE */
stmmac_dma_operation_mode(priv);
+ /* Enable RX IPC if supported by silicon */
+ ret = stmmac_hw_set_rx_ipc(priv, true);
+
/* Extra statistics */
memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
priv->xstats.threshold = tc;
@@ -1085,9 +1154,12 @@ static int stmmac_open(struct net_device *dev)
stmmac_mmc_setup(priv);
#ifdef CONFIG_STMMAC_DEBUG_FS
- ret = stmmac_init_fs(dev);
- if (ret < 0)
- pr_warning("%s: failed debugFS registration\n", __func__);
+ if (debugfs_registered == 0){
+ debugfs_registered = 1;
+ ret = stmmac_init_fs(dev);
+ if (ret < 0)
+ pr_warning("%s: failed debugFS registration\n", __func__);
+ }
#endif
/* Start the ball rolling... */
DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
@@ -1430,6 +1502,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
#endif
skb->protocol = eth_type_trans(skb, priv->dev);
+#ifdef CONFIG_STMMAC_PTP
+ stmmac_ptp_tx_hwtstamp(priv, priv->dma_rx + entry, skb);
+#endif
if (unlikely(!priv->plat->rx_coe))
skb_checksum_none_assert(skb);
else
@@ -1588,9 +1663,19 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
features &= ~NETIF_F_ALL_CSUM;
+ stmmac_hw_set_rx_ipc(priv, features & NETIF_F_RXCSUM);
+
return features;
}
+#if defined(CONFIG_INTEL_CLN_SOC)
+ #define mask_pvm(x) cln_pci_pvm_mask(x)
+ #define unmask_pvm(x) cln_pci_pvm_unmask(x)
+#else
+ #define mask_pvm(x)
+ #define unmask_pvm(x)
+#endif
+
static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
@@ -1601,10 +1686,12 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
+ mask_pvm(priv->pdev);
+
/* To handle GMAC own interrupts */
if (priv->plat->has_gmac) {
- int status = priv->hw->mac->host_irq_status((void __iomem *)
- dev->base_addr);
+ int status = priv->hw->mac->host_irq_status(priv);
+
if (unlikely(status)) {
if (status & core_mmc_tx_irq)
priv->xstats.mmc_tx_irq_n++;
@@ -1634,6 +1721,8 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
/* To handle DMA interrupts */
stmmac_dma_interrupt(priv);
+ unmask_pvm(priv->pdev);
+
return IRQ_HANDLED;
}
@@ -1669,7 +1758,15 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!priv->phydev)
return -EINVAL;
- ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+ switch (cmd) {
+#ifdef CONFIG_STMMAC_PTP
+ case SIOCSHWTSTAMP:
+ ret = stmmac_ptp_hwtstamp_ioctl(priv, rq, cmd);
+ break;
+#endif
+ default:
+ ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+ }
return ret;
}
@@ -1850,6 +1947,21 @@ static void stmmac_exit_fs(void)
}
#endif /* CONFIG_STMMAC_DEBUG_FS */
+#ifdef STMMAC_VLAN_HASH
+static int stmmac_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+ return priv->hw->mac->vlan_rx_add_vid(priv, vid);
+}
+
+static int stmmac_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+ return priv->hw->mac->vlan_rx_kill_vid(priv, vid);
+}
+
+#endif
+
static const struct net_device_ops stmmac_netdev_ops = {
.ndo_open = stmmac_open,
.ndo_start_xmit = stmmac_xmit,
@@ -1860,6 +1972,10 @@ static const struct net_device_ops stmmac_netdev_ops = {
.ndo_tx_timeout = stmmac_tx_timeout,
.ndo_do_ioctl = stmmac_ioctl,
.ndo_set_config = stmmac_config,
+#ifdef STMMAC_VLAN_HASH
+ .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid,
+#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = stmmac_poll_controller,
#endif
@@ -1924,13 +2040,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
/* Select the enhnaced/normal descriptor structures */
stmmac_selec_desc_mode(priv);
- /* Enable the IPC (Checksum Offload) and check if the feature has been
- * enabled during the core configuration. */
- ret = priv->hw->mac->rx_ipc(priv->ioaddr);
- if (!ret) {
- pr_warning(" RX IPC Checksum Offload not configured.\n");
- priv->plat->rx_coe = STMMAC_RX_COE_NONE;
- }
+ ret = stmmac_hw_set_rx_ipc(priv, true);
if (priv->plat->rx_coe)
pr_info(" RX Checksum Offload Engine supported (type %d)\n",
@@ -2001,6 +2111,12 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
/* Both mac100 and gmac support receive VLAN tag detection */
ndev->features |= NETIF_F_HW_VLAN_RX;
#endif
+#ifdef STMMAC_VLAN_HASH
+ ndev->features |= NETIF_F_HW_VLAN_FILTER;
+ ndev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXCSUM;
+#endif
+
priv->msg_enable = netif_msg_init(debug, default_msg_level);
if (flow_ctrl)
@@ -2044,6 +2160,10 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
else
priv->clk_csr = priv->plat->clk_csr;
+#ifdef CONFIG_STMMAC_PTP
+ stmmac_ptp_init(ndev, device);
+#endif
+
/* MDIO bus Registration */
ret = stmmac_mdio_register(ndev);
if (ret < 0) {
@@ -2060,6 +2180,9 @@ error_clk_get:
unregister_netdev(ndev);
error_netdev_register:
netif_napi_del(&priv->napi);
+#ifdef CONFIG_STMMAC_PTP
+ stmmac_ptp_remove(priv);
+#endif
free_netdev(ndev);
return NULL;
@@ -2075,7 +2198,7 @@ int stmmac_dvr_remove(struct net_device *ndev)
{
struct stmmac_priv *priv = netdev_priv(ndev);
- pr_info("%s:\n\tremoving driver", __func__);
+ pr_info("%s:\n\tremoving driver\n", __func__);
priv->hw->dma->stop_rx(priv->ioaddr);
priv->hw->dma->stop_tx(priv->ioaddr);
@@ -2083,6 +2206,10 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_set_mac(priv->ioaddr, false);
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
+
+#ifdef CONFIG_STMMAC_PTP
+ stmmac_ptp_remove(priv);
+#endif
unregister_netdev(ndev);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 064eaac..70563bc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -24,29 +24,186 @@
*******************************************************************************/
#include <linux/pci.h>
+#include <linux/platform_data/clanton.h>
#include "stmmac.h"
-struct plat_stmmacenet_data plat_dat;
-struct stmmac_mdio_bus_data mdio_data;
-struct stmmac_dma_cfg dma_cfg;
+/* List of supported PCI device IDs */
+#define STMMAC_VENDOR_ID 0x700
+#define STMMAC_DEVICE_ID 0x1108
+#define STMMAC_CLANTON_ID 0x0937
+#define MAX_INTERFACES 0x02
+
+#if defined (CONFIG_INTEL_CLN_SOC)
+static int enable_msi = 1;
+#else
+static int enable_msi = 0;
+#endif
+module_param(enable_msi, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_msi, "Enable PCI MSI mode");
+
+static int bus_id = 1;
+static char stmmac_mac_data[MAX_INTERFACES][ETH_ALEN];
+
+struct stmmac_cln_mac_data {
+ int phy_addr;
+ int bus_id;
+ cln_plat_id_t plat_id;
+};
+
+static struct stmmac_cln_mac_data phy_data [] = {
+ {
+ .phy_addr = -1, /* not connected */
+ .bus_id = 1,
+ .plat_id = CLANTON_EMULATION,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 2,
+ .plat_id = CLANTON_EMULATION,
+ },
+ {
+ .phy_addr = 3,
+ .bus_id = 1,
+ .plat_id = CLANTON_PEAK,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 2,
+ .plat_id = CLANTON_PEAK,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 1,
+ .plat_id = KIPS_BAY,
+ },
+ {
+ .phy_addr = -1, /* not connected */
+ .bus_id = 2,
+ .plat_id = KIPS_BAY,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 1,
+ .plat_id = CROSS_HILL,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 2,
+ .plat_id = CROSS_HILL,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 1,
+ .plat_id = CLANTON_HILL,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 2,
+ .plat_id = CLANTON_HILL,
+ },
+ {
+ .phy_addr = 1,
+ .bus_id = 1,
+ .plat_id = IZMIR,
+ },
+ {
+ .phy_addr = -1, /* not connected */
+ .bus_id = 2,
+ .plat_id = IZMIR,
+ },
+};
+
+
+static int stmmac_find_phy_addr(int mdio_bus_id, cln_plat_id_t cln_plat_id)
+{
+ int i = 0;
+
+ for (; i < sizeof(phy_data)/sizeof(struct stmmac_cln_mac_data); i++){
+ if ( phy_data[i].plat_id == cln_plat_id &&
+ phy_data[i].bus_id == mdio_bus_id)
+ return phy_data[i].phy_addr;
+ }
+
+ return -1;
+}
+
+static int stmmac_default_data(struct plat_stmmacenet_data *plat_dat,
+ int mdio_bus_id, const struct pci_device_id *id)
+{
+ int phy_addr = 0;
+ memset(plat_dat, 0, sizeof(struct plat_stmmacenet_data));
+
+ plat_dat->mdio_bus_data = kzalloc(sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
+ if (plat_dat->mdio_bus_data == NULL)
+ return -ENOMEM;
+
+ plat_dat->dma_cfg = kzalloc(sizeof(struct stmmac_dma_cfg),GFP_KERNEL);
+ if (plat_dat->dma_cfg == NULL)
+ return -ENOMEM;
+
+ if (id->device == STMMAC_CLANTON_ID) {
+
+ phy_addr = stmmac_find_phy_addr(mdio_bus_id,
+ intel_cln_plat_get_id());
+ if (phy_addr == -1)
+ return -ENODEV;
+
+ plat_dat->bus_id = mdio_bus_id;
+ plat_dat->phy_addr = phy_addr;
+ plat_dat->interface = PHY_INTERFACE_MODE_RMII;
+ /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+ plat_dat->clk_csr = 2;
+ plat_dat->has_gmac = 1;
+ plat_dat->force_sf_dma_mode = 1;
+
+ plat_dat->mdio_bus_data->phy_reset = NULL;
+ plat_dat->mdio_bus_data->phy_mask = 0;
+
+ plat_dat->dma_cfg->pbl = 16;
+ plat_dat->dma_cfg->fixed_burst = 1;
+ plat_dat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
+
+ } else {
+
+ plat_dat->bus_id = mdio_bus_id;
+ plat_dat->phy_addr = phy_addr;
+ plat_dat->interface = PHY_INTERFACE_MODE_GMII;
+ /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+ plat_dat->clk_csr = 2;
+ plat_dat->has_gmac = 1;
+ plat_dat->force_sf_dma_mode = 1;
+
+ plat_dat->mdio_bus_data->phy_reset = NULL;
+ plat_dat->mdio_bus_data->phy_mask = 0;
+
+ plat_dat->dma_cfg->pbl = 32;
+ plat_dat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
+
+ }
+
+ return 0;
+}
-static void stmmac_default_data(void)
+/**
+ * stmmac_pci_find_mac
+ *
+ * @prive: pointer to private stmmac structure
+ * @mdio_bus_id : MDIO bus identifier used to find the platform MAC id
+ *
+ * Attempt to find MAC in platform data. If not found then driver will generate
+ * a random one for itself in any case
+ */
+void stmmac_pci_find_mac (struct stmmac_priv * priv, unsigned int mdio_bus_id)
{
- memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
- plat_dat.bus_id = 1;
- plat_dat.phy_addr = 0;
- plat_dat.interface = PHY_INTERFACE_MODE_GMII;
- plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
- plat_dat.has_gmac = 1;
- plat_dat.force_sf_dma_mode = 1;
-
- mdio_data.phy_reset = NULL;
- mdio_data.phy_mask = 0;
- plat_dat.mdio_bus_data = &mdio_data;
-
- dma_cfg.pbl = 32;
- dma_cfg.burst_len = DMA_AXI_BLEN_256;
- plat_dat.dma_cfg = &dma_cfg;
+ unsigned int id = mdio_bus_id - 1;
+ if (priv == NULL || id >= MAX_INTERFACES)
+ return;
+
+ if (intel_cln_plat_get_mac(PLAT_DATA_MAC0+id,
+ (char*)&stmmac_mac_data[id]) == 0){
+ memcpy(priv->dev->dev_addr, &stmmac_mac_data[id], ETH_ALEN);
+ }
}
/**
@@ -67,8 +224,21 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
int ret = 0;
void __iomem *addr = NULL;
struct stmmac_priv *priv = NULL;
+ struct plat_stmmacenet_data *plat_dat = NULL;
int i;
+ plat_dat = kmalloc(sizeof(struct plat_stmmacenet_data), GFP_KERNEL);
+ if (plat_dat == NULL){
+ ret = -ENOMEM;
+ goto err_out_map_failed;
+ }
+
+ /* return -ENODEV for non existing PHY, stop probing here */
+ ret = stmmac_default_data(plat_dat, bus_id, id);
+ if (ret != 0)
+ goto err_platdata;
+
+
/* Enable pci device */
ret = pci_enable_device(pdev);
if (ret) {
@@ -96,30 +266,51 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
break;
}
pci_set_master(pdev);
+ if(enable_msi == 1){
+ pci_enable_msi(pdev);
+ pr_info("stmmac MSI mode enabled");
+ }
- stmmac_default_data();
+ pr_info("Vendor 0x%04x Device 0x%04x\n",
+ id->vendor, id->device);
- priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
+ priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
if (!priv) {
pr_err("%s: main driver probe failed", __func__);
goto err_out;
}
+
+ stmmac_pci_find_mac(priv, bus_id);
+
priv->dev->irq = pdev->irq;
priv->wol_irq = pdev->irq;
-
+ priv->irqmode_msi = enable_msi;
+ priv->pdev = pdev;
+ #ifdef CONFIG_INTEL_CLN_SOC
+ priv->lpi_irq = -ENXIO;
+ #endif
pci_set_drvdata(pdev, priv->dev);
pr_debug("STMMAC platform driver registration completed");
+ bus_id++;
return 0;
err_out:
pci_clear_master(pdev);
-err_out_map_failed:
pci_release_regions(pdev);
err_out_req_reg_failed:
pci_disable_device(pdev);
-
+err_platdata:
+ if (plat_dat != NULL){
+ if (plat_dat->dma_cfg != NULL)
+ kfree (plat_dat->dma_cfg);
+ if (plat_dat->mdio_bus_data != NULL)
+ kfree (plat_dat->mdio_bus_data);
+ kfree(plat_dat);
+ }
+err_out_map_failed:
+ bus_id++;
return ret;
}
@@ -138,6 +329,21 @@ static void stmmac_pci_remove(struct pci_dev *pdev)
stmmac_dvr_remove(ndev);
pci_set_drvdata(pdev, NULL);
+
+ if(enable_msi == 1) {
+ if(pci_dev_msi_enabled(pdev)) {
+ pci_disable_msi(pdev);
+ }
+ }
+
+ if (priv->plat != NULL) {
+ if (priv->plat->dma_cfg != NULL)
+ kfree (priv->plat->dma_cfg);
+ if (priv->plat->mdio_bus_data != NULL)
+ kfree (priv->plat->mdio_bus_data);
+ kfree(priv->plat);
+ }
+
pci_iounmap(pdev, priv->ioaddr);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -167,12 +373,10 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
}
#endif
-#define STMMAC_VENDOR_ID 0x700
-#define STMMAC_DEVICE_ID 0x1108
-
static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, STMMAC_CLANTON_ID)},
{}
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
new file mode 100644
index 0000000..8552d0c
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -0,0 +1,723 @@
+/*******************************************************************************
+
+ STMMAC 1588-2005 hardware accel
+ Copyright(c) 2012 Intel Corporation. This code is based on IXGBE_PTP
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information::w
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+#include "stmmac.h"
+#include "dwmac1000.h"
+#include <linux/export.h>
+#include <linux/net_tstamp.h>
+
+/* PPSCMD0 */
+#define STMMAC_PPSCMD_NONE 0x00 /* No command */
+#define STMMAC_PPSCMD_START_SINGLE 0x01 /* Start single pulse */
+#define STMMAC_PPSCMD_START_PULSE 0x02 /* Start pulse train */
+#define STMMAC_PPSCMD_START_CANCEL 0x03 /* Cancel start */
+#define STMMAC_PPSCMD_STOP_PULSE_ATTIME 0x04 /* Stop pulse train at time */
+#define STMMAC_PPSCMD_STOP_PULSE_IMMED 0x05 /* Stop pulse train immediate */
+#define STMMAC_PPSCMD_STOP_CANCEL 0x06 /* Stop cancel pulse train */
+
+#define STMMAC_PTP_OVERFLOW_CHECK_ENABLED (u32)(1)
+#define STMMAC_PTP_PPS_ENABLED (u32)(1 << 1)
+#define STMMAC_PTP_HWTS_TX_EN (u32)(1 << 2)
+#define STMMAC_PTP_HWTS_RX_EN (u32)(1 << 3)
+
+#ifndef NSECS_PER_SEC
+#define NSECS_PER_SEC 1000000000ULL
+#endif
+
+/*
+ * Structure of STMMAC timer registers
+ *
+ * GMAC_TS_HWSEC GMAC_ST_SEC GMAC_ST_NSEC
+ * +--------------+ +--------------+ +---+---+------+
+ * STMMAC | 16 | | 32 | | 32 |
+ * +--------------+ +--------------+ +---+---+------+
+ *
+ * The counter for the STMMAC is 80 bits
+ * - HWSEC == overflow value for ST_SEC => 130 years to overflow (optional)
+ * - ST_SEC == seconds
+ * - ST_NSEC == nanoseconds
+ */
+
+/**
+ * stmmac_ptp_read - read raw cycle counter (to be used by time counter)
+ * @cc - the cyclecounter structure
+ *
+ * this function reads the cyclecounter registers and is called by the
+ * cyclecounter structure used to construct a ns counter from the
+ * arbitrary fixed point registers
+ */
+static cycle_t stmmac_ptp_read(const struct cyclecounter *ccnt)
+{
+ struct stmmac_priv *priv =
+ container_of(ccnt, struct stmmac_priv, ccnt);
+ cycle_t stamp = 0;
+
+ stamp = (u64)readl(priv->ioaddr + GMAC_ST_NSEC);
+ stamp |= (u64)readl(priv->ioaddr + GMAC_ST_SEC) << 32;
+
+ return stamp;
+}
+
+/**
+ * stmmac_ptp_adjfreq
+ * @ptp - the ptp clock structure
+ * @ppb - parts per billion adjustment from base
+ *
+ * adjust the frequency of the ptp cycle counter by the
+ * indicated ppb from the base frequency.
+ */
+static int stmmac_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ return 0;
+}
+
+/**
+ * stmmac_ptp_adjtime
+ * @ptp - the ptp clock structure
+ * @delta - offset to adjust the cycle counter by
+ *
+ * adjust the timer by resetting the timecounter structure.
+ */
+static int stmmac_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct stmmac_priv *priv =
+ container_of(ptp, struct stmmac_priv, ptp_caps);
+ unsigned long flags;
+ u64 now;
+
+ spin_lock_irqsave(&priv->tmreg_lock, flags);
+
+ now = timecounter_read(&priv->tcnt);
+ now += delta;
+
+ /* reset the timecounter */
+ timecounter_init(&priv->tcnt,
+ &priv->ccnt,
+ now);
+
+ spin_unlock_irqrestore(&priv->tmreg_lock, flags);
+ return 0;
+}
+
+/**
+ * stmmac_ptp_gettime
+ * @ptp - the ptp clock structure
+ * @ts - timespec structure to hold the current time value
+ *
+ * read the timecounter and return the correct value on ns,
+ * after converting it into a struct timespec.
+ */
+static int stmmac_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ struct stmmac_priv *priv =
+ container_of(ptp, struct stmmac_priv, ptp_caps);
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tmreg_lock, flags);
+ ns = timecounter_read(&priv->tcnt);
+ spin_unlock_irqrestore(&priv->tmreg_lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+/**
+ * stmmac_ptp_settime
+ * @ptp - the ptp clock structure
+ * @ts - the timespec containing the new time for the cycle counter
+ *
+ * reset the timecounter to use a new base value instead of the kernel
+ * wall timer value.
+ */
+static int stmmac_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ struct stmmac_priv *priv =
+ container_of(ptp, struct stmmac_priv, ptp_caps);
+ u64 ns;
+ unsigned long flags;
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ /* reset the timecounter */
+ spin_lock_irqsave(&priv->tmreg_lock, flags);
+ timecounter_init(&priv->tcnt, &priv->ccnt, ns);
+ spin_unlock_irqrestore(&priv->tmreg_lock, flags);
+
+ return 0;
+}
+
+/**
+ * stmmac_ptp_enable
+ * @ptp - the ptp clock structure
+ * @rq - the requested feature to change
+ * @on - whether to enable or disable the feature
+ *
+ * enable (or disable) ancillary features of the phc subsystem.
+ * our driver only supports the PPS feature on the X540
+ */
+static int stmmac_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ struct stmmac_priv *priv =
+ container_of(ptp, struct stmmac_priv, ptp_caps);
+ uint32_t reg = 0;
+
+ /**
+ * When enabling PPS functionality in STMMAC we need to unmask the
+ * interrupt mask reg and enable the TSTRIG bit in the timestamp control
+ * reg
+ */
+ if (rq->type == PTP_CLK_REQ_PPS) {
+ if (on){
+ priv->hwts |= STMMAC_PTP_PPS_ENABLED;
+
+ /* Enable TSTRIG */
+ reg = readl(priv->ioaddr + GMAC_TS_CTRL);
+ reg |= GMAC_TS_CTRL_TSTRIG;
+ writel(reg, priv->ioaddr + GMAC_TS_CTRL);
+ wmb();
+
+ /* Unmask interrupt */
+ reg = readl(priv->ioaddr + GMAC_INT_MASK);
+ printk(KERN_INFO "%s[on] read interrupt mask 0x%08x\n", __func__, reg);
+ reg &= ~GMAC_INT_MASK_TSIM;
+ printk(KERN_INFO "%s[on] write interrupt mask 0x%08x\n", __func__, reg);
+ writel(reg, priv->ioaddr + GMAC_INT_MASK);
+ wmb();
+
+ } else {
+ /* Mask interrupt */
+ reg = readl(priv->ioaddr + GMAC_INT_MASK);
+ printk(KERN_INFO "%s[off] read interrupt mask 0x%08x\n", __func__, reg);
+ reg |= GMAC_INT_MASK_TSIM;
+ printk(KERN_INFO "%s[off] write interrupt mask 0x%08x\n", __func__, reg);
+ writel(reg, priv->ioaddr + GMAC_INT_MASK);
+ wmb();
+
+ /* Disable TSTRIG */
+ reg = readl(priv->ioaddr + GMAC_TS_CTRL);
+ reg &= ~GMAC_TS_CTRL_TSTRIG;
+ writel(reg, priv->ioaddr + GMAC_TS_CTRL);
+ wmb();
+
+ priv->hwts &=
+ ~STMMAC_PTP_PPS_ENABLED;
+ }
+ return 0;
+ }
+
+ return -ENOTSUPP;
+}
+
+/**
+ * stmmac_ptp_check_pps_event
+ * @priv - the private priv structure
+ *
+ * This function is called by the interrupt routine when checking for
+ * interrupts. It will check and handle a pps event.
+ */
+void stmmac_ptp_check_pps_event(struct stmmac_priv *priv)
+{
+ struct ptp_clock_event event;
+ event.type = PTP_CLOCK_PPS;
+
+ /* Make sure ptp clock is valid, and PPS event enabled */
+ if (!priv->ptp_clock ||
+ !(priv->hwts & STMMAC_PTP_PPS_ENABLED)){
+ return;
+ }
+
+ ptp_clock_event(priv->ptp_clock, &event);
+}
+
+#if 0
+/**
+ * stmmac_ptp_overflow_check - delayed work to detect SYSTIME overflow
+ * @work: structure containing information about this work task
+ *
+ * this work function is scheduled to continue reading the timecounter
+ * in order to prevent missing when the system time registers wrap
+ * around. This needs to be run approximately twice a minute when no
+ * PTP activity is occurring.
+ */
+void stmmac_ptp_overflow_check(struct stmmac_priv *priv)
+{
+ unsigned long elapsed_jiffies = priv->last_overflow_check - jiffies;
+ struct timespec ts;
+
+ if ((priv->hwts & STMMAC_PTP_OVERFLOW_CHECK_ENABLED) &&
+ (elapsed_jiffies >= STMMAC_OVERFLOW_PERIOD)) {
+ stmmac_ptp_gettime(&priv->ptp_caps, &ts);
+ priv->last_overflow_check = jiffies;
+ }
+}
+#endif
+
+/**
+ * stmmac_ptp_tx_hwtstamp - utility function which checks for TX time stamp
+ * @q_vector: structure containing interrupt and ring information
+ * @skb: particular skb to send timestamp with
+ *
+ * if the timestamp is valid, we convert it into the timecounter ns
+ * value, then store that result into the shhwtstamps structure which
+ * is passed up the network stack
+ */
+void stmmac_ptp_tx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *pdma,
+ struct sk_buff *skb)
+{
+ /* Sanity check input */
+ if (unlikely(priv == NULL || pdma == NULL || skb == NULL)){
+ return;
+ }
+
+ if(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP){
+ struct skb_shared_hwtstamps shhwtstamps;
+ u64 ns;
+ u64 regval;
+ unsigned long flags;
+
+ regval = (u64)pdma->ts_lo;
+ regval |= (u64)pdma->ts_hi << 32;
+
+ spin_lock_irqsave(&priv->tmreg_lock, flags);
+ ns = timecounter_cyc2time(&priv->tcnt, regval);
+ spin_unlock_irqrestore(&priv->tmreg_lock, flags);
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+}
+
+/**
+ * stmmac_ptp_rx_hwtstamp - utility function which checks for RX time stamp
+ * @q_vector: structure containing interrupt and ring information
+ * @skb: particular skb to send timestamp with
+ *
+ * if the timestamp is valid, we convert it into the timecounter ns
+ * value, then store that result into the shhwtstamps structure which
+ * is passed up the network stack
+ */
+void stmmac_ptp_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *pdma,
+ struct sk_buff *skb)
+{
+ /* Sanity check input */
+ if (unlikely(priv == NULL || pdma == NULL || skb == NULL)){
+ return;
+ }
+
+ if(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP){
+ struct skb_shared_hwtstamps shhwtstamps;
+ u64 ns;
+ u64 regval;
+ unsigned long flags;
+
+ regval = (u64)pdma->ts_lo;
+ regval |= (u64)pdma->ts_hi << 32;
+
+ spin_lock_irqsave(&priv->tmreg_lock, flags);
+ ns = timecounter_cyc2time(&priv->tcnt, regval);
+ spin_unlock_irqrestore(&priv->tmreg_lock, flags);
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ }
+}
+
+/**
+ * ixgbe_ptp_hwtstamp_ioctl - control hardware time stamping
+ * @priv: pointer to priv struct
+ * @ifreq: ioctl data
+ * @cmd: particular ioctl requested
+ *
+ * Outgoing time stamping can be enabled and disabled. Play nice and
+ * disable it when requested, although it shouldn't case any overhead
+ * when no packet needs it. At most one packet in the queue may be
+ * marked for time stamping, otherwise it would be impossible to tell
+ * for sure to which packet the hardware time stamp belongs.
+ *
+ * Incoming time stamping has to be configured via the hardware
+ * filters. Not all combinations are supported, in particular event
+ * type has to be specified. Matching the kind of event packet is
+ * not supported, with the exception of "all V2 events regardless of
+ * level 2 or 4".
+ */
+int stmmac_ptp_hwtstamp_ioctl(struct stmmac_priv *priv,
+ struct ifreq *ifr, int cmd)
+{
+ struct hwtstamp_config config;
+// struct stmmac_priv *priv = netdev_priv(netdev);
+ u32 tsctl = 0;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ /* Snapshot the reg - preserve Timestamp Interrupt Trigger Enable */
+ tsctl = readl(priv->ioaddr + GMAC_TS_CTRL) & GMAC_TS_CTRL_TSTRIG;
+
+ /* TX */
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ priv->hwts &= ~STMMAC_PTP_HWTS_TX_EN;
+ printk(KERN_INFO "%s set TX PTP en false\n", __func__);
+ break;
+ case HWTSTAMP_TX_ON:
+ priv->hwts |= STMMAC_PTP_HWTS_TX_EN;
+ printk(KERN_INFO "%s set TX PTP en true\n", __func__);
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ /* RX */
+ priv->hwts |= STMMAC_PTP_HWTS_RX_EN;
+
+ switch (config.rx_filter) {
+
+
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ /*
+ * V1_L4 UDP any event
+ * SYNC, Follow_Up, Delay_Req, Delay_Resp,
+ * Pdelay_Req, Pdelay_Resp, Pdelay_Resp_Follow_Up
+ *
+ * SNAPTYPSEL=1, TSMSTRENA=x, TSEVNTENA=0, TSVER2ENA=0, IPV4=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL1 | GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V1_L4_EVENT \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ /*
+ * V1_L4 Master
+ * Delay_Req
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=1, TSEVNTENA=1, TSVER2ENA=0, IPV4=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSMSTRENA;
+ tsctl |= GMAC_TS_CTRL_TSEVNTENA | GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ /*
+ * V1_L4 Slave
+ * Sync
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=0, TSEVNTENA=1, TSVER2ENA=0, IPV4=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSEVNTENA;
+ tsctl |= GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V1_L4_SYNC \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ /*
+ * V2_L4 UDP any event
+ * SYNC, Follow_Up, Delay_Req, Delay_Resp,
+ * Pdelay_Req, Pdelay_Resp, Pdelay_Resp_Follow_Up
+ *
+ * SNAPTYPSEL=1, TSMSTRENA=x, TSEVNTENA=0, TSVER2ENA=1, IPV4=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL1 | GMAC_TS_CTRL_TSVER2ENA | GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_L4_EVENT \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ /*
+ * V2_L4 Master
+ * Delay_Req
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=1, TSEVNTENA=1, TSVER2ENA=1, IPV4=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSMSTRENA;
+ tsctl |= GMAC_TS_CTRL_TSEVNTENA | GMAC_TS_CTRL_TSVER2ENA;
+ tsctl |= GMAC_TS_CTRL_TSIPV4ENA;
+
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ /*
+ * V2_L4 Slave
+ * Sync
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=0, TSEVNTENA=1, TSVER2ENA=1, IPV4=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSVER2ENA | GMAC_TS_CTRL_TSEVNTENA;
+ tsctl |= GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_L4_SYNC \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ /*
+ * V2_L2 Ethernet any event
+ * SYNC, Follow_Up, Delay_Req, Delay_Resp,
+ * Pdelay_Req, Pdelay_Resp, Pdelay_Resp_Follow_Up
+ *
+ * SNAPTYPSEL=1, TSMSTRENA=x, TSEVNTENA=0, TSVER2ENA=1,TSIPENA=1
+ * TSIPENA=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL1 | GMAC_TS_CTRL_TSVER2ENA | GMAC_TS_CTRL_TSIPENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_L2_EVENT \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ /*
+ * V2_L2 Master
+ * Delay_Req
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=1, TSEVNTENA=1, TSVER2ENA=1,TSIPENA=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSMSTRENA;
+ tsctl |= GMAC_TS_CTRL_TSEVNTENA | GMAC_TS_CTRL_TSVER2ENA;
+ tsctl |= GMAC_TS_CTRL_TSIPENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ /*
+ * V2_L2 Slave
+ * Sync
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=0, TSEVNTENA=1, TSVER2ENA=1,
+ * TSIPENA=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSVER2ENA;
+ tsctl |= GMAC_TS_CTRL_TSEVNTENA | GMAC_TS_CTRL_TSIPENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_L2_SYNC \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ /*
+ * V2_L2 Ethernet any event
+ * SYNC, Follow_Up, Delay_Req, Delay_Resp,
+ * Pdelay_Req, Pdelay_Resp, Pdelay_Resp_Follow_Up
+ *
+ * SNAPTYPSEL=1, TSMSTRENA=x, TSEVNTENA=0, TSVER2ENA=1
+ * TSIPENA=1, TSIPV4ENA=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL1 | GMAC_TS_CTRL_TSVER2ENA;
+ tsctl |= GMAC_TS_CTRL_TSIPENA | GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_EVENT \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ /*
+ * V2_L2_L4 Master
+ * Delay_Req
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=1, TSEVNTENA=1,
+ * TSVER2ENA=1,TSIPENA=1, TSIPV4ENA=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSMSTRENA;
+ tsctl |= GMAC_TS_CTRL_TSEVNTENA | GMAC_TS_CTRL_TSVER2ENA;
+ tsctl |= GMAC_TS_CTRL_TSIPENA | GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_DELAY_REQ \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ /*
+ * V2_L2_L4 Slave
+ * Sync
+ *
+ * SNAPTYPSEL=0, TSMSTRENA=0, TSEVNTENA=1, TSVER2ENA=1,
+ * TSIPENA=1, TSIPV4ENA=1
+ */
+ tsctl |= GMAC_TS_CTRL_SNTYPSEL0 | GMAC_TS_CTRL_TSVER2ENA;
+ tsctl |= GMAC_TS_CTRL_TSEVNTENA | GMAC_TS_CTRL_TSIPENA;
+ tsctl |= GMAC_TS_CTRL_TSIPV4ENA;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_PTP_V2_SYNC \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_ALL:
+ /*
+ * V2_L2_L4 Ethernet any event
+ *
+ * SYNC, Follow_Up, Delay_Req, Delay_Resp,
+ * Pdelay_Req, Pdelay_Resp, Pdelay_Resp_Follow_Up
+ *
+ * GMAC_TS_CTRL_TSENALL
+ */
+ tsctl |= GMAC_TS_CTRL_TSENALL;
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_ALL \n", __func__);
+ break;
+
+ case HWTSTAMP_FILTER_NONE:
+ printk(KERN_INFO "%s HWTSTAMP_FILTER_NONE \n", __func__);
+ priv->hwts &= ~STMMAC_PTP_HWTS_RX_EN;
+ break;
+
+ default:
+ printk(KERN_INFO "%s error ioctl rx type %d \n", __func__, config.rx_filter);
+ /* bad/unknown parameter */
+ return -ERANGE;
+ }
+
+ /* Set the TS CTRL reg */
+ tsctl |= GMAC_TS_CTRL_TSENA;
+ writel(tsctl, priv->ioaddr + GMAC_TS_CTRL);
+ wmb();
+
+ printk(KERN_INFO "%s sync ts_ctl @ value 0x%08x\n", __func__, tsctl);
+
+ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+
+
+#define DEFAULT_PTP_CLK 50
+
+/**
+ * stmmac_ptp_init_timestamp - initialise the PTP clock
+ * @priv - pointer to the priv structure
+ *
+ * This function initialises the PTP clock consistent with the method spelled
+ * out in the Snopsys documentation
+ */
+static void stmmac_ptp_init_timestamp(struct stmmac_priv *priv)
+{
+ unsigned long tsctl = GMAC_TS_CTRL_TSENA, flags = 0;
+ uint8_t ssinc = CONFIG_STMMAC_PTP_CLK_MHZ;
+
+ /* Enable TS */
+ writel(tsctl, priv->ioaddr + GMAC_TS_CTRL);
+ wmb();
+
+ /* Write SSINC - number of nano seconds to increment on each clock */
+ if(ssinc == 0){
+ ssinc = DEFAULT_PTP_CLK;
+ }
+ ssinc = 1000/ssinc;
+ writel(ssinc, priv->ioaddr + GMAC_SS_INC);
+ wmb();
+
+ printk(KERN_INFO "%s setting PTP_CLK to 0x%02x\n", __func__, ssinc);
+
+ /* Reset system time registers to zero */
+ writel(0x00000000, priv->ioaddr + GMAC_ST_SEC);
+ writel(0x00000000, priv->ioaddr + GMAC_ST_NSEC);
+ wmb();
+
+ /* Set TSINT to latch values in ST_SEC and ST_NSEC */
+ tsctl |= GMAC_TS_CTRL_TSINT;
+ writel(tsctl, priv->ioaddr + GMAC_TS_CTRL);
+ wmb();
+ printk(KERN_INFO "%s tsctl == 0x%08lx (TSINIT | TSENA)\n", __func__, tsctl);
+
+ spin_lock_irqsave(&priv->tmreg_lock, flags);
+
+ /* Init timecounter */
+ memset(&priv->ccnt, 0, sizeof(priv->ccnt));
+ priv->ccnt.read = stmmac_ptp_read;
+ priv->ccnt.mask = CLOCKSOURCE_MASK(64);
+ priv->ccnt.mult = 1;
+ priv->ccnt.shift = 0;
+
+ /* reset the ns time counter */
+ timecounter_init(&priv->tcnt, &priv->ccnt,
+ ktime_to_ns(ktime_get_real()));
+
+ spin_unlock_irqrestore(&priv->tmreg_lock, flags);
+}
+
+/**
+ * stmmac_ptp_init
+ * @priv - the stmmac private priv structure
+ *
+ * This function performs the required steps for enabling ptp
+ * support. If ptp support has already been loaded it simply calls the
+ * cyclecounter init routine and exits.
+ */
+void stmmac_ptp_init(struct net_device *ndev, struct device * pdev)
+{
+ struct stmmac_priv *priv = netdev_priv(ndev);
+
+ /* Ensure the timestamp interrupt is masked */
+ writel(GMAC_INT_MASK_TSIM, priv->ioaddr + GMAC_INT_MASK);
+
+ /* Fill out PTP callback contents */
+ snprintf(priv->ptp_caps.name, 16, "%pm", ndev->dev_addr);
+ priv->ptp_caps.owner = THIS_MODULE;
+ priv->ptp_caps.max_adj = 0; /* Cannot be adjusted */
+ priv->ptp_caps.n_alarm = 0;
+ priv->ptp_caps.n_ext_ts = 0;
+ priv->ptp_caps.n_per_out = 0;
+ priv->ptp_caps.pps = 0;
+ priv->ptp_caps.adjfreq = stmmac_ptp_adjfreq;
+ priv->ptp_caps.adjtime = stmmac_ptp_adjtime;
+ priv->ptp_caps.gettime = stmmac_ptp_gettime;
+ priv->ptp_caps.settime = stmmac_ptp_settime;
+ priv->ptp_caps.enable = stmmac_ptp_enable;
+
+ spin_lock_init(&priv->tmreg_lock);
+
+ stmmac_ptp_init_timestamp(priv);
+
+ /* Init to default state */
+// priv->hwts = STMMAC_PTP_OVERFLOW_CHECK_ENABLED;
+
+ priv->ptp_clock = ptp_clock_register(&priv->ptp_caps, pdev);
+ if (IS_ERR(priv->ptp_clock)) {
+ priv->ptp_clock = NULL;
+ printk(KERN_ERR "%s ptp_clock_reg failed!\n", __func__);
+ } else {
+ printk(KERN_INFO "%s ptp_clock_reg success!\n", __func__);
+ }
+
+ return;
+}
+
+/**
+ * stmmac_ptp_remove - disable ptp device and stop the overflow check
+ * @priv: pointer to priv struct
+ *
+ * this function stops the ptp support, and cancels the delayed work.
+ */
+void stmmac_ptp_remove(struct stmmac_priv *priv)
+{
+ /* Ensure the timestamp interrupt is masked */
+ writel(GMAC_INT_MASK_TSIM, priv->ioaddr + GMAC_INT_MASK);
+
+ /* stop the overflow check task */
+// priv->hwts &= ~STMMAC_PTP_OVERFLOW_CHECK_ENABLED;
+
+ if (priv->ptp_clock != NULL) {
+ ptp_clock_unregister(priv->ptp_clock);
+ priv->ptp_clock = NULL;
+ printk(KERN_INFO "%s removed ptp_clock\n", __func__);
+ }
+}
+
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 044b532..dc92097 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -95,7 +95,7 @@ static struct class mdio_bus_class = {
#if IS_ENABLED(CONFIG_OF_MDIO)
/* Helper function for of_mdio_find_bus */
-static int of_mdio_bus_match(struct device *dev, void *mdio_bus_np)
+static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np)
{
return dev->of_node == mdio_bus_np;
}
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index c86bae8..4d56ffb 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -672,6 +672,76 @@ config INTEL_MFLD_THERMAL
Say Y here to enable thermal driver support for the Intel Medfield
platform.
+config INTEL_CLN_ESRAM
+ bool "eSRAM - embedded SRAM driver for Intel Clanton platform"
+ depends on INTEL_CLN_SOC && PM
+ select KALLSYMS
+ select CRC16
+ help
+ Say Y here to enable eSRAM overlay and software-initiated ECC
+ updates. eSRAM overlaying allows for code/data structures to be
+ mapped into eSRAM thus providing far faster access to code/data
+ than ordinary DRAM. Slower than cache RAM faster than DRAM.
+
+config INTEL_CLN_ECC_REFRESH_PERIOD
+ int "Choose eSRAM ECC coverage period"
+ depends on INTEL_CLN_ESRAM
+ default 24
+ help
+ Select the period over which *RAM ECC codes should be refreshed.
+ IA Core will periodically enable disabled eSRAM pages to ensure all of
+ disabled eSRAM pages are 'address walked' in this period. A logical
+ component within the silicon on Clanton will ensure DRAM (and
+ overlayed eSRAM) pages by extension are similarly updated over the
+ same period. This variable controlls how long a time this address
+ walking algorithm should take. For a noisy environment like a
+ sub-station or a satellite update frequently. For less noisy
+ environments this value should be lower. Default 24 hours is right for
+ most people. Set to zero to disable - this is NOT recommended. Max 48
+ hours.
+
+config INTEL_CLN_ECC_SCRUB
+ bool "Hardware ECC Scrub - /proc interface for Intel Clanton platform"
+ depends on INTEL_CLN_SOC
+ help
+ Say Y here to enable support for accessing the hardware memory
+ ECC Scrubber via the /proc interface.
+
+config INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG
+ bool "Hardware ECC Scrub - use config settings to override scrub vals"
+ depends on INTEL_CLN_ECC_SCRUB
+ help
+ Say Y here to enable support to use config settings to override
+ BIOS configured scrub values
+
+config INTEL_CLN_HW_ECC_REFRESH_RATE
+ int "Choose DRAM ECC refresh rate"
+ depends on INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG
+ default 20
+ help
+ Range 0 - 255 mSec
+
+config INTEL_CLN_HW_ECC_REFRESH_SIZE
+ int "Choose DRAM ECC refresh size"
+ depends on INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG
+ default 512
+ help
+ Range 64-512 bytes, multiples of 32
+
+config INTEL_CLN_ECC_SCRUB_S3_CONFIG
+ bool "Hardware ECC Scrub - linux manages S3 entry/resume for scrub"
+ depends on INTEL_CLN_ECC_SCRUB
+ help
+ Say Y here to enable linux to manage S3 entry/resume for the
+ hardware memory ECC Scrubber.
+
+config INTEL_CLN_THERMAL
+ bool "Thermal driver for Intel Clanton platform"
+ depends on INTEL_CLN_SOC
+ help
+ Say Y here to enable Clanton's Thermal driver plus the MSI's
+ that can be hooked from the thermal sub-system
+
config INTEL_IPS
tristate "Intel Intelligent Power Sharing"
depends on ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index bf7e4f9..06dd3bc 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -36,6 +36,8 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
+obj-$(CONFIG_INTEL_CLN_ECC_SCRUB) += intel_cln_ecc_scrub.o
+obj-$(CONFIG_INTEL_CLN_THERMAL) += intel_cln_thermal.o
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
@@ -50,3 +52,5 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o
+
+obj-$(CONFIG_INTEL_CLN_SPI_UPDATE) += intel_cln_spi_update.o
diff --git a/drivers/platform/x86/intel_cln_ecc_scrub.c b/drivers/platform/x86/intel_cln_ecc_scrub.c
new file mode 100644
index 0000000..dd5b434
--- /dev/null
+++ b/drivers/platform/x86/intel_cln_ecc_scrub.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton DRAM ECC Scrub driver
+ *
+ * !!!!!!! Description
+ *
+ */
+#include <asm-generic/uaccess.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+
+#define DRIVER_NAME "intel-cln-ecc"
+#define INTEL_CLN_ECC_SCRUB_PROCDIR "driver/ecc_scrub"
+#define STATUS "status"
+#define CONTROL "control"
+#define INTERVAL "interval"
+#define ECC_BLOCK_SIZE "block_size"
+
+#define CONTROL_USAGE "ECC Scrub Control: invalid setting. "\
+ "Valid values are 1 or 0\n"
+#define CONTROL_SCRUB_ON_STR "1\n"
+#define CONTROL_SCRUB_OFF_STR "0\n"
+#define CONTROL_ON_STR "on\n"
+#define CONTROL_OFF_STR "off\n"
+
+#define INTERVAL_USAGE "ECC Scrub Interval: invalid setting. "\
+ "Valid range is 1 - 255\n"
+#define SIZE_USAGE "ECC Scrub Block Size: invalid setting. "\
+ "Valid range is 64 - 512\n"
+
+#define OVERRIDE_CONFIG_PARM_DESC "Clanton ECC Scrub - "\
+ "Override BIOS settings "\
+ "for Scrub Config"
+
+#define OVERRIDE_START_PARM_DESC "Clanton ECC Scrub - "\
+ "Override BIOS settings "\
+ "for Scrub Start address"
+
+#define OVERRIDE_END_PARM_DESC "Clanton ECC Scrub - "\
+ "Override BIOS settings "\
+ "for Scrub End address"
+
+#define OVERRIDE_NEXT_PARM_DESC "Clanton ECC Scrub - "\
+ "Override BIOS settings "\
+ "for Scrub Next address"
+
+#define MAX_SCRUB_BLOCK_SIZE 512
+#define MIN_SCRUB_BLOCK_SIZE 64
+#define MAX_SCRUB_REFRESH 255
+#define MIN_SCRUB_REFRESH 0
+
+#define NOT_OVERRIDDEN 0xfffffffful
+
+/* Shorten fn names to fit 80 char limit */
+#ifndef sb_read
+#define sb_read intel_cln_sb_read_reg
+#endif
+#ifndef sb_write
+#define sb_write intel_cln_sb_write_reg
+#endif
+
+/* Register ID */
+#define ECC_SCRUB_CONFIG_REG (0x50)
+#define ECC_SCRUB_START_MEM_REG (0x76)
+#define ECC_SCRUB_END_MEM_REG (0x77)
+#define ECC_SCRUB_NEXT_READ_REG (0x7C)
+
+
+/* Reg commands */
+#define THERMAL_CTRL_READ (0x10)
+#define THERMAL_CTRL_WRITE (0x11)
+#define THERMAL_RESUME_SCRUB (0xC2)
+#define THERMAL_PAUSE_SCRUB (0xC3)
+
+/**
+ * struct intel_cln_ecc_scrub_dev
+ *
+ * Structure to represent module state/data/etc
+ */
+struct intel_cln_ecc_scrub_dev {
+
+ /* Linux kernel structures */
+ struct platform_device *pldev; /* Platform device */
+ struct proc_dir_entry *pdir; /* Proc directory */
+ /* /proc/driver/ecc_scrub/ */
+ struct proc_dir_entry *pcontrol; /* ""/control */
+ struct proc_dir_entry *pstatus; /* ""/status */
+ struct proc_dir_entry *pinterval; /* ""/interval */
+ struct proc_dir_entry *psize; /* ""/block_size */
+
+ /* Register copies */
+ u32 start_address;
+ u32 end_address;
+ u32 next_address;
+ u32 config;
+
+};
+
+static struct intel_cln_ecc_scrub_dev ecc_scrub_dev;
+
+static u32 ecc_scrub_config_override = NOT_OVERRIDDEN;
+static u32 ecc_scrub_start_override = NOT_OVERRIDDEN;
+static u32 ecc_scrub_end_override = NOT_OVERRIDDEN;
+static u32 ecc_scrub_next_override = NOT_OVERRIDDEN;
+
+#ifdef CONFIG_PROC_FS
+
+
+/**
+ * intel_cln_ecc_scrub_stat_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Populates ecc_scrub state via /proc/driver/ecc_scrub/status
+ */
+static int intel_cln_ecc_scrub_stat_read(char *page, char **start,
+ off_t off, int count,
+ int *eof, void *data)
+
+{
+ int len = 0, size = 0;
+ u32 reg_data = 0;
+ char *scrub_status = CONTROL_OFF_STR;
+
+ /* Display start of memory address */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_START_MEM_REG,
+ &reg_data, 1);
+ len += snprintf(page + len, count - len,
+ "ecc scrub mem start\t\t\t: 0x%08x\n", reg_data);
+
+
+ /* Display end of memory address */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_END_MEM_REG,
+ &reg_data, 1);
+ len += snprintf(page + len, count - len,
+ "ecc scrub mem end\t\t\t: 0x%08x\n", reg_data);
+
+ /* Display next address to be read */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_NEXT_READ_REG,
+ &reg_data, 1);
+ len += snprintf(page + len, count - len,
+ "ecc scrub next read\t\t\t: 0x%08x\n", reg_data);
+
+ /* Display config settings */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+
+ /* Interval is the lsbyte of the config reg, so mask out just
+ * that byte in the data printed. */
+ len += snprintf(page + len, count - len,
+ "ecc scrub interval\t\t\t: %d\n",
+ (reg_data & 0x000000ff));
+
+ /* Size is indicated in bits 12:8 of register in
+ * terms of 32 byte blocks. */
+ size = ((reg_data & 0x00001f00) >> 8)*32;
+ len += snprintf(page + len, count - len,
+ "ecc scrub block_size\t\t\t: %d\n", size);
+
+ /* Status is indicated in bit 13 of register. */
+ if ((reg_data & 0x00002000) > 0)
+ scrub_status = CONTROL_ON_STR;
+
+ len += snprintf(page + len, count - len,
+ "ecc scrub status\t\t\t: %s\n", scrub_status);
+ *eof = 1;
+
+ return len;
+}
+
+/**
+ * intel_cln_ecc_scrub_ctrl_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Populates ecc_scrub state via /proc/driver/ecc_scrub/control
+ */
+static int intel_cln_ecc_scrub_ctrl_read(char *page, char **start,
+ off_t off, int count,
+ int *eof, void *data)
+
+{
+ int len = 0;
+ u32 reg_data = 0;
+ char *on_or_off = CONTROL_SCRUB_OFF_STR;
+
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+
+ /* Status is indicated in bit 13 of register. */
+ if ((reg_data & 0x00002000) > 0)
+ /* interval > 0 assume scrubbing on */
+ on_or_off = CONTROL_SCRUB_ON_STR;
+
+ len += snprintf(page + len, count - len,
+ "%s", on_or_off);
+ *eof = 1;
+
+ return len;
+}
+
+/**
+ * intel_cln_ecc_scrub_ctrl_write
+ *
+ * @param file: File pointer
+ * @param buf: Data being sent from user-space
+ * @param count: Number of bytes being sent
+ * @param data: Statically set data in the /proc callback - unused
+ * @return number of bytes successfully written or < 0 to indicate error
+ *
+ * Function allows user-space to switch on/off scrubbing with a simple
+ * echo 1/0 > /proc/driver/ecc_scrub/control command
+ */
+static int
+intel_cln_ecc_scrub_ctrl_write(struct file *file, const char __user *buf,
+ unsigned long count, void *data)
+{
+ ssize_t ret = 0;
+ char *cbuf = NULL;
+
+ if (count <= 1)
+ return -EINVAL;
+
+
+ /* Get input */
+ cbuf = kzalloc(count+1, GFP_KERNEL);
+ if (cbuf == NULL)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (!copy_from_user(cbuf, buf, count)) {
+ ret = -EINVAL;
+
+ /* Check for command starting with "scrub"
+ * and ending with "on" or "off" */
+
+ if (!strcmp(cbuf, CONTROL_SCRUB_ON_STR)) {
+ sb_write(SB_ID_THERMAL, THERMAL_RESUME_SCRUB,
+ 0, 0, 1);
+ ret = 0;
+ } else if (!strcmp(cbuf, CONTROL_SCRUB_OFF_STR)) {
+ sb_write(SB_ID_THERMAL, THERMAL_PAUSE_SCRUB, 0,
+ 0, 1);
+ ret = 0;
+ }
+ }
+
+
+ if (ret == 0)
+ ret = (ssize_t)count;
+
+ else if (ret == -EINVAL)
+ printk(CONTROL_USAGE);
+
+ kfree(cbuf);
+ return ret;
+}
+
+/**
+ * intel_cln_ecc_scrub_intrvl_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Populates ecc_scrub state via /proc/driver/ecc_scrub/interval
+ */
+static int intel_cln_ecc_scrub_intrvl_read(char *page, char **start,
+ off_t off,
+ int count, int *eof,
+ void *data)
+
+{
+ int len = 0;
+ u32 reg_data = 0;
+
+ /* Interval is the lsbyte of the config reg,
+ * so mask out just that byte in the data printed. */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+ len += snprintf(page + len, count - len,
+ "%d\n", (reg_data & 0x000000ff));
+ *eof = 1;
+
+ return len;
+}
+
+/**
+ * intel_cln_ecc_scrub_intrvl_write
+ *
+ * @param file: File pointer
+ * @param buf: Data being sent from user-space
+ * @param count: Number of bytes being sent
+ * @param data: Statically set data in the /proc callback - unused
+ * @return number of bytes successfully written or < 0 to indicate error
+ *
+ * Function allows user-space to set scrub interval with a value of 1-255
+ * echo 1-255 > /proc/driver/ecc_scrub/interval type command
+ */
+static int
+intel_cln_ecc_scrub_intrvl_write(struct file *file, const char __user *buf,
+ unsigned long count, void *data)
+{
+ ssize_t ret = 0;
+ char *cbuf = NULL;
+ unsigned long val = 0;
+ u32 reg_data = 0;
+ int ret_temp = 0;
+
+ if (count <= 1)
+ return -EINVAL;
+
+ /* Get input */
+ cbuf = kzalloc(count+1, GFP_KERNEL);
+ if (cbuf == NULL)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (!copy_from_user(cbuf, buf, count)) {
+ ret = -EINVAL;
+
+ ret_temp = kstrtoul(cbuf, 10, &val);
+
+ if (ret_temp)
+ return ret_temp;
+
+ if (val > MIN_SCRUB_REFRESH && val <= MAX_SCRUB_REFRESH) {
+ /* Need to read-modify-write config register. */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ,
+ ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+
+ reg_data &= 0xffffff00; /* clear lsb. */
+ reg_data |= val; /* now set interval. */
+
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_CONFIG_REG,
+ reg_data, 1);
+ ret = 0;
+ } else {
+ printk(INTERVAL_USAGE);
+ }
+
+ }
+
+ if (ret == 0)
+ ret = (ssize_t)count;
+ kfree(cbuf);
+ return ret;
+}
+
+/**
+ * intel_cln_ecc_scrub_size_read
+ *
+ * @param page: buffer to write data into
+ * @param start: where the data has been written in the page
+ * @param offset: same meaning as read system call
+ * @param count: same meaning as read system call
+ * @param eof: set if no more data needs to be returned
+ * @return number of bytes successfully read
+ *
+ * Populates ecc_scrub state via /proc/driver/ecc_scrub/block_size
+ */
+static int intel_cln_ecc_scrub_size_read(char *page, char **start,
+ off_t off,
+ int count, int *eof,
+ void *data)
+
+{
+ int len = 0;
+ int size = 0;
+ u32 reg_data = 0;
+
+ /* Size is indicated in bits 12:8 of config register
+ * multiply x32 to get num bytes). */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+ size = ((reg_data & 0x00001f00) >> 8)*32;
+
+ len += snprintf(page + len, count - len,
+ "%d\n", size);
+ *eof = 1;
+
+ return len;
+}
+
+/**
+ * intel_cln_ecc_scrub_size_write
+ *
+ * @param file: File pointer
+ * @param buf: Data being sent from user-space
+ * @param count: Number of bytes being sent
+ * @param data: Statically set data in the /proc callback - unused
+ * @return number of bytes successfully written or < 0 to indicate error
+ *
+ * Function allows user-space to set scrub block size of 64-512 with a simple
+ * echo 64-512 > /proc/driver/ecc_scrub/block_size command
+ */
+static int
+intel_cln_ecc_scrub_size_write(struct file *file, const char __user *buf,
+ unsigned long count, void *data)
+{
+ ssize_t ret = 0;
+ char *cbuf = NULL;
+ unsigned long val = 0;
+ u32 reg_data = 0;
+ int ret_temp = 0;
+
+ if (count <= 1)
+ return -EINVAL;
+
+ /* Get input */
+ cbuf = kzalloc(count+1, GFP_KERNEL);
+ if (cbuf == NULL)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (!copy_from_user(cbuf, buf, count)) {
+ ret = -EINVAL;
+
+ ret_temp = kstrtoul(cbuf, 10, &val);
+
+ if (ret_temp)
+ return ret_temp;
+
+ if (val >= MIN_SCRUB_BLOCK_SIZE
+ && val <= MAX_SCRUB_BLOCK_SIZE){
+ /* Need to read-modify-write config register. */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ,
+ ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+
+ reg_data &= 0xfffffe0ff; /* clear bits 12:8 */
+ reg_data |= (val/32)<<8; /* now set size */
+
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_CONFIG_REG,
+ reg_data, 1);
+ ret = 0;
+ } else {
+ printk(SIZE_USAGE);
+ }
+
+ }
+
+ if (ret == 0)
+ ret = (ssize_t)count;
+ kfree(cbuf);
+ return ret;
+}
+
+/**
+ * intel_cln_ecc_scrub_addfs
+ *
+ * @return 0 on success or standard errnos on failure
+ *
+ * Adds entries to procfs
+ */
+static int intel_cln_ecc_scrub_add(void)
+{
+ ecc_scrub_dev.pdir = proc_mkdir(INTEL_CLN_ECC_SCRUB_PROCDIR, NULL);
+ if (ecc_scrub_dev.pdir == NULL)
+ return -ENOMEM;
+
+
+ ecc_scrub_dev.pstatus = create_proc_read_entry(STATUS, 0,
+ ecc_scrub_dev.pdir,
+ intel_cln_ecc_scrub_stat_read,
+ NULL);
+ if (ecc_scrub_dev.pstatus == NULL)
+ return -EIO;
+
+ ecc_scrub_dev.pcontrol = create_proc_entry(CONTROL, 0,
+ ecc_scrub_dev.pdir);
+ if (ecc_scrub_dev.pcontrol == NULL)
+ return -EIO;
+
+ ecc_scrub_dev.pcontrol->read_proc = intel_cln_ecc_scrub_ctrl_read;
+ ecc_scrub_dev.pcontrol->write_proc = intel_cln_ecc_scrub_ctrl_write;
+ ecc_scrub_dev.pcontrol->data = NULL;
+
+ ecc_scrub_dev.pinterval = create_proc_entry(INTERVAL, 0,
+ ecc_scrub_dev.pdir);
+ if (ecc_scrub_dev.pinterval == NULL)
+ return -EIO;
+
+ ecc_scrub_dev.pinterval->read_proc = intel_cln_ecc_scrub_intrvl_read;
+ ecc_scrub_dev.pinterval->write_proc = intel_cln_ecc_scrub_intrvl_write;
+ ecc_scrub_dev.pinterval->data = NULL;
+
+ ecc_scrub_dev.psize = create_proc_entry(ECC_BLOCK_SIZE, 0,
+ ecc_scrub_dev.pdir);
+ if (ecc_scrub_dev.psize == NULL)
+ return -EIO;
+
+ ecc_scrub_dev.psize->read_proc = intel_cln_ecc_scrub_size_read;
+ ecc_scrub_dev.psize->write_proc = intel_cln_ecc_scrub_size_write;
+ ecc_scrub_dev.psize->data = NULL;
+
+ return 0;
+}
+
+/**
+ * intel_cln_ecc_scrub_proc_remove
+ *
+ * @return nothing
+ *
+ * Removes /proc entires
+ */
+static void intel_cln_ecc_scrub_proc_remove(void)
+{
+ remove_proc_entry(CONTROL, ecc_scrub_dev.pcontrol);
+ remove_proc_entry(INTERVAL, ecc_scrub_dev.pinterval);
+ remove_proc_entry(ECC_BLOCK_SIZE, ecc_scrub_dev.pinterval);
+ remove_proc_entry(STATUS, ecc_scrub_dev.pstatus);
+ remove_proc_entry(INTEL_CLN_ECC_SCRUB_PROCDIR, NULL);
+}
+
+#else
+
+static int intel_cln_ecc_scrub_add(void){ return 0; }
+static void intel_cln_ecc_scrub_remove(void){ return; }
+
+#endif /* CONFIG_PROC_FS */
+
+/*****************************************************************************
+ * Module/PowerManagement hooks
+ *****************************************************************************/
+/**
+ * intel_cln_ecc_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ *
+ */
+static int intel_cln_ecc_scrub_probe(struct platform_device *pdev)
+{
+ int value_overridden = 0;
+
+#ifdef CONFIG_INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG
+ u32 scrubber_refresh = 0;
+ u32 scrubber_block_size = 0;
+ u32 config_settings = 0;
+#endif
+
+ memset(&ecc_scrub_dev, 0x00, sizeof(ecc_scrub_dev));
+
+ /* Update config settings, if directed so to do */
+ if (ecc_scrub_start_override != NOT_OVERRIDDEN) {
+ /* start of memory address */
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_START_MEM_REG, ecc_scrub_start_override, 1);
+
+ value_overridden = 1;
+ }
+ if (ecc_scrub_end_override != NOT_OVERRIDDEN) {
+ /* end of memory address */
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_END_MEM_REG, ecc_scrub_end_override, 1);
+
+ value_overridden = 1;
+ }
+ if (ecc_scrub_next_override != NOT_OVERRIDDEN) {
+ /* next address to be read */
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_NEXT_READ_REG, ecc_scrub_next_override, 1);
+
+ value_overridden = 1;
+ }
+ if (ecc_scrub_config_override != NOT_OVERRIDDEN) {
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_CONFIG_REG, ecc_scrub_config_override, 1);
+
+ value_overridden = 1;
+ }
+
+ /* Config Reg can be updated by either command line or kconfig setting
+ * in the case where we have both the command line takes precedence.*/
+
+ else {
+#ifdef CONFIG_INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG
+ scrubber_refresh = CONFIG_INTEL_CLN_HW_ECC_REFRESH_RATE;
+ scrubber_block_size = CONFIG_INTEL_CLN_HW_ECC_REFRESH_SIZE;
+
+ if (scrubber_block_size > MAX_SCRUB_BLOCK_SIZE)
+ scrubber_block_size = MAX_SCRUB_BLOCK_SIZE;
+
+ else if (scrubber_block_size < MIN_SCRUB_BLOCK_SIZE)
+ scrubber_block_size = MIN_SCRUB_BLOCK_SIZE;
+
+ if (scrubber_refresh > MAX_SCRUB_REFRESH)
+ scrubber_refresh = MAX_SCRUB_REFRESH;
+
+
+ /* adjust block size to multiples of 32 -
+ * as that is what the register setting actually expects. */
+ config_settings = scrubber_block_size/32;
+ config_settings <<= 8;
+ config_settings += scrubber_refresh;
+
+ /* config settings */
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE,
+ ECC_SCRUB_CONFIG_REG, config_settings, 1);
+
+ value_overridden = 1;
+#endif
+ }
+
+ if (value_overridden)
+ sb_write(SB_ID_THERMAL, THERMAL_RESUME_SCRUB, 0, 0, 1);
+
+ return intel_cln_ecc_scrub_add();
+}
+
+/**
+ * intel_cln_ecc_scrub_suspend
+ *
+ * @param pdev: Platform device structure (unused)
+ * @return 0 success < 0 failure
+ *
+ */
+static int intel_cln_ecc_scrub_suspend(struct device *pdev)
+{
+#ifdef CONFIG_INTEL_CLN_ECC_SCRUB_S3_CONFIG
+ u32 reg_data = 0;
+
+ /* Store off the 4 registers associated with scrubbing. */
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_START_MEM_REG,
+ &reg_data, 1);
+ ecc_scrub_dev.start_address = reg_data;
+
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_END_MEM_REG,
+ &reg_data, 1);
+ ecc_scrub_dev.end_address = reg_data;
+
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_NEXT_READ_REG,
+ &reg_data, 1);
+ ecc_scrub_dev.next_address = reg_data;
+
+ sb_read(SB_ID_THERMAL, THERMAL_CTRL_READ, ECC_SCRUB_CONFIG_REG,
+ &reg_data, 1);
+ ecc_scrub_dev.config = reg_data;
+#endif
+ return 0;
+}
+
+/**
+ * intel_cln_ecc_scrub_resume
+ *
+ * @param pdev: Platform device structure (unused)
+ * @return 0 success < 0 failure
+ */
+static int intel_cln_ecc_scrub_resume(struct device *pdev)
+{
+#ifdef CONFIG_INTEL_CLN_ECC_SCRUB_S3_CONFIG
+
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE, ECC_SCRUB_START_MEM_REG,
+ ecc_scrub_dev.start_address, 1);
+
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE, ECC_SCRUB_END_MEM_REG,
+ ecc_scrub_dev.end_address, 1);
+
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE, ECC_SCRUB_NEXT_READ_REG,
+ ecc_scrub_dev.next_address, 1);
+
+ sb_write(SB_ID_THERMAL, THERMAL_CTRL_WRITE, ECC_SCRUB_CONFIG_REG,
+ ecc_scrub_dev.config, 1);
+
+ sb_write(SB_ID_THERMAL, THERMAL_RESUME_SCRUB, 0, 0, 1);
+
+#endif
+ return 0;
+}
+
+/**
+ * intel_cln_ecc_scrub_remove
+ *
+ * @return 0 success < 0 failure
+ *
+ * Removes a platform device
+ */
+static int intel_cln_ecc_scrub_remove(struct platform_device *pdev)
+{
+ intel_cln_ecc_scrub_proc_remove();
+
+ return 0;
+}
+
+/*
+ * Power management operations
+ */
+static const struct dev_pm_ops intel_cln_ecc_scrub_pm_ops = {
+ .suspend = intel_cln_ecc_scrub_suspend,
+ .resume = intel_cln_ecc_scrub_resume,
+};
+
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_ecc_scrub_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &intel_cln_ecc_scrub_pm_ops,
+ },
+ .probe = intel_cln_ecc_scrub_probe,
+ .remove = intel_cln_ecc_scrub_remove,
+};
+
+
+MODULE_AUTHOR("Derek Harnett <derek.harnett@intel.com>");
+MODULE_DESCRIPTION("Intel Clanton DRAM ECC-scrub driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_param(ecc_scrub_config_override, uint, 0644);
+MODULE_PARM_DESC(ecc_scrub_config_override, OVERRIDE_CONFIG_PARM_DESC);
+
+module_param(ecc_scrub_start_override, uint, 0644);
+MODULE_PARM_DESC(ecc_scrub_start_override, OVERRIDE_START_PARM_DESC);
+
+module_param(ecc_scrub_end_override, uint, 0644);
+MODULE_PARM_DESC(ecc_scrub_end_override, OVERRIDE_END_PARM_DESC);
+
+module_param(ecc_scrub_next_override, uint, 0644);
+MODULE_PARM_DESC(ecc_scrub_next_override, OVERRIDE_NEXT_PARM_DESC);
+
+module_platform_driver(intel_cln_ecc_scrub_driver);
+
diff --git a/drivers/platform/x86/intel_cln_thermal.c b/drivers/platform/x86/intel_cln_thermal.c
new file mode 100644
index 0000000..ce0da9cd
--- /dev/null
+++ b/drivers/platform/x86/intel_cln_thermal.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton Thermal driver
+ */
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/intel_cln_sb.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/thermal.h>
+#include <linux/timer.h>
+
+#define DRIVER_NAME "intel-cln-thrm"
+
+/* Definition of register locations for thermal management */
+#define THRM_CTRL_REG (0x80) /* Thermal control */
+#define THRM_MODE_REG (0xB0) /* Thermal mode */
+#define THRM_MODE_SENSOR_EN (0x00008000) /* Thermal mode sensor enable */
+#define THRM_TEMP_REG (0xB1) /* Thermal sensor temperature */
+#define THRM_TRPCLR_REG (0xB2) /* Catastropic/Hot trip/clear */
+#define THRM_AUXTRP_REG (0xB3) /* Aux0-Aux3 trip point */
+#define THRM_AUXCLR_REG (0xB4) /* Aux0-Aux3 clear trip */
+#define THRM_STATUS_REG (0xB5) /* Thermal sensor status */
+#define THRM_TRIPBEHAVE_REG (0xB6) /* Trip point behavior */
+#define THRM_MSIADDR_REG (0xC5) /* Thermal MSI addres reg */
+#define THRM_MSIDATA_REG (0xC6) /* Thermal MSI data reg */
+#define THRM_CTRL_READ (0x10) /* Config reg */
+#define THRM_CTRL_WRITE (0x11) /* Config reg */
+
+#define SOC_TSENSOR_REG (0x34)
+#define SOC_TSENSOR_RST (0x00000001)
+#define SOC_CTRL_READ (0x06)
+#define SOC_CTRL_WRITE (0x07)
+
+
+#define THRM_ZONE_COUNT 2 /* Only hot/critical relevant */
+#define ACTIVE_INTERVAL (1000)
+#define IDLE_INTERVAL (20000)
+#define MCELSIUS(x) ((x) * 1000)
+
+/* CPU Zone information */
+#define CATASTROPIC_ZONE 0
+#define HOT_ZONE 1
+#define AUX0_ZONE 2 /* Unused */
+#define AUX1_ZONE 3 /* Unused */
+#define AUX2_ZONE 4 /* Unused */
+#define AUX3_ZONE 5 /* Unused */
+#define MIN_USED_ZONE CATASTROPIC_ZONE
+#define MAX_USED_ZONE HOT_ZONE
+/*
+ * Default catastrophic/hot trip values - in degrees celsius
+ * Maximum temperature is 105 degrees
+ */
+#define CRIT_TEMP 104
+#define HOT_TEMP 95
+#define RAW2CELSIUS_DIFF 50
+
+static int driver_enable = 1;
+module_param(driver_enable, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(driver_enable, "Disable Thermal Driver Polling");
+
+/* Shorten fn names to fit 80 char limit */
+#ifndef sb_read
+#define sb_read intel_cln_sb_read_reg
+#endif
+#ifndef sb_write
+#define sb_write intel_cln_sb_write_reg
+#endif
+
+struct intel_cln_therm_zone {
+ enum thermal_trip_type type;
+ int trip_value;
+};
+
+/**
+ * struct intel_cln_thermal_dev
+ *
+ */
+struct intel_cln_thermal_dev {
+ enum thermal_device_mode mode;
+ struct intel_cln_therm_zone tzone[THRM_ZONE_COUNT];
+ struct mutex lock;
+ struct platform_device *pldev; /* Platform device */
+ struct thermal_zone_device *therm_dev; /* Thermal device */
+};
+
+static struct intel_cln_thermal_dev cln_tdev;
+
+/******************************************************************************
+ * Thermal API implementation
+ ******************************************************************************/
+
+/**
+ * get_temp
+ *
+ * @param tz: Thermal zone descriptor
+ *
+ * Get the current temperature
+ * We have exactly one thermal zone/sensor
+ * Value passed is an unsigned long - our sensor reports up to -50 celsius so we
+ * just clip at zero if the temperature is negative.
+ */
+static int intel_cln_thermal_get_temp(struct thermal_zone_device *tz,
+ unsigned long *temp)
+{
+ sb_read(SB_ID_THERMAL, THRM_CTRL_READ, THRM_TEMP_REG, (u32 *)temp, 1);
+ *temp -= RAW2CELSIUS_DIFF;
+
+ /* Clip to unsigned output value if sensor is reporting sub-zero */
+ if ((int)*temp < 0)
+ *temp = 0;
+
+ *temp = MCELSIUS(*temp&0x000000FF);
+
+ return 0;
+}
+
+/**
+ * get_trend
+ *
+ * Wears good clothes
+ */
+static int intel_cln_thermal_get_trend(struct thermal_zone_device *tz,
+ int trip, enum thermal_trend *trend)
+{
+ if (tz->temperature >= trip)
+ *trend = THERMAL_TREND_RAISING;
+ else
+ *trend = THERMAL_TREND_DROPPING;
+
+ return 0;
+}
+
+/**
+ * intel_cln_thermal_get_mode
+ *
+ * Get the mode
+ */
+static int intel_cln_thermal_get_mode(struct thermal_zone_device *tz,
+ enum thermal_device_mode *mode)
+{
+ mutex_lock(&cln_tdev.lock);
+ *mode = cln_tdev.mode;
+ mutex_unlock(&cln_tdev.lock);
+
+ return 0;
+}
+
+/**
+ * intel_cln_thermal_set_mode
+ *
+ * Set the mode
+ */
+static int intel_cln_thermal_set_mode(struct thermal_zone_device *tz,
+ enum thermal_device_mode mode)
+{
+ mutex_lock(&cln_tdev.lock);
+
+ if (mode == THERMAL_DEVICE_ENABLED)
+ cln_tdev.therm_dev->polling_delay = IDLE_INTERVAL;
+ else
+ cln_tdev.therm_dev->polling_delay = 0;
+ cln_tdev.mode = mode;
+
+ mutex_unlock(&cln_tdev.lock);
+
+ thermal_zone_device_update(cln_tdev.therm_dev);
+ pr_info("thermal polling set for duration=%d msec\n",
+ cln_tdev.therm_dev->polling_delay);
+ return 0;
+}
+
+/**
+ * intel_cln_thermal_get_trip_type
+ *
+ * Get trip type
+ */
+static int intel_cln_thermal_get_trip_type(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type *type)
+{
+ if (trip < MIN_USED_ZONE || trip > MAX_USED_ZONE)
+ return -EINVAL;
+
+ *type = cln_tdev.tzone[trip].type;
+ return 0;
+}
+
+/**
+ * intel_cln_thermal_get_trip_temp
+ *
+ * Get trip temp
+ */
+static int intel_cln_thermal_get_trip_temp(struct thermal_zone_device *tz,
+ int trip, unsigned long *temp)
+{
+ if (trip < MIN_USED_ZONE || trip > MAX_USED_ZONE)
+ return -EINVAL;
+
+ /* Convert the temperature into millicelsius */
+ *temp = cln_tdev.tzone[trip].trip_value;
+
+ return 0;
+}
+
+/**
+ * intel_cln_thermal_get_trip_type
+ *
+ * Get trip temp
+ */
+static int intel_cln_thermal_get_crit_temp(struct thermal_zone_device *tz,
+ unsigned long *temp)
+{
+ /* Critical zone */
+ *temp = cln_tdev.tzone[CATASTROPIC_ZONE].trip_value;
+ return 0;
+}
+
+static struct thermal_zone_device_ops intel_cln_thrm_dev_ops = {
+ .get_temp = intel_cln_thermal_get_temp,
+ .get_trend = intel_cln_thermal_get_trend,
+ .get_mode = intel_cln_thermal_get_mode,
+ .set_mode = intel_cln_thermal_set_mode,
+ .get_trip_type = intel_cln_thermal_get_trip_type,
+ .get_trip_temp = intel_cln_thermal_get_trip_temp,
+ .get_crit_temp = intel_cln_thermal_get_crit_temp,
+};
+
+
+
+/**
+ * intel_cln_init_zone
+ *
+ * Initialise a zone
+ */
+static void intel_cln_thermal_init_zone(struct intel_cln_therm_zone *tz,
+ enum thermal_trip_type type, int trip_value)
+{
+ tz->type = type;
+ tz->trip_value = MCELSIUS(trip_value);
+}
+
+/******************************************************************************
+ * Module Entry/Exit hooks
+ ******************************************************************************/
+
+/**
+ * intel_cln_thermal_probe
+ *
+ * @param pdev: Platform device
+ * @return 0 success < 0 failure
+ *
+ * Callback from platform sub-system to probe
+ *
+ * This routine registers a thermal device with the kernel's thermal management
+ * sub-system
+ */
+static int intel_cln_thermal_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ int critical_temp = 0, hot_temp = 0;
+ uint32_t regval = 0;
+
+ if (driver_enable == 0)
+ return 0;
+
+ memset(&cln_tdev, 0x00, sizeof(cln_tdev));
+
+ critical_temp = CRIT_TEMP;
+ hot_temp = HOT_TEMP;
+
+ /* Enumerate zone type data */
+ memset(&cln_tdev, 0x00, sizeof(cln_tdev));
+ mutex_init(&cln_tdev.lock);
+
+ /* Set initial state disabled */
+ cln_tdev.mode = THERMAL_DEVICE_ENABLED;
+
+ intel_cln_thermal_init_zone(&cln_tdev.tzone[CATASTROPIC_ZONE],
+ THERMAL_TRIP_CRITICAL, critical_temp);
+ intel_cln_thermal_init_zone(&cln_tdev.tzone[HOT_ZONE],
+ THERMAL_TRIP_HOT, hot_temp);
+
+ /* Register a thermal zone */
+ cln_tdev.therm_dev = thermal_zone_device_register(DRIVER_NAME,
+ THRM_ZONE_COUNT, 0, 0, &intel_cln_thrm_dev_ops,
+ 0, IDLE_INTERVAL, ACTIVE_INTERVAL);
+
+ if (IS_ERR(cln_tdev.therm_dev)) {
+ err = PTR_ERR(cln_tdev.therm_dev);
+ return err;
+ }
+
+ /* Read the BIOS configured hardware catastrophic trip temp */
+ sb_read(SB_ID_THERMAL, THRM_CTRL_READ, THRM_TRPCLR_REG, &regval, 1);
+ regval = (regval & 0xff) - 50;
+
+ pr_info("THRM: critical reset %d c hot %d c hardware failover %d c\n",
+ critical_temp, hot_temp, regval);
+
+ return 0;
+}
+
+/**
+ * intel_cln_thermal_remove
+ *
+ * @return 0 success < 0 failure
+ *
+ * Removes a platform device
+ */
+static int intel_cln_thermal_remove(struct platform_device *pdev)
+{
+ if (cln_tdev.therm_dev != NULL) {
+ thermal_zone_device_unregister(cln_tdev.therm_dev);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/*
+ * Platform structures useful for interface to PM subsystem
+ */
+static struct platform_driver intel_cln_thermal_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = intel_cln_thermal_probe,
+ .remove = intel_cln_thermal_remove,
+};
+
+module_platform_driver(intel_cln_thermal_driver);
+
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Clanton Thermal driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 8a7cfb3..5deac43 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -141,7 +141,7 @@ int power_supply_set_battery_charged(struct power_supply *psy)
}
EXPORT_SYMBOL_GPL(power_supply_set_battery_charged);
-static int power_supply_match_device_by_name(struct device *dev, void *data)
+static int power_supply_match_device_by_name(struct device *dev, const void *data)
{
const char *name = data;
struct power_supply *psy = dev_get_drvdata(dev);
@@ -149,7 +149,7 @@ static int power_supply_match_device_by_name(struct device *dev, void *data)
return strcmp(psy->name, name) == 0;
}
-struct power_supply *power_supply_get_by_name(char *name)
+struct power_supply *power_supply_get_by_name(const char *name)
{
struct device *dev = class_find_device(power_supply_class, NULL, name,
power_supply_match_device_by_name);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index e513cd9..03120a8 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -28,6 +28,10 @@ menuconfig PWM
if PWM
+config PWM_SYSFS
+ bool
+ default y if SYSFS
+
config PWM_AB8500
tristate "AB8500 PWM support"
depends on AB8500_CORE && ARCH_U8500
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 62a2963..f98371b 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_PWM) += core.o
+obj-$(CONFIG_PWM_SYSFS) += sysfs.o
obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 903138b..bfc8c05 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -272,6 +272,8 @@ int pwmchip_add(struct pwm_chip *chip)
if (IS_ENABLED(CONFIG_OF))
of_pwmchip_add(chip);
+ pwmchip_sysfs_export(chip);
+
out:
mutex_unlock(&pwm_lock);
return ret;
@@ -308,6 +310,8 @@ int pwmchip_remove(struct pwm_chip *chip)
free_pwms(chip);
+ pwmchip_sysfs_unexport(chip);
+
out:
mutex_unlock(&pwm_lock);
return ret;
@@ -400,10 +404,19 @@ EXPORT_SYMBOL_GPL(pwm_free);
*/
int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
{
+ int err;
+
if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
return -EINVAL;
- return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
+ err = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
+ if (err)
+ return err;
+
+ pwm->duty_cycle = duty_ns;
+ pwm->period = period_ns;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(pwm_config);
@@ -416,6 +429,8 @@ EXPORT_SYMBOL_GPL(pwm_config);
*/
int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
{
+ int err;
+
if (!pwm || !pwm->chip->ops)
return -EINVAL;
@@ -425,7 +440,13 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
if (test_bit(PWMF_ENABLED, &pwm->flags))
return -EBUSY;
- return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
+ err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
+ if (err)
+ return err;
+
+ pwm->polarity = polarity;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(pwm_set_polarity);
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
new file mode 100644
index 0000000..4cd6d78
--- /dev/null
+++ b/drivers/pwm/sysfs.c
@@ -0,0 +1,353 @@
+/*
+ * A simple sysfs interface for the generic PWM framework
+ *
+ * Copyright (C) 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on previous work by Lars Poeschel <poeschel@lemonage.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/export.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/kdev_t.h>
+#include <linux/pwm.h>
+
+struct pwm_export {
+ struct device child;
+ struct pwm_device *pwm;
+};
+
+static struct pwm_export *child_to_pwm_export(struct device *child)
+{
+ return container_of(child, struct pwm_export, child);
+}
+
+static struct pwm_device *child_to_pwm_device(struct device *child)
+{
+ struct pwm_export *export = child_to_pwm_export(child);
+
+ return export->pwm;
+}
+
+static ssize_t pwm_period_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
+{
+ const struct pwm_device *pwm = child_to_pwm_device(child);
+
+ return sprintf(buf, "%u\n", pwm->period);
+}
+
+static ssize_t pwm_period_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pwm_device *pwm = child_to_pwm_device(child);
+ unsigned int val;
+ int ret;
+
+ ret = kstrtouint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = pwm_config(pwm, pwm->duty_cycle, val);
+
+ return ret ? : size;
+}
+
+static ssize_t pwm_duty_cycle_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
+{
+ const struct pwm_device *pwm = child_to_pwm_device(child);
+
+ return sprintf(buf, "%u\n", pwm->duty_cycle);
+}
+
+static ssize_t pwm_duty_cycle_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pwm_device *pwm = child_to_pwm_device(child);
+ unsigned int val;
+ int ret;
+
+ ret = kstrtouint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = pwm_config(pwm, val, pwm->period);
+
+ return ret ? : size;
+}
+
+static ssize_t pwm_enable_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
+{
+ const struct pwm_device *pwm = child_to_pwm_device(child);
+ int enabled = test_bit(PWMF_ENABLED, &pwm->flags);
+
+ return sprintf(buf, "%d\n", enabled);
+}
+
+static ssize_t pwm_enable_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pwm_device *pwm = child_to_pwm_device(child);
+ int val, ret;
+
+ ret = kstrtoint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ switch (val) {
+ case 0:
+ pwm_disable(pwm);
+ break;
+ case 1:
+ ret = pwm_enable(pwm);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret ? : size;
+}
+
+static ssize_t pwm_polarity_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
+{
+ const struct pwm_device *pwm = child_to_pwm_device(child);
+
+ return sprintf(buf, "%s\n", pwm->polarity ? "inversed" : "normal");
+}
+
+static ssize_t pwm_polarity_store(struct device *child,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct pwm_device *pwm = child_to_pwm_device(child);
+ enum pwm_polarity polarity;
+ int ret;
+
+ if (sysfs_streq(buf, "normal"))
+ polarity = PWM_POLARITY_NORMAL;
+ else if (sysfs_streq(buf, "inversed"))
+ polarity = PWM_POLARITY_INVERSED;
+ else
+ return -EINVAL;
+
+ ret = pwm_set_polarity(pwm, polarity);
+
+ return ret ? : size;
+}
+
+static DEVICE_ATTR(period, 0644, pwm_period_show, pwm_period_store);
+static DEVICE_ATTR(duty_cycle, 0644, pwm_duty_cycle_show, pwm_duty_cycle_store);
+static DEVICE_ATTR(enable, 0644, pwm_enable_show, pwm_enable_store);
+static DEVICE_ATTR(polarity, 0644, pwm_polarity_show, pwm_polarity_store);
+
+static struct attribute *pwm_attrs[] = {
+ &dev_attr_period.attr,
+ &dev_attr_duty_cycle.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_polarity.attr,
+ NULL
+};
+
+static const struct attribute_group pwm_attr_group = {
+ .attrs = pwm_attrs,
+};
+
+static const struct attribute_group *pwm_attr_groups[] = {
+ &pwm_attr_group,
+ NULL,
+};
+
+static void pwm_export_release(struct device *child)
+{
+ struct pwm_export *export = child_to_pwm_export(child);
+
+ kfree(export);
+}
+
+static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
+{
+ struct pwm_export *export;
+ int ret;
+
+ if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
+ return -EBUSY;
+
+ export = kzalloc(sizeof(*export), GFP_KERNEL);
+ if (!export) {
+ clear_bit(PWMF_EXPORTED, &pwm->flags);
+ return -ENOMEM;
+ }
+
+ export->pwm = pwm;
+
+ export->child.release = pwm_export_release;
+ export->child.parent = parent;
+ export->child.devt = MKDEV(0, 0);
+ export->child.groups = pwm_attr_groups;
+ dev_set_name(&export->child, "pwm%u", pwm->hwpwm);
+
+ ret = device_register(&export->child);
+ if (ret) {
+ clear_bit(PWMF_EXPORTED, &pwm->flags);
+ kfree(export);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pwm_unexport_match(struct device *child, void *data)
+{
+ return child_to_pwm_device(child) == data;
+}
+
+static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
+{
+ struct device *child;
+
+ if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
+ return -ENODEV;
+
+ child = device_find_child(parent, pwm, pwm_unexport_match);
+ if (!child)
+ return -ENODEV;
+
+ /* for device_find_child() */
+ put_device(child);
+ device_unregister(child);
+ pwm_put(pwm);
+
+ return 0;
+}
+
+static ssize_t pwm_export_store(struct device *parent,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pwm_chip *chip = dev_get_drvdata(parent);
+ struct pwm_device *pwm;
+ unsigned int hwpwm;
+ int ret;
+
+ ret = kstrtouint(buf, 0, &hwpwm);
+ if (ret < 0)
+ return ret;
+
+ if (hwpwm >= chip->npwm)
+ return -ENODEV;
+
+ pwm = pwm_request_from_chip(chip, hwpwm, "sysfs");
+ if (IS_ERR(pwm))
+ return PTR_ERR(pwm);
+
+ ret = pwm_export_child(parent, pwm);
+ if (ret < 0)
+ pwm_put(pwm);
+
+ return ret ? : len;
+}
+
+static ssize_t pwm_unexport_store(struct device *parent,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pwm_chip *chip = dev_get_drvdata(parent);
+ unsigned int hwpwm;
+ int ret;
+
+ ret = kstrtouint(buf, 0, &hwpwm);
+ if (ret < 0)
+ return ret;
+
+ if (hwpwm >= chip->npwm)
+ return -ENODEV;
+
+ ret = pwm_unexport_child(parent, &chip->pwms[hwpwm]);
+
+ return ret ? : len;
+}
+
+static ssize_t pwm_npwm_show(struct device *parent,
+ struct device_attribute *attr,
+ char *buf)
+{
+ const struct pwm_chip *chip = dev_get_drvdata(parent);
+
+ return sprintf(buf, "%u\n", chip->npwm);
+}
+
+static struct device_attribute pwm_chip_attrs[] = {
+ __ATTR(export, 0200, NULL, pwm_export_store),
+ __ATTR(unexport, 0200, NULL, pwm_unexport_store),
+ __ATTR(npwm, 0444, pwm_npwm_show, NULL),
+ __ATTR_NULL,
+};
+
+static struct class pwm_class = {
+ .name = "pwm",
+ .owner = THIS_MODULE,
+ .dev_attrs = pwm_chip_attrs,
+};
+
+static int pwmchip_sysfs_match(struct device *parent, const void *data)
+{
+ return dev_get_drvdata(parent) == data;
+}
+
+void pwmchip_sysfs_export(struct pwm_chip *chip)
+{
+ struct device *parent;
+
+ /*
+ * If device_create() fails the pwm_chip is still usable by
+ * the kernel its just not exported.
+ */
+ parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
+ "pwmchip%d", chip->base);
+ if (IS_ERR(parent)) {
+ dev_warn(chip->dev,
+ "device_create failed for pwm_chip sysfs export\n");
+ }
+}
+
+void pwmchip_sysfs_unexport(struct pwm_chip *chip)
+{
+ struct device *parent;
+
+ parent = class_find_device(&pwm_class, NULL, chip,
+ pwmchip_sysfs_match);
+ if (parent) {
+ /* for class_find_device() */
+ put_device(parent);
+ device_unregister(parent);
+ }
+}
+
+static int __init pwm_sysfs_init(void)
+{
+ return class_register(&pwm_class);
+}
+subsys_initcall(pwm_sysfs_init);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 9592b93..42bd57d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -587,16 +587,16 @@ void rtc_update_irq(struct rtc_device *rtc,
}
EXPORT_SYMBOL_GPL(rtc_update_irq);
-static int __rtc_match(struct device *dev, void *data)
+static int __rtc_match(struct device *dev, const void *data)
{
- char *name = (char *)data;
+ const char *name = data;
if (strcmp(dev_name(dev), name) == 0)
return 1;
return 0;
}
-struct rtc_device *rtc_class_open(char *name)
+struct rtc_device *rtc_class_open(const char *name)
{
struct device *dev;
struct rtc_device *rtc = NULL;
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 593085a..df0c3c7 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -468,10 +468,10 @@ void scsi_unregister(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(scsi_unregister);
-static int __scsi_host_match(struct device *dev, void *data)
+static int __scsi_host_match(struct device *dev, const void *data)
{
struct Scsi_Host *p;
- unsigned short *hostnum = (unsigned short *)data;
+ const unsigned short *hostnum = data;
p = class_to_shost(dev);
return p->host_no == *hostnum;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 4375417..0fab6b5 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -268,18 +268,11 @@ static inline bool _the_same_or_null(const u8 *a1, unsigned a1_len,
return 0 == memcmp(a1, a2, a1_len);
}
-struct find_oud_t {
- const struct osd_dev_info *odi;
- struct device *dev;
- struct osd_uld_device *oud;
-} ;
-
-int _mach_odi(struct device *dev, void *find_data)
+static int _match_odi(struct device *dev, const void *find_data)
{
struct osd_uld_device *oud = container_of(dev, struct osd_uld_device,
class_dev);
- struct find_oud_t *fot = find_data;
- const struct osd_dev_info *odi = fot->odi;
+ const struct osd_dev_info *odi = find_data;
if (_the_same_or_null(oud->odi.systemid, oud->odi.systemid_len,
odi->systemid, odi->systemid_len) &&
@@ -287,7 +280,6 @@ int _mach_odi(struct device *dev, void *find_data)
odi->osdname, odi->osdname_len)) {
OSD_DEBUG("found device sysid_len=%d osdname=%d\n",
odi->systemid_len, odi->osdname_len);
- fot->oud = oud;
return 1;
} else {
return 0;
@@ -301,19 +293,19 @@ int _mach_odi(struct device *dev, void *find_data)
*/
struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi)
{
- struct find_oud_t find = {.odi = odi};
-
- find.dev = class_find_device(&osd_uld_class, NULL, &find, _mach_odi);
- if (likely(find.dev)) {
+ struct device *dev = class_find_device(&osd_uld_class, NULL, odi, _match_odi);
+ if (likely(dev)) {
struct osd_dev_handle *odh = kzalloc(sizeof(*odh), GFP_KERNEL);
+ struct osd_uld_device *oud = container_of(dev,
+ struct osd_uld_device, class_dev);
if (unlikely(!odh)) {
- put_device(find.dev);
+ put_device(dev);
return ERR_PTR(-ENOMEM);
}
- odh->od = find.oud->od;
- odh->oud = find.oud;
+ odh->od = oud->od;
+ odh->oud = oud;
return &odh->od;
}
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 31969f2..59d427b 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -183,10 +183,10 @@ static struct attribute_group iscsi_endpoint_group = {
#define ISCSI_MAX_EPID -1
-static int iscsi_match_epid(struct device *dev, void *data)
+static int iscsi_match_epid(struct device *dev, const void *data)
{
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
- uint64_t *epid = (uint64_t *) data;
+ const uint64_t *epid = data;
return *epid == ep->id;
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2e188e1..84bcdf1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -35,6 +35,14 @@ config SPI_DEBUG
Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
sysfs, and debugfs support in SPI controller and protocol drivers.
+config GEN3_SPI
+ bool "Intel Media SOC SPI support"
+ depends on SPI && ARCH_GEN3 && INTEL_CLN_SOC
+ default y
+ help
+ This option enables Intel Media SOC SPI support.
+ For Clanton this option depends on INTEL_CLN_SOC.
+
#
# MASTER side ... talking to discrete SPI slave chips including microcontrollers
#
@@ -74,7 +82,15 @@ config SPI_ATMEL
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
-config SPI_BFIN5XX
+config SPI_CE5XX_SPI_FLASH
+ tristate "CE5XX SPI FLASH"
+ depends on ARCH_GEN3 && HW_MUTEXES
+ default y
+ help
+ This selects a driver for CE5XX Serial Flash controler
+
+
+config SPI_BFIN
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN
help
@@ -302,12 +318,21 @@ config SPI_PXA2XX
depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
select PXA_SSP if ARCH_PXA
help
- This enables using a PXA2xx or Sodaville SSP port as a SPI master
+ This enables using a PXA2xx or Intel CE4100/CE4200/CE5300 port as a SPI master
controller. The driver can be configured to use any SSP port and
additional documentation can be found a Documentation/spi/pxa2xx.
config SPI_PXA2XX_PCI
- def_bool SPI_PXA2XX && X86_32 && PCI
+ tristate "Intel CE SPI PCI adapter"
+ depends on SPI_PXA2XX && X86_32 && PCI && GEN3_SPI
+ help
+ This driver supports the Intel CE SPI master controller and acts
+ as the PCI-SPI glue code for PXA's driver
+
+config SPI_CE5XX_SPI_SLAVE
+ tristate "CE5XX SPI SLAVE"
+ help
+ This selects a driver for CE5XX SPI Slave controler, it is emudulated into a spi device
config SPI_RSPI
tristate "Renesas RSPI controller"
@@ -471,6 +496,14 @@ config SPI_DW_MMIO
depends on SPI_DESIGNWARE && HAVE_CLK
#
+# Bring out the LPC_SCH SPI block
+#
+
+config SPI_LPC_SCH
+ tristate "LPC SCH Legacy SPI controller"
+ depends on LPC_SCH
+
+#
# There are lots of SPI device types, with sensors and memory
# being probably the most widely used ones.
#
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 64e970b..b67de97 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
+obj-$(CONFIG_SPI_LPC_SCH) += spi-lpc-sch.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index c7cf0b7..0fa345c 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -265,9 +265,9 @@ static int spi_gpio_setup(struct spi_device *spi)
}
}
if (!status) {
- status = spi_bitbang_setup(spi);
/* in case it was initialized from static board data */
spi_gpio->cs_gpios[spi->chip_select] = cs;
+ status = spi_bitbang_setup(spi);
}
if (status) {
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index cf95587..ab031e7 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -7,6 +7,47 @@
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/spi/pxa2xx_spi.h>
+#include <linux/irq.h>
+#include <linux/platform_data/clanton.h>
+
+/* defined here to avoid including arch/x86/pci/intel_media_proc_gen3.c */
+#define CE3100_SOC_DEVICE_ID 0x2E50
+#define CE4100_SOC_DEVICE_ID 0x0708
+#define CE4200_SOC_DEVICE_ID 0x0709
+#define CE5300_SOC_DEVICE_ID 0x0C40
+#define CE2600_SOC_DEVICE_ID 0x0931
+
+#ifdef CONFIG_INTEL_CLN_SOC_FPGAEMU
+#define CE4200_NUM_SPI_MASTER 1
+#else
+#define CE4200_NUM_SPI_MASTER 2
+#endif
+
+#define CE4X00_SPI_MAX_SPEED 1843200
+
+#ifdef CONFIG_INTEL_CLN_SOC
+#define CE4200_NUM_CHIPSELECT 2
+#ifdef CONFIG_INTEL_CLN_SOC_FPGAEMU
+#define CE5X00_SPI_MAX_SPEED 3500000
+#else
+#define CE5X00_SPI_MAX_SPEED 50000000
+#endif
+#else
+#define CE4200_NUM_CHIPSELECT 4
+#define CE5X00_SPI_MAX_SPEED 5000000
+#endif
+
+#define SPI_CE_DEBUG
+
+static int interface;
+
+#ifdef CONFIG_INTEL_CLN_SOC
+static int enable_msi = 1;
+#else
+static int enable_msi;
+#endif
+module_param(enable_msi, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_msi, "Enable PCI MSI mode");
struct ce4100_info {
struct ssp_device ssp;
@@ -57,10 +98,11 @@ static int ce4100_spi_probe(struct pci_dev *dev,
int ret;
resource_size_t phys_beg;
resource_size_t phys_len;
- struct ce4100_info *spi_info;
+ struct ce4100_info *spi_info = NULL;
struct platform_device *pdev;
struct pxa2xx_spi_master spi_pdata;
struct ssp_device *ssp;
+ unsigned int id;
ret = pci_enable_device(dev);
if (ret)
@@ -77,42 +119,75 @@ static int ce4100_spi_probe(struct pci_dev *dev,
}
pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto err_release_mem_region;
+ }
spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
- if (!pdev || !spi_info ) {
+ if (!spi_info) {
ret = -ENOMEM;
- goto err_nomem;
+ goto err_platform_device_put;
}
memset(&spi_pdata, 0, sizeof(spi_pdata));
- spi_pdata.num_chipselect = dev->devfn;
+ spi_pdata.num_chipselect = CE4200_NUM_CHIPSELECT;
ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
if (ret)
- goto err_nomem;
+ goto err_free_spi_info;
+ pdev->id = interface;
pdev->dev.parent = &dev->dev;
+#ifdef CONFIG_OF
pdev->dev.of_node = dev->dev.of_node;
+#endif
ssp = &spi_info->ssp;
+ ssp->pcidev = dev;
ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = ioremap(phys_beg, phys_len);
if (!ssp->mmio_base) {
dev_err(&pdev->dev, "failed to ioremap() registers\n");
ret = -EIO;
- goto err_nomem;
+ goto err_ioremap;
+ }
+ pci_set_master(dev);
+ if (enable_msi == 1) {
+ ret = pci_enable_msi(dev);
+ if (ret) {
+ dev_err(&dev->dev, "failed to allocate MSI entry\n");
+ goto err_dev_add;
+ }
}
+
ssp->irq = dev->irq;
ssp->port_id = pdev->id;
- ssp->type = PXA25x_SSP;
+#ifdef CONFIG_INTEL_CLN_SOC
+ id = CE5300_SOC_DEVICE_ID;
+#else
+ intelce_get_soc_info(&id, NULL);
+#endif
+ switch (id) {
+ case CE5300_SOC_DEVICE_ID:
+ ssp->type = CE5X00_SSP;
+ break;
+ case CE4200_SOC_DEVICE_ID:
+ default:
+ ssp->type = CE4100_SSP;
+ break;
+ }
mutex_lock(&ssp_lock);
list_add(&ssp->node, &ssp_list);
mutex_unlock(&ssp_lock);
pci_set_drvdata(dev, spi_info);
+ spi_info->spi_pdev = pdev;
ret = platform_device_add(pdev);
if (ret)
goto err_dev_add;
+ interface++;
+
return ret;
err_dev_add:
@@ -121,11 +196,16 @@ err_dev_add:
list_del(&ssp->node);
mutex_unlock(&ssp_lock);
iounmap(ssp->mmio_base);
+err_ioremap:
-err_nomem:
- release_mem_region(phys_beg, phys_len);
- platform_device_put(pdev);
+err_free_spi_info:
kfree(spi_info);
+
+err_platform_device_put:
+ platform_device_put(pdev);
+
+err_release_mem_region:
+ release_mem_region(phys_beg, phys_len);
return ret;
}
@@ -146,21 +226,50 @@ static void ce4100_spi_remove(struct pci_dev *dev)
list_del(&ssp->node);
mutex_unlock(&ssp_lock);
+ if (enable_msi == 1) {
+ if (pci_dev_msi_enabled(dev))
+ pci_disable_msi(dev);
+ }
+
pci_set_drvdata(dev, NULL);
pci_disable_device(dev);
kfree(spi_info);
}
+
+#ifdef CONFIG_PM
+static int ce4XXX_spi_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ return 0;
+}
+
+static int ce4XXX_spi_resume(struct pci_dev *dev)
+{
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ return 0;
+}
+#endif
+
static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0935) },
{ },
};
+
MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
static struct pci_driver ce4100_spi_driver = {
.name = "ce4100_spi",
.id_table = ce4100_spi_devices,
.probe = ce4100_spi_probe,
+#ifdef CONFIG_PM
+ .suspend = ce4XXX_spi_suspend,
+ .resume = ce4XXX_spi_resume,
+#endif
.remove = ce4100_spi_remove,
};
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 5c8c4f5..9ba6cee 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -26,14 +26,18 @@
#include <linux/spi/pxa2xx_spi.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#ifdef CONFIG_INTEL_CLN_SOC
+#include <asm/cln.h>
+#endif
-#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/delay.h>
MODULE_AUTHOR("Stephen Street");
@@ -51,6 +55,9 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define MAX_DMA_LEN 8191
#define DMA_ALIGNMENT 8
+#define CE5X00_FIFO_DEPTH 32
+#define CE4X00_FIFO_DEPTH 4
+
/*
* for testing SSCR1 changes that require SSP restart, basically
* everything except the service and interrupt enables, the pxa270 developer
@@ -59,35 +66,144 @@ MODULE_ALIAS("platform:pxa2xx-spi");
* service and interrupt enables
*/
#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
- | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
- | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
- | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
- | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
- | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
-
-#define DEFINE_SSP_REG(reg, off) \
-static inline u32 read_##reg(void const __iomem *p) \
-{ return __raw_readl(p + (off)); } \
-\
-static inline void write_##reg(u32 v, void __iomem *p) \
-{ __raw_writel(v, p + (off)); }
-
-DEFINE_SSP_REG(SSCR0, 0x00)
-DEFINE_SSP_REG(SSCR1, 0x04)
-DEFINE_SSP_REG(SSSR, 0x08)
-DEFINE_SSP_REG(SSITR, 0x0c)
-DEFINE_SSP_REG(SSDR, 0x10)
-DEFINE_SSP_REG(SSTO, 0x28)
-DEFINE_SSP_REG(SSPSP, 0x2c)
-
-#define START_STATE ((void*)0)
-#define RUNNING_STATE ((void*)1)
-#define DONE_STATE ((void*)2)
-#define ERROR_STATE ((void*)-1)
+ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+ | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
+ | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
+ | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
+ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+
+#define CE5X00_SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
+ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+ | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
+ | SSCR1_IFS | CE5X00_SSCR1_STRF \
+ | CE5X00_SSCR1_EFWR \
+ | CE5X00_SSCR1_RFT | CE5X00_SSCR1_TFT \
+ | SSCR1_MWDS \
+ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+
+
+#define DEFINE_SSP_REG(reg, off) \
+ static inline u32 read_##reg(void const __iomem *p) \
+ { return __raw_readl(p + (off)); } \
+ \
+ static inline void write_##reg(u32 v, void __iomem *p) \
+ { __raw_writel(v, p + (off)); }
+
+DEFINE_SSP_REG(sscr0, 0x00)
+DEFINE_SSP_REG(sscr1, 0x04)
+DEFINE_SSP_REG(sssr, 0x08)
+DEFINE_SSP_REG(ssitr, 0x0c)
+DEFINE_SSP_REG(ssdr, 0x10)
+#ifdef CONFIG_INTEL_CLN_SOC
+DEFINE_SSP_REG(dds_rate, 0x28) /* SSTO unused for clanton */
+#endif
+DEFINE_SSP_REG(ssto, 0x28)
+DEFINE_SSP_REG(sspsp, 0x2c)
+
+#define START_STATE ((void *)0)
+#define RUNNING_STATE ((void *)1)
+#define DONE_STATE ((void *)2)
+#define ERROR_STATE ((void *)-1)
#define QUEUE_RUNNING 0
#define QUEUE_STOPPED 1
+#ifdef CONFIG_INTEL_CLN_SOC
+#define DDS_MAX 0x800000
+#define DDS_666666 0x666666
+#define DDS_400000 0x400000
+#define DDS_200000 0x200000
+#define DDS_100000 0x100000
+#define DDS_80000 0x80000
+#define DDS_40000 0x40000
+#define DDS_20000 0x20000
+#define DDS_10000 0x10000
+#define DDS_8000 0x8000
+
+#if defined(CONFIG_INTEL_CLN_SOC_FPGAEMU)
+/* these values are different on emulations where system clock is 14mhz */
+#define FSYS 14 /* mhz */
+#define BITRATE_50MHZ 3500000
+#define BITRATE_40MHZ 2800000
+#define BITRATE_25MHZ 1750000
+#define BITRATE_20MHZ 1400000
+#define BITRATE_16667KHZ 1167000
+#define BITRATE_13333KHZ 933000
+#define BITRATE_12500KHZ 875000
+#define BITRATE_10MHZ 700000
+#define BITRATE_8MHZ 560000
+#define BITRATE_6250KHZ 438000
+#define BITRATE_5MHZ 350000
+#define BITRATE_4MHZ 280000
+#define BITRATE_3125KHZ 219000
+#define BITRATE_2500KHZ 175000
+#define BITRATE_2MHZ 140000
+#define BITRATE_1563KHZ 109000
+#define BITRATE_1250KHZ 88000
+#define BITRATE_1MHZ 70000
+#define BITRATE_800KHZ 56000
+#define BITRATE_781KHZ 54688
+#define BITRATE_625KHZ 43750
+#define BITRATE_500KHZ 35000
+#define BITRATE_400KHZ 28000
+#define BITRATE_390KHZ 27344
+#define BITRATE_250KHZ 17500
+#define BITRATE_200KHZ 14000
+#define BITRATE_195KHZ 13672
+#define BITRATE_125KHZ 8750
+#define BITRATE_100KHZ 7000
+#define BITRATE_50KHZ 3500
+#define BITRATE_25KHZ 1750
+#define BITRATE_10KHZ 701
+#define BITRATE_5KHZ 353
+#define BITRATE_1KHZ 70
+#define BITRATE_MAX BITRATE_50MHZ
+#define BITRATE_MIN BITRATE_1KHZ
+
+#else
+
+#define BITRATE_50MHZ 50000000
+#define BITRATE_40MHZ 40000000
+#define BITRATE_25MHZ 25000000
+#define BITRATE_20MHZ 20000000
+#define BITRATE_16667KHZ 16667000
+#define BITRATE_13333KHZ 13333000
+#define BITRATE_12500KHZ 12500000
+#define BITRATE_10MHZ 10000000
+#define BITRATE_8MHZ 8000000
+#define BITRATE_6250KHZ 6250000
+#define BITRATE_5MHZ 5000000
+#define BITRATE_4MHZ 4000000
+#define BITRATE_3125KHZ 3125000
+#define BITRATE_2500KHZ 2500000
+#define BITRATE_2MHZ 2000000
+#define BITRATE_1563KHZ 1563000
+#define BITRATE_1250KHZ 1250000
+#define BITRATE_1MHZ 1000000
+#define BITRATE_800KHZ 800000
+#define BITRATE_781KHZ 781250
+#define BITRATE_625KHZ 625000
+#define BITRATE_500KHZ 500000
+#define BITRATE_400KHZ 400000
+#define BITRATE_390KHZ 390625
+#define BITRATE_250KHZ 250000
+#define BITRATE_200KHZ 200000
+#define BITRATE_195KHZ 195313
+#define BITRATE_125KHZ 125000
+#define BITRATE_100KHZ 100000
+#define BITRATE_50KHZ 50000
+#define BITRATE_25KHZ 25000
+#define BITRATE_10KHZ 10016
+#define BITRATE_5KHZ 5040
+#define BITRATE_1KHZ 1000
+#define BITRATE_MIN BITRATE_1KHZ
+#define BITRATE_MAX BITRATE_50MHZ
+#define FSYS 200 /* mhz */
+
+#endif /* #if defined(CONFIG_INTEL_CLN_SOC_FPGAEMU) */
+
+#endif /* CONFIG_INTEL_CLN_SOC */
+
struct driver_data {
/* Driver model hookup */
struct platform_device *pdev;
@@ -117,20 +233,12 @@ struct driver_data {
u32 clear_sr;
u32 mask_sr;
- /* Driver message queue */
- struct workqueue_struct *workqueue;
- struct work_struct pump_messages;
- spinlock_t lock;
- struct list_head queue;
- int busy;
- int run;
-
- /* Message Transfer pump */
+ /* Message per-transfer pump */
struct tasklet_struct pump_transfers;
/* Current message transfer state info */
- struct spi_message* cur_msg;
- struct spi_transfer* cur_transfer;
+ struct spi_message *cur_msg;
+ struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
size_t len;
void *tx;
@@ -153,6 +261,9 @@ struct driver_data {
struct chip_data {
u32 cr0;
u32 cr1;
+#ifdef CONFIG_INTEL_CLN_SOC
+ u32 dds_rate;
+#endif
u32 psp;
u32 timeout;
u8 n_bytes;
@@ -173,14 +284,14 @@ struct chip_data {
void (*cs_control)(u32 command);
};
-static void pump_messages(struct work_struct *work);
-
static void cs_assert(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
- if (drv_data->ssp_type == CE4100_SSP) {
- write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
+ if (drv_data->ssp_type == CE4100_SSP ||
+ (drv_data->ssp_type == CE5X00_SSP &&
+ (!gpio_is_valid(chip->gpio_cs)))) {
+ write_sssr(drv_data->cur_chip->frm, drv_data->ioaddr);
return;
}
@@ -197,9 +308,11 @@ static void cs_deassert(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
- if (drv_data->ssp_type == CE4100_SSP)
+ if (drv_data->ssp_type == CE4100_SSP ||
+ (drv_data->ssp_type == CE5X00_SSP
+ && (!gpio_is_valid(chip->gpio_cs)))) {
return;
-
+ }
if (chip->cs_control) {
chip->cs_control(PXA2XX_CS_DEASSERT);
return;
@@ -209,14 +322,15 @@ static void cs_deassert(struct driver_data *drv_data)
gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
}
-static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
+static void write_sssr_cs(struct driver_data *drv_data, u32 val)
{
void __iomem *reg = drv_data->ioaddr;
- if (drv_data->ssp_type == CE4100_SSP)
- val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
+ if (drv_data->ssp_type == CE4100_SSP
+ || drv_data->ssp_type == CE5X00_SSP)
+ val |= read_sssr(reg) & SSSR_ALT_FRM_MASK;
- write_SSSR(val, reg);
+ write_sssr(val, reg);
}
static int pxa25x_ssp_comp(struct driver_data *drv_data)
@@ -225,6 +339,10 @@ static int pxa25x_ssp_comp(struct driver_data *drv_data)
return 1;
if (drv_data->ssp_type == CE4100_SSP)
return 1;
+#ifdef CONFIG_GEN3_SPI
+ if (drv_data->ssp_type == CE5X00_SSP)
+ return 2;
+#endif
return 0;
}
@@ -235,25 +353,46 @@ static int flush(struct driver_data *drv_data)
void __iomem *reg = drv_data->ioaddr;
do {
- while (read_SSSR(reg) & SSSR_RNE) {
- read_SSDR(reg);
- }
- } while ((read_SSSR(reg) & SSSR_BSY) && --limit);
- write_SSSR_CS(drv_data, SSSR_ROR);
+ while (read_sssr(reg) & SSSR_RNE)
+ read_ssdr(reg);
+ } while ((read_sssr(reg) & SSSR_BSY) && --limit);
+ write_sssr_cs(drv_data, SSSR_ROR);
return limit;
}
+#ifdef CONFIG_GEN3_SPI
+static void wait_till_not_busy(struct driver_data *drv_data)
+{
+ /*
+ * Most cases, the BSY bit will be cleared in very short time.
+ * But if the controller is set to the slowest speed, the BSY
+ * bit waitting time will increase a lot.
+ * Here, we set the wait time to 100ms is to deal with such corner case,
+ * but in real world, there is almost no one will use the slowest
+ * speed to transfer data, which means there is no need to add more
+ * complex code to to deal with the slowest speed case.
+ */
+ unsigned long end = jiffies + 1 + usecs_to_jiffies(100000);
+ void __iomem *reg = drv_data->ioaddr;
+ while (time_before(jiffies, end)) {
+ if (!(read_sssr(reg) & SSSR_BSY))
+ return;
+ }
+ pr_err("SPI MASTER keeps busy for 100ms after a read/write!\n");
+}
+#endif
+
static int null_writer(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
u8 n_bytes = drv_data->n_bytes;
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
+ if ((!(read_sssr(reg) & SSSR_TNF))
+ || (drv_data->tx == drv_data->tx_end))
return 0;
- write_SSDR(0, reg);
+ write_ssdr(0, reg);
drv_data->tx += n_bytes;
return 1;
@@ -264,9 +403,9 @@ static int null_reader(struct driver_data *drv_data)
void __iomem *reg = drv_data->ioaddr;
u8 n_bytes = drv_data->n_bytes;
- while ((read_SSSR(reg) & SSSR_RNE)
+ while ((read_sssr(reg) & SSSR_RNE)
&& (drv_data->rx < drv_data->rx_end)) {
- read_SSDR(reg);
+ read_ssdr(reg);
drv_data->rx += n_bytes;
}
@@ -277,11 +416,11 @@ static int u8_writer(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
+ if ((!(read_sssr(reg) & SSSR_TNF))
+ || (drv_data->tx == drv_data->tx_end))
return 0;
- write_SSDR(*(u8 *)(drv_data->tx), reg);
+ write_ssdr(*(u8 *)(drv_data->tx), reg);
++drv_data->tx;
return 1;
@@ -291,9 +430,9 @@ static int u8_reader(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- *(u8 *)(drv_data->rx) = read_SSDR(reg);
+ while ((read_sssr(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ *(u8 *)(drv_data->rx) = read_ssdr(reg);
++drv_data->rx;
}
@@ -304,11 +443,11 @@ static int u16_writer(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
+ if ((!(read_sssr(reg) & SSSR_TNF))
+ || (drv_data->tx == drv_data->tx_end))
return 0;
- write_SSDR(*(u16 *)(drv_data->tx), reg);
+ write_ssdr(*(u16 *)(drv_data->tx), reg);
drv_data->tx += 2;
return 1;
@@ -318,9 +457,9 @@ static int u16_reader(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- *(u16 *)(drv_data->rx) = read_SSDR(reg);
+ while ((read_sssr(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ *(u16 *)(drv_data->rx) = read_ssdr(reg);
drv_data->rx += 2;
}
@@ -331,11 +470,11 @@ static int u32_writer(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
+ if ((!(read_sssr(reg) & SSSR_TNF))
+ || (drv_data->tx == drv_data->tx_end))
return 0;
- write_SSDR(*(u32 *)(drv_data->tx), reg);
+ write_ssdr(*(u32 *)(drv_data->tx), reg);
drv_data->tx += 4;
return 1;
@@ -345,9 +484,9 @@ static int u32_reader(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- *(u32 *)(drv_data->rx) = read_SSDR(reg);
+ while ((read_sssr(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ *(u32 *)(drv_data->rx) = read_ssdr(reg);
drv_data->rx += 4;
}
@@ -443,20 +582,11 @@ static void unmap_dma_buffers(struct driver_data *drv_data)
/* caller already set message->status; dma and pio irqs are blocked */
static void giveback(struct driver_data *drv_data)
{
- struct spi_transfer* last_transfer;
- unsigned long flags;
- struct spi_message *msg;
+ struct spi_transfer *last_transfer;
- spin_lock_irqsave(&drv_data->lock, flags);
- msg = drv_data->cur_msg;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- last_transfer = list_entry(msg->transfers.prev,
- struct spi_transfer,
- transfer_list);
+ last_transfer = list_entry(drv_data->cur_msg->transfers.prev,
+ struct spi_transfer,
+ transfer_list);
/* Delay if requested before any change in chip select */
if (last_transfer->delay_usecs)
@@ -475,41 +605,33 @@ static void giveback(struct driver_data *drv_data)
* time with the following tests unless this was hinted.
*
* We cannot postpone this until pump_messages, because
- * after calling msg->complete (below) the driver that
- * sent the current message could be unloaded, which
- * could invalidate the cs_control() callback...
+ * after calling spi_finalize_current_message (below) the
+ * driver that sent the current message could be unloaded,
+ * which could invalidate the cs_control() callback...
*/
-
/* get a pointer to the next message, if any */
- spin_lock_irqsave(&drv_data->lock, flags);
- if (list_empty(&drv_data->queue))
- next_msg = NULL;
- else
- next_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
- spin_unlock_irqrestore(&drv_data->lock, flags);
+ next_msg = spi_get_next_queued_message(drv_data->master);
/* see if the next and current messages point
* to the same chip
*/
- if (next_msg && next_msg->spi != msg->spi)
+ if (next_msg && next_msg->spi != drv_data->cur_msg->spi)
next_msg = NULL;
- if (!next_msg || msg->state == ERROR_STATE)
+ if (!next_msg || drv_data->cur_msg->state == ERROR_STATE)
cs_deassert(drv_data);
}
- msg->state = NULL;
- if (msg->complete)
- msg->complete(msg->context);
-
+ drv_data->cur_msg = NULL;
+ drv_data->cur_transfer = NULL;
drv_data->cur_chip = NULL;
+ spi_finalize_current_message(drv_data->master);
}
static int wait_ssp_rx_stall(void const __iomem *ioaddr)
{
unsigned long limit = loops_per_jiffy << 1;
- while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
+ while ((read_sssr(ioaddr) & SSSR_BSY) && --limit)
cpu_relax();
return limit;
@@ -532,12 +654,12 @@ static void dma_error_stop(struct driver_data *drv_data, const char *msg)
/* Stop and reset */
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ write_sssr_cs(drv_data, drv_data->clear_sr);
+ write_sscr1(read_sscr1(reg) & ~drv_data->dma_cr1, reg);
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
+ write_ssto(0, reg);
flush(drv_data);
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ write_sscr0(read_sscr0(reg) & ~SSCR0_SSE, reg);
unmap_dma_buffers(drv_data);
@@ -553,8 +675,8 @@ static void dma_transfer_complete(struct driver_data *drv_data)
struct spi_message *msg = drv_data->cur_msg;
/* Clear and disable interrupts on SSP and DMA channels*/
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
- write_SSSR_CS(drv_data, drv_data->clear_sr);
+ write_sscr1(read_sscr1(reg) & ~drv_data->dma_cr1, reg);
+ write_sssr_cs(drv_data, drv_data->clear_sr);
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
@@ -630,7 +752,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
u32 irq_status;
void __iomem *reg = drv_data->ioaddr;
- irq_status = read_SSSR(reg) & drv_data->mask_sr;
+ irq_status = read_sssr(reg) & drv_data->mask_sr;
if (irq_status & SSSR_ROR) {
dma_error_stop(drv_data, "dma_transfer: fifo overrun");
return IRQ_HANDLED;
@@ -639,7 +761,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
/* Check for false positive timeout */
if ((irq_status & SSSR_TINT)
&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
- write_SSSR(SSSR_TINT, reg);
+ write_sssr(SSSR_TINT, reg);
return IRQ_HANDLED;
}
@@ -648,7 +770,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
/* Clear and disable timeout interrupt, do the rest in
* dma_transfer_complete */
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
+ write_ssto(0, reg);
/* finish this transfer, start the next */
dma_transfer_complete(drv_data);
@@ -666,23 +788,26 @@ static void reset_sccr1(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;
u32 sccr1_reg;
- sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
- sccr1_reg &= ~SSCR1_RFT;
+ sccr1_reg = read_sscr1(reg) & ~drv_data->int_cr1;
+ if (drv_data->ssp_type == CE5X00_SSP)
+ sccr1_reg &= ~CE5X00_SSCR1_RFT;
+ else
+ sccr1_reg &= ~SSCR1_RFT;
sccr1_reg |= chip->threshold;
- write_SSCR1(sccr1_reg, reg);
+ write_sscr1(sccr1_reg, reg);
}
-static void int_error_stop(struct driver_data *drv_data, const char* msg)
+static void int_error_stop(struct driver_data *drv_data, const char *msg)
{
void __iomem *reg = drv_data->ioaddr;
/* Stop and reset SSP */
- write_SSSR_CS(drv_data, drv_data->clear_sr);
+ write_sssr_cs(drv_data, drv_data->clear_sr);
reset_sccr1(drv_data);
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
+ write_ssto(0, reg);
flush(drv_data);
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ write_sscr0(read_sscr0(reg) & ~SSCR0_SSE, reg);
dev_err(&drv_data->pdev->dev, "%s\n", msg);
@@ -695,10 +820,10 @@ static void int_transfer_complete(struct driver_data *drv_data)
void __iomem *reg = drv_data->ioaddr;
/* Stop SSP */
- write_SSSR_CS(drv_data, drv_data->clear_sr);
+ write_sssr_cs(drv_data, drv_data->clear_sr);
reset_sccr1(drv_data);
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
+ write_ssto(0, reg);
/* Update total byte transferred return count actual bytes read */
drv_data->cur_msg->actual_length += drv_data->len -
@@ -715,14 +840,16 @@ static void int_transfer_complete(struct driver_data *drv_data)
tasklet_schedule(&drv_data->pump_transfers);
}
+#ifndef CONFIG_GEN3_SPI
+
static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
- u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
+ u32 irq_mask = (read_sscr1(reg) & SSCR1_TIE) ?
drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
- u32 irq_status = read_SSSR(reg) & irq_mask;
+ u32 irq_status = read_sssr(reg) & irq_mask;
if (irq_status & SSSR_ROR) {
int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
@@ -730,7 +857,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
}
if (irq_status & SSSR_TINT) {
- write_SSSR(SSSR_TINT, reg);
+ write_sssr_cs(drv_data, SSSR_TINT);
if (drv_data->read(drv_data)) {
int_transfer_complete(drv_data);
return IRQ_HANDLED;
@@ -751,10 +878,12 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
}
if (drv_data->tx == drv_data->tx_end) {
- u32 bytes_left;
+#ifndef CONFIG_GEN3_SPI
+ u32 bytes_left = 0;
+#endif
u32 sccr1_reg;
- sccr1_reg = read_SSCR1(reg);
+ sccr1_reg = read_sscr1(reg);
sccr1_reg &= ~SSCR1_TIE;
/*
@@ -762,13 +891,13 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
* remaining RX bytes.
*/
if (pxa25x_ssp_comp(drv_data)) {
-
+#ifndef CONFIG_GEN3_SPI
sccr1_reg &= ~SSCR1_RFT;
bytes_left = drv_data->rx_end - drv_data->rx;
switch (drv_data->n_bytes) {
case 4:
- bytes_left >>= 1;
+ bytes_left >>= 2;
case 2:
bytes_left >>= 1;
}
@@ -777,23 +906,198 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
bytes_left = RX_THRESH_DFLT;
sccr1_reg |= SSCR1_RxTresh(bytes_left);
+#endif
+ }
+ write_sscr1(sccr1_reg, reg);
+#ifdef CONFIG_GEN3_SPI
+ if (!wait_ssp_rx_stall(reg)) {
+ int_error_stop(drv_data,
+ "interrupt_transfer: rx stall failed");
+ return IRQ_HANDLED;
+ }
+
+ if (!drv_data->read(drv_data)) {
+ int_error_stop(drv_data,
+ "interrupt_transfer: "
+ "trailing byte read failed");
+ return IRQ_HANDLED;
+ }
+
+ int_transfer_complete(drv_data);
+#endif
+
+ }
+
+ /* We did something */
+ return IRQ_HANDLED;
+}
+#else
+#ifdef WANT_TO_USE_THIS
+static int is_txfifo_empty(struct driver_data *drv_data, u32 tfl_mask)
+{
+ void __iomem *reg = drv_data->ioaddr;
+ u32 sssr = read_sssr(reg);
+ u32 tx_fifo_entry = 0;
+ tx_fifo_entry = (sssr & tfl_mask)>>8;
+ if ((sssr & SSSR_TNF) && (!tx_fifo_entry))
+ return 1;
+ return 0;
+}
+#endif
+
+static void pxa2xx_update_tx_threshold(struct driver_data *drv_data,
+ u32 threshold)
+{
+ void __iomem *reg = drv_data->ioaddr;
+ u32 sscr1_reg = 0;
+ sscr1_reg = read_sscr1(reg);
+ sscr1_reg |= SSCR1_TIE;
+ if (drv_data->ssp_type == CE5X00_SSP) {
+ sscr1_reg &= ~CE5X00_SSCR1_TFT;
+ sscr1_reg |= CE5X00_SSCR1_TxTresh(threshold);
+ } else {
+ sscr1_reg &= ~SSCR1_TFT;
+ sscr1_reg |= SSCR1_TxTresh(threshold);
+ }
+
+ write_sscr1(sscr1_reg, reg);
+}
+
+static void pxa2xx_mask_intr(void __iomem *reg, u32 intr)
+{
+ u32 mask;
+ mask = read_sscr1(reg) & ~intr;
+ write_sscr1(mask, reg);
+}
+
+static void pxa2xx_unmask_intr(void __iomem *reg, u32 intr)
+{
+ u32 mask;
+ mask = read_sscr1(reg) | intr;
+ write_sscr1(mask, reg);
+}
+
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+ void __iomem *reg = drv_data->ioaddr;
+
+ u32 tx_count;
+ u32 irq_mask = (read_sscr1(reg) & SSCR1_TIE) ?
+ drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
+
+ int left;
+
+ u32 tmp_sssr = read_sssr(reg);
+ u32 irq_status = tmp_sssr & irq_mask;
+ /*
+ * Transmit FIFO Level Depth/MASK/Default value
+ */
+ u32 fifo_depth, sssr_tfl_mask, sscr1_tft_mask, tfl_default;
+
+ /*
+ * Check whether the irq is valid spi interrupt
+ */
+ if (!(tmp_sssr & (SSSR_TFS | SSSR_RFS | SSSR_ROR)))
+ return IRQ_NONE;
+
+ switch (drv_data->ssp_type) {
+ case CE4100_SSP:
+ fifo_depth = CE4X00_FIFO_DEPTH;
+ sssr_tfl_mask = SSSR_TFL_MASK;
+ sscr1_tft_mask = SSCR1_TFT;
+ tfl_default = TX_THRESH_DFLT;
+ break;
+ case CE5X00_SSP:
+ fifo_depth = CE5X00_FIFO_DEPTH;
+ sssr_tfl_mask = CE5X00_SSSR_TFL_MASK;
+ sscr1_tft_mask = CE5X00_SSCR1_TFT;
+ tfl_default = TX_THRESH_CE5X00_DFLT;
+ break;
+ default:
+ int_error_stop(drv_data, "Unsupported spi contoller type");
+ return IRQ_HANDLED;
+ }
+
+
+ if (irq_status & SSSR_ROR) {
+ int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
+ return IRQ_HANDLED;
+ }
+
+
+ if (irq_status & SSSR_TINT) {
+ write_sssr_cs(drv_data, SSSR_TINT);
+ if (drv_data->read(drv_data)) {
+ int_transfer_complete(drv_data);
+ return IRQ_HANDLED;
}
- write_SSCR1(sccr1_reg, reg);
}
+
+ if (irq_status & SSSR_TFS) {
+
+ /*
+ * Mask the Transmit interrupt
+ */
+ pxa2xx_mask_intr(reg, SSCR1_TIE);
+
+ left = (drv_data->tx_end - drv_data->tx) / drv_data->n_bytes;
+
+ tmp_sssr = read_sssr(reg);
+ tmp_sssr = (tmp_sssr & sssr_tfl_mask)>>8;
+ /*
+ * Choose the correct tx_count to fill the Tx fifo and
+ * avoid the Rx Fifo overrun
+ */
+ tx_count = (fifo_depth - 1) - tmp_sssr;
+
+ if (left <= tx_count) {
+ if (left > 0) {
+ drv_data->read(drv_data);
+ pxa2xx_update_tx_threshold(drv_data, 1);
+ while ((left) > 0) {
+ left--;
+ drv_data->write(drv_data);
+ }
+ pxa2xx_unmask_intr(reg, SSCR1_TIE);
+ return IRQ_HANDLED;
+ } else {
+ /*
+ * Tx transfer is done now,
+ * Read data when controller is not busy.
+ */
+ wait_till_not_busy(drv_data);
+ drv_data->read(drv_data);
+ pxa2xx_unmask_intr(reg, SSCR1_TIE);
+ int_transfer_complete(drv_data);
+ return IRQ_HANDLED;
+ }
+ } else {
+ left = (left > tx_count) ? tx_count : left;
+ drv_data->read(drv_data);
+ while ((left) > 0) {
+ left--;
+ drv_data->write(drv_data);
+ }
+ pxa2xx_unmask_intr(reg, SSCR1_TIE);
+ return IRQ_HANDLED;
+ }
+ }
/* We did something */
return IRQ_HANDLED;
}
+#endif
static irqreturn_t ssp_int(int irq, void *dev_id)
{
struct driver_data *drv_data = dev_id;
void __iomem *reg = drv_data->ioaddr;
- u32 sccr1_reg = read_SSCR1(reg);
+ u32 sccr1_reg = read_sscr1(reg);
u32 mask = drv_data->mask_sr;
u32 status;
+ irqreturn_t ret;
- status = read_SSSR(reg);
+ status = read_sssr(reg);
/* Ignore possible writes if we don't need to write */
if (!(sccr1_reg & SSCR1_TIE))
@@ -802,22 +1106,27 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
if (!(status & mask))
return IRQ_NONE;
+#ifdef CONFIG_INTEL_CLN_SOC
+ mask_pvm(drv_data->ssp->pcidev);
+#endif
if (!drv_data->cur_msg) {
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+ write_sscr0(read_sscr0(reg) & ~SSCR0_SSE, reg);
+ write_sscr1(read_sscr1(reg) & ~drv_data->int_cr1, reg);
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
- write_SSSR_CS(drv_data, drv_data->clear_sr);
-
- dev_err(&drv_data->pdev->dev, "bad message state "
- "in interrupt handler\n");
+ write_ssto(0, reg);
+ write_sssr_cs(drv_data, drv_data->clear_sr);
+ dev_err(&drv_data->pdev->dev,
+ "bad message state in interrupt handler\n");
/* Never fail */
return IRQ_HANDLED;
}
-
- return drv_data->transfer_handler(drv_data);
+ ret = drv_data->transfer_handler(drv_data);
+#ifdef CONFIG_INTEL_CLN_SOC
+ unmask_pvm(drv_data->ssp->pcidev);
+#endif
+ return ret;
}
static int set_dma_burst_and_threshold(struct chip_data *chip,
@@ -916,16 +1225,192 @@ static int set_dma_burst_and_threshold(struct chip_data *chip,
return retval;
}
+#ifdef CONFIG_GEN3_SPI
+/* this returns the value of DDS_FREQ not Input_Clock
+ DDS_FREQ = Input_Clock ( DDS_CLK_RATEdec / 2^24) */
+static unsigned long spi_clk_get_rate(int ssp_type)
+{
+ switch (ssp_type) {
+ case CE5X00_SSP:
+ /* CE5X00 clk is 10MHZ */
+ return 10000000;
+ case CE4100_SSP:
+ /* CE4X00 clk is 3.684MHZ */
+ default:
+ return 3686400;
+ }
+ return 3686400;
+}
+#endif
+
+#ifdef CONFIG_INTEL_CLN_SOC
+/* see Clanton SPI data sheet for implementation rationale */
+u32 cln_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
+{
+ if (rate <= BITRATE_MAX && rate >= BITRATE_MIN) {
+ if (rate >= BITRATE_50MHZ) {
+ *dds = DDS_MAX;
+ *clk_div = 0;
+ return BITRATE_50MHZ;
+ } else if (rate >= BITRATE_40MHZ) {
+ *dds = DDS_666666;
+ *clk_div = 0;
+ return BITRATE_40MHZ;
+ } else if (rate >= BITRATE_25MHZ) {
+ *dds = DDS_400000;
+ *clk_div = 0;
+ return BITRATE_25MHZ;
+ } else if (rate >= BITRATE_20MHZ) {
+ *dds = DDS_666666;
+ *clk_div = 1;
+ return BITRATE_20MHZ;
+ } else if (rate >= BITRATE_16667KHZ) {
+ *dds = DDS_MAX;
+ *clk_div = 2;
+ return BITRATE_16667KHZ;
+ } else if (rate >= BITRATE_13333KHZ) {
+ *dds = DDS_666666;
+ *clk_div = 2;
+ return BITRATE_13333KHZ;
+ } else if (rate >= BITRATE_12500KHZ) {
+ *dds = DDS_200000;
+ *clk_div = 0;
+ return BITRATE_12500KHZ;
+ } else if (rate >= BITRATE_10MHZ) {
+ *dds = DDS_MAX;
+ *clk_div = 4;
+ return BITRATE_10MHZ;
+ } else if (rate >= BITRATE_8MHZ) {
+ *dds = DDS_666666;
+ *clk_div = 4;
+ return BITRATE_8MHZ;
+ } else if (rate >= BITRATE_6250KHZ) {
+ *dds = DDS_400000;
+ *clk_div = 3;
+ return BITRATE_6250KHZ;
+ } else if (rate >= BITRATE_5MHZ) {
+ *dds = DDS_400000;
+ *clk_div = 4;
+ return BITRATE_5MHZ;
+ } else if (rate >= BITRATE_4MHZ) {
+ *dds = DDS_666666;
+ *clk_div = 9;
+ return BITRATE_4MHZ;
+ } else if (rate >= BITRATE_3125KHZ) {
+ *dds = DDS_80000;
+ *clk_div = 0;
+ return BITRATE_3125KHZ;
+ } else if (rate >= BITRATE_2500KHZ) {
+ *dds = DDS_400000;
+ *clk_div = 9;
+ return BITRATE_2500KHZ;
+ } else if (rate >= BITRATE_2MHZ) {
+ *dds = DDS_666666;
+ *clk_div = 19;
+ return BITRATE_2MHZ;
+ } else if (rate >= BITRATE_1563KHZ) {
+ *dds = DDS_40000;
+ *clk_div = 0;
+ return BITRATE_1563KHZ;
+ } else if (rate >= BITRATE_1250KHZ) {
+ *dds = DDS_200000;
+ *clk_div = 9;
+ return BITRATE_1250KHZ;
+ } else if (rate >= BITRATE_1MHZ) {
+ *dds = DDS_400000;
+ *clk_div = 24;
+ return BITRATE_1MHZ;
+ } else if (rate >= BITRATE_800KHZ) {
+ *dds = DDS_666666;
+ *clk_div = 49;
+ return BITRATE_800KHZ;
+ } else if (rate >= BITRATE_781KHZ) {
+ *dds = DDS_20000;
+ *clk_div = 0;
+ return BITRATE_781KHZ;
+ } else if (rate >= BITRATE_625KHZ) {
+ *dds = DDS_200000;
+ *clk_div = 19;
+ return BITRATE_625KHZ;
+ } else if (rate >= BITRATE_500KHZ) {
+ *dds = DDS_400000;
+ *clk_div = 49;
+ return BITRATE_500KHZ;
+ } else if (rate >= BITRATE_400KHZ) {
+ *dds = DDS_666666;
+ *clk_div = 99;
+ return BITRATE_400KHZ;
+ } else if (rate >= BITRATE_390KHZ) {
+ *dds = DDS_10000;
+ *clk_div = 0;
+ return BITRATE_390KHZ;
+ } else if (rate >= BITRATE_250KHZ) {
+ *dds = DDS_400000;
+ *clk_div = 99;
+ return BITRATE_250KHZ;
+ } else if (rate >= BITRATE_200KHZ) {
+ *dds = DDS_666666;
+ *clk_div = 199;
+ return BITRATE_200KHZ;
+ } else if (rate >= BITRATE_195KHZ) {
+ *dds = DDS_8000;
+ *clk_div = 0;
+ return BITRATE_195KHZ;
+ } else if (rate >= BITRATE_125KHZ) {
+ *dds = DDS_100000;
+ *clk_div = 49;
+ return BITRATE_125KHZ;
+ } else if (rate >= BITRATE_100KHZ) {
+ *dds = DDS_200000;
+ *clk_div = 124;
+ return BITRATE_100KHZ;
+ } else if (rate >= BITRATE_50KHZ) {
+ *dds = DDS_100000;
+ *clk_div = 124;
+ return BITRATE_50KHZ;
+ } else if (rate >= BITRATE_25KHZ) {
+ *dds = DDS_80000;
+ *clk_div = 124;
+ return BITRATE_25KHZ;
+ } else if (rate >= BITRATE_10KHZ) {
+ *dds = DDS_20000;
+ *clk_div = 77;
+ return BITRATE_10KHZ;
+ } else if (rate >= BITRATE_5KHZ) {
+ *dds = DDS_20000;
+ *clk_div = 154;
+ return BITRATE_5KHZ;
+ } else if (rate >= BITRATE_1KHZ) {
+ *dds = DDS_8000;
+ *clk_div = 194;
+ return BITRATE_1KHZ;
+ }
+ } else {
+ *dds = DDS_8000;
+ *clk_div = 194;
+ return BITRATE_MIN;
+ }
+ return 0;
+}
+#else
+/* this returns the value that SCR needs to be set to
+ Bit rate = DDS_FREQ / (2 x (SCR + 1)) */
static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
{
+#ifdef CONFIG_GEN3_SPI
+ unsigned long ssp_clk = spi_clk_get_rate(ssp->type);
+#else
unsigned long ssp_clk = clk_get_rate(ssp->clk);
+#endif
- if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
+ if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP
+ || ssp->type == CE5X00_SSP)
return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
else
return ((ssp_clk / rate - 1) & 0xfff) << 8;
}
+#endif /* CONFIG_INTEL_CLN_SOC */
static void pump_transfers(unsigned long data)
{
@@ -934,7 +1419,11 @@ static void pump_transfers(unsigned long data)
struct spi_transfer *transfer = NULL;
struct spi_transfer *previous = NULL;
struct chip_data *chip = NULL;
+#ifndef CONFIG_INTEL_CLN_SOC
struct ssp_device *ssp = drv_data->ssp;
+#else
+ u32 actual_speed = 0;
+#endif
void __iomem *reg = drv_data->ioaddr;
u32 clk_div = 0;
u8 bits = 0;
@@ -947,8 +1436,11 @@ static void pump_transfers(unsigned long data)
/* Get current state information */
message = drv_data->cur_msg;
transfer = drv_data->cur_transfer;
+
chip = drv_data->cur_chip;
+ if (transfer->bits_per_word)
+ chip->n_bytes = (transfer->bits_per_word + 7)/8;
/* Handle for abort */
if (message->state == ERROR_STATE) {
message->status = -EIO;
@@ -992,11 +1484,11 @@ static void pump_transfers(unsigned long data)
}
/* warn ... we force this to PIO mode */
- if (printk_ratelimit())
- dev_warn(&message->spi->dev, "pump_transfers: "
- "DMA disabled for transfer length %ld "
- "greater than %d\n",
- (long)drv_data->len, MAX_DMA_LEN);
+ dev_warn_ratelimited(&message->spi->dev,
+ "pump_transfers: "
+ "DMA disabled for transfer length %ld "
+ "greater than %d\n",
+ (long)drv_data->len, MAX_DMA_LEN);
}
/* Setup the transfer state based on the type of transfer */
@@ -1009,19 +1501,21 @@ static void pump_transfers(unsigned long data)
drv_data->n_bytes = chip->n_bytes;
drv_data->dma_width = chip->dma_width;
drv_data->tx = (void *)transfer->tx_buf;
- drv_data->tx_end = drv_data->tx + transfer->len;
+ drv_data->tx_end = drv_data->tx
+ + (transfer->len/drv_data->n_bytes)*drv_data->n_bytes;
drv_data->rx = transfer->rx_buf;
- drv_data->rx_end = drv_data->rx + transfer->len;
+ drv_data->rx_end = drv_data->rx
+ + (transfer->len/drv_data->n_bytes)*drv_data->n_bytes;
drv_data->rx_dma = transfer->rx_dma;
drv_data->tx_dma = transfer->tx_dma;
- drv_data->len = transfer->len & DCMD_LENGTH;
+ drv_data->len = (transfer->len/drv_data->n_bytes)
+ * drv_data->n_bytes & DCMD_LENGTH;
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
/* Change speed and bit per word on a per transfer */
cr0 = chip->cr0;
if (transfer->speed_hz || transfer->bits_per_word) {
-
bits = chip->bits_per_word;
speed = chip->speed_hz;
@@ -1031,8 +1525,13 @@ static void pump_transfers(unsigned long data)
if (transfer->bits_per_word)
bits = transfer->bits_per_word;
+#ifdef CONFIG_INTEL_CLN_SOC
+ actual_speed = cln_set_clk_regvals
+ (speed, &chip->dds_rate, &clk_div);
+ clk_div = (clk_div << 8);
+#else
clk_div = ssp_get_clk_div(ssp, speed);
-
+#endif
if (bits <= 8) {
drv_data->n_bytes = 1;
drv_data->dma_width = DCMD_WIDTH1;
@@ -1061,18 +1560,32 @@ static void pump_transfers(unsigned long data)
if (set_dma_burst_and_threshold(chip, message->spi,
bits, &dma_burst,
&dma_thresh))
- if (printk_ratelimit())
- dev_warn(&message->spi->dev,
- "pump_transfers: "
- "DMA burst size reduced to "
- "match bits_per_word\n");
+ dev_warn_ratelimited(&message->spi->dev,
+ "pump_transfers: "
+ "DMA burst size reduced to"
+ " match bits_per_word\n");
}
- cr0 = clk_div
- | SSCR0_Motorola
- | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
- | SSCR0_SSE
- | (bits > 16 ? SSCR0_EDSS : 0);
+ switch (drv_data->ssp_type) {
+ case CE5X00_SSP:
+ chip->cr0 = clk_div
+ | CE5X00_SSCR0_Motorola
+ | CE5X00_SSCR0_DataSize(bits > 32 ?
+ 8 : bits)
+ | SSCR0_SSE;
+ break;
+ case CE4100_SSP:
+ case PXA25x_SSP:
+ default:
+ chip->cr0 = clk_div
+ | SSCR0_Motorola
+ | SSCR0_DataSize(bits > 16 ?
+ bits - 16 : bits)
+ | SSCR0_SSE
+ | (bits > 16 ? SSCR0_EDSS : 0);
+ }
+
+ cr0 = chip->cr0;
}
message->state = RUNNING_STATE;
@@ -1138,7 +1651,7 @@ static void pump_transfers(unsigned long data)
/* Clear status and start DMA engine */
cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
- write_SSSR(drv_data->clear_sr, reg);
+ write_sssr(drv_data->clear_sr, reg);
DCSR(drv_data->rx_channel) |= DCSR_RUN;
DCSR(drv_data->tx_channel) |= DCSR_RUN;
} else {
@@ -1147,100 +1660,72 @@ static void pump_transfers(unsigned long data)
/* Clear status */
cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
- write_SSSR_CS(drv_data, drv_data->clear_sr);
+ write_sssr_cs(drv_data, drv_data->clear_sr);
}
/* see if we need to reload the config registers */
- if ((read_SSCR0(reg) != cr0)
- || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
- (cr1 & SSCR1_CHANGE_MASK)) {
+ if (drv_data->ssp_type == CE5X00_SSP) {
+#ifdef CONFIG_INTEL_CLN_SOC
+ if (read_dds_rate(reg) != chip->dds_rate)
+ write_dds_rate(chip->dds_rate, reg);
+#endif
+ if ((read_sscr0(reg) != cr0)
+ || (read_sscr1(reg) & CE5X00_SSCR1_CHANGE_MASK) !=
+ (cr1 & CE5X00_SSCR1_CHANGE_MASK)) {
+ /* stop the SSP, and update the other bits */
+ write_sscr0(cr0 & ~SSCR0_SSE, reg);
+ if (!pxa25x_ssp_comp(drv_data))
+ write_ssto(chip->timeout, reg);
+ /* first set CR1 w/o interrupt and service enables */
+ write_sscr1(cr1 & CE5X00_SSCR1_CHANGE_MASK, reg);
+ /* restart the SSP */
+ write_sscr0(cr0, reg);
+ } else {
+ if (!pxa25x_ssp_comp(drv_data))
+ write_ssto(chip->timeout, reg);
+ }
+ } else if ((read_sscr0(reg) != cr0)
+ || (read_sscr1(reg) & SSCR1_CHANGE_MASK) !=
+ (cr1 & SSCR1_CHANGE_MASK)) {
/* stop the SSP, and update the other bits */
- write_SSCR0(cr0 & ~SSCR0_SSE, reg);
+ write_sscr0(cr0 & ~SSCR0_SSE, reg);
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(chip->timeout, reg);
+ write_ssto(chip->timeout, reg);
/* first set CR1 without interrupt and service enables */
- write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
+ write_sscr1(cr1 & SSCR1_CHANGE_MASK, reg);
/* restart the SSP */
- write_SSCR0(cr0, reg);
+ write_sscr0(cr0, reg);
- } else {
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(chip->timeout, reg);
+ } else if (!pxa25x_ssp_comp(drv_data)) {
+ write_ssto(chip->timeout, reg);
}
-
cs_assert(drv_data);
/* after chip select, release the data by enabling service
* requests and interrupts, without changing any mode bits */
- write_SSCR1(cr1, reg);
+ write_sscr1(cr1, reg);
}
-static void pump_messages(struct work_struct *work)
+static int transfer_one_message(struct spi_master *master,
+ struct spi_message *msg)
{
- struct driver_data *drv_data =
- container_of(work, struct driver_data, pump_messages);
- unsigned long flags;
-
- /* Lock queue and check for queue work */
- spin_lock_irqsave(&drv_data->lock, flags);
- if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
- drv_data->busy = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
+ struct driver_data *drv_data = spi_master_get_devdata(master);
- /* Make sure we are not already running a message */
- if (drv_data->cur_msg) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Extract head of queue */
- drv_data->cur_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
- list_del_init(&drv_data->cur_msg->queue);
+ /* Initial message state */
+ drv_data->cur_msg = msg;
+ msg->state = START_STATE;
- /* Initial message state*/
- drv_data->cur_msg->state = START_STATE;
- drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
- struct spi_transfer,
- transfer_list);
+ drv_data->cur_transfer = list_entry(msg->transfers.next,
+ struct spi_transfer, transfer_list);
/* prepare to setup the SSP, in pump_transfers, using the per
* chip configuration */
- drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+ drv_data->cur_chip = spi_get_ctldata(msg->spi);
- /* Mark as busy and launch transfers */
+ /* Launch transfers */
tasklet_schedule(&drv_data->pump_transfers);
- drv_data->busy = 1;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-static int transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct driver_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (drv_data->run == QUEUE_STOPPED) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -ESHUTDOWN;
- }
-
- msg->actual_length = 0;
- msg->status = -EINPROGRESS;
- msg->state = START_STATE;
-
- list_add_tail(&msg->queue, &drv_data->queue);
-
- if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
return 0;
}
@@ -1267,8 +1752,9 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
if (gpio_is_valid(chip_info->gpio_cs)) {
err = gpio_request(chip_info->gpio_cs, "SPI_CS");
if (err) {
- dev_err(&spi->dev, "failed to request chip select "
- "GPIO%d\n", chip_info->gpio_cs);
+ dev_err(&spi->dev,
+ "failed to request chip select "
+ "GPIO%d\n", chip_info->gpio_cs);
return err;
}
@@ -1282,6 +1768,31 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
return err;
}
+static int prepare_transfer_hardware(struct spi_master *master)
+{
+ struct driver_data *drv_data = spi_master_get_devdata(master);
+
+ /*
+ * Just make sure we have all we need to run the transfer by syncing
+ * with the runtime PM framework.
+ */
+ pm_runtime_get_sync(&drv_data->pdev->dev);
+ return 0;
+}
+
+static int unprepare_transfer_hardware(struct spi_master *master)
+{
+ struct driver_data *drv_data = spi_master_get_devdata(master);
+
+ /* nothing more to do - disable spi/ssp and power off */
+ write_sscr0(0, drv_data->ioaddr);
+ clk_disable(drv_data->ssp->clk);
+
+ pm_runtime_put(&drv_data->pdev->dev);
+
+ return 0;
+}
+
static int setup(struct spi_device *spi)
{
struct pxa2xx_spi_chip *chip_info = NULL;
@@ -1289,21 +1800,29 @@ static int setup(struct spi_device *spi)
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
struct ssp_device *ssp = drv_data->ssp;
unsigned int clk_div;
+#ifdef CONFIG_INTEL_CLN_SOC
+ u32 actual_speed;
+#endif
uint tx_thres = TX_THRESH_DFLT;
uint rx_thres = RX_THRESH_DFLT;
-
- if (!pxa25x_ssp_comp(drv_data)
+ if (drv_data->ssp_type == CE5X00_SSP) {
+ tx_thres = TX_THRESH_CE5X00_DFLT;
+ rx_thres = RX_THRESH_CE5X00_DFLT;
+ }
+ if ((!pxa25x_ssp_comp(drv_data) || pxa25x_ssp_comp(drv_data) == 2)
&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
- dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
- "b/w not 4-32 for type non-PXA25x_SSP\n",
- drv_data->ssp_type, spi->bits_per_word);
+ dev_err(&spi->dev,
+ "failed setup: ssp_type=%d, bits/wrd=%d "
+ "b/w not 4-32 for type non-PXA25x_SSP\n",
+ drv_data->ssp_type, spi->bits_per_word);
return -EINVAL;
- } else if (pxa25x_ssp_comp(drv_data)
+ } else if (pxa25x_ssp_comp(drv_data) == 1
&& (spi->bits_per_word < 4
|| spi->bits_per_word > 16)) {
- dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
- "b/w not 4-16 for type PXA25x_SSP\n",
- drv_data->ssp_type, spi->bits_per_word);
+ dev_err(&spi->dev,
+ "failed setup: ssp_type=%d, bits/wrd=%d "
+ "b/w not 4-16 for type PXA25x_SSP\n",
+ drv_data->ssp_type, spi->bits_per_word);
return -EINVAL;
}
@@ -1319,8 +1838,9 @@ static int setup(struct spi_device *spi)
if (drv_data->ssp_type == CE4100_SSP) {
if (spi->chip_select > 4) {
- dev_err(&spi->dev, "failed setup: "
- "cs number must not be > 4.\n");
+ dev_err(&spi->dev,
+ "failed setup: "
+ "cs number must not be > 4.\n");
kfree(chip);
return -EINVAL;
}
@@ -1328,6 +1848,7 @@ static int setup(struct spi_device *spi)
chip->frm = spi->chip_select;
} else
chip->gpio_cs = -1;
+
chip->enable_dma = 0;
chip->timeout = TIMOUT_DFLT;
chip->dma_burst_size = drv_data->master_info->enable_dma ?
@@ -1340,6 +1861,7 @@ static int setup(struct spi_device *spi)
/* chip_info isn't always needed */
chip->cr1 = 0;
+ chip->cr0 = 0;
if (chip_info) {
if (chip_info->timeout)
chip->timeout = chip_info->timeout;
@@ -1353,9 +1875,6 @@ static int setup(struct spi_device *spi)
chip->cr1 = SSCR1_LBM;
}
- chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
- (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
-
/* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the
* burst and threshold can still respond to changes in bits_per_word */
@@ -1364,33 +1883,73 @@ static int setup(struct spi_device *spi)
if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word,
&chip->dma_burst_size,
&chip->dma_threshold)) {
- dev_warn(&spi->dev, "in setup: DMA burst size reduced "
- "to match bits_per_word\n");
+ dev_warn(&spi->dev,
+ "in setup: DMA burst size reduced "
+ "to match bits_per_word\n");
}
}
-
+#ifdef CONFIG_INTEL_CLN_SOC
+ actual_speed = cln_set_clk_regvals(spi->max_speed_hz,
+ &chip->dds_rate, &clk_div);
+ clk_div = (clk_div << 8);
+#else
clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
+#endif
chip->speed_hz = spi->max_speed_hz;
- chip->cr0 = clk_div
+ switch (drv_data->ssp_type) {
+ case CE5X00_SSP:
+ chip->cr0 = clk_div
+ | CE5X00_SSCR0_Motorola
+ | CE5X00_SSCR0_DataSize(spi->bits_per_word > 32 ?
+ 8 : spi->bits_per_word)
+ | SSCR0_SSE;
+ chip->threshold = (CE5X00_SSCR1_RxTresh(rx_thres)
+ & CE5X00_SSCR1_RFT) |
+ (CE5X00_SSCR1_TxTresh(tx_thres) & CE5X00_SSCR1_TFT);
+ break;
+ case CE4100_SSP:
+ case PXA25x_SSP:
+ default:
+ chip->cr0 = clk_div
| SSCR0_Motorola
| SSCR0_DataSize(spi->bits_per_word > 16 ?
spi->bits_per_word - 16 : spi->bits_per_word)
| SSCR0_SSE
| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
+ chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+ (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+ }
+
chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
+#ifdef CONFIG_INTEL_CLN_SOC
+ chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+ | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0)
+ | (((spi->mode & SPI_LOOP) != 0) ? SSCR1_LBM : 0);
+#else
chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
+#endif
/* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (!pxa25x_ssp_comp(drv_data))
- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
+ dev_dbg(&spi->dev,
+ "%ld Hz actual, %s\n",
+#ifndef CONFIG_GEN3_SPI
clk_get_rate(ssp->clk)
+#else
+ spi_clk_get_rate(ssp->type)
+#endif
/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO");
else
- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
+ dev_dbg(&spi->dev,
+ "%ld Hz actual, %s\n",
+#ifndef CONFIG_GEN3_SPI
clk_get_rate(ssp->clk) / 2
+#else
+ spi_clk_get_rate(ssp->type) / 2
+#endif
/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO");
@@ -1405,7 +1964,9 @@ static int setup(struct spi_device *spi)
chip->read = u16_reader;
chip->write = u16_writer;
} else if (spi->bits_per_word <= 32) {
+#ifndef CONFIG_GEN3_SPI
chip->cr0 |= SSCR0_EDSS;
+#endif
chip->n_bytes = 4;
chip->dma_width = DCMD_WIDTH4;
chip->read = u32_reader;
@@ -1438,94 +1999,6 @@ static void cleanup(struct spi_device *spi)
kfree(chip);
}
-static int init_queue(struct driver_data *drv_data)
-{
- INIT_LIST_HEAD(&drv_data->queue);
- spin_lock_init(&drv_data->lock);
-
- drv_data->run = QUEUE_STOPPED;
- drv_data->busy = 0;
-
- tasklet_init(&drv_data->pump_transfers,
- pump_transfers, (unsigned long)drv_data);
-
- INIT_WORK(&drv_data->pump_messages, pump_messages);
- drv_data->workqueue = create_singlethread_workqueue(
- dev_name(drv_data->master->dev.parent));
- if (drv_data->workqueue == NULL)
- return -EBUSY;
-
- return 0;
-}
-
-static int start_queue(struct driver_data *drv_data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -EBUSY;
- }
-
- drv_data->run = QUEUE_RUNNING;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- drv_data->cur_chip = NULL;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- return 0;
-}
-
-static int stop_queue(struct driver_data *drv_data)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- /* This is a bit lame, but is optimized for the common execution path.
- * A wait_queue on the drv_data->busy could be used, but then the common
- * execution path (pump_messages) would be required to call wake_up or
- * friends on every SPI message. Do this instead */
- drv_data->run = QUEUE_STOPPED;
- while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- msleep(10);
- spin_lock_irqsave(&drv_data->lock, flags);
- }
-
- if (!list_empty(&drv_data->queue) || drv_data->busy)
- status = -EBUSY;
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return status;
-}
-
-static int destroy_queue(struct driver_data *drv_data)
-{
- int status;
-
- status = stop_queue(drv_data);
- /* we are unloading the module or failing to load (only two calls
- * to this routine), and neither call can handle a return value.
- * However, destroy_workqueue calls flush_workqueue, and that will
- * block until all work is done. If the reason that stop_queue
- * timed out is that the work will never finish, then it does no
- * good to call destroy_workqueue, so return anyway. */
- if (status != 0)
- return status;
-
- destroy_workqueue(drv_data->workqueue);
-
- return 0;
-}
-
static int pxa2xx_spi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1557,16 +2030,27 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->ssp = ssp;
master->dev.parent = &pdev->dev;
+#ifdef CONFIG_OF
+#ifndef CONFIG_GEN3_SPI
master->dev.of_node = pdev->dev.of_node;
+#endif
+#endif
+
/* the spi->mode bits understood by this driver: */
+#ifdef CONFIG_INTEL_CLN_SOC
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+#else
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
+#endif
master->bus_num = pdev->id;
master->num_chipselect = platform_info->num_chipselect;
master->dma_alignment = DMA_ALIGNMENT;
master->cleanup = cleanup;
master->setup = setup;
- master->transfer = transfer;
+ master->prepare_transfer_hardware = prepare_transfer_hardware;
+ master->transfer_one_message = transfer_one_message;
+ master->unprepare_transfer_hardware = unprepare_transfer_hardware;
+ master->rt = true;
drv_data->ssp_type = ssp->type;
drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
@@ -1628,43 +2112,59 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
clk_enable(ssp->clk);
/* Load default SSP configuration */
- write_SSCR0(0, drv_data->ioaddr);
- write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
- SSCR1_TxTresh(TX_THRESH_DFLT),
- drv_data->ioaddr);
- write_SSCR0(SSCR0_SCR(2)
- | SSCR0_Motorola
- | SSCR0_DataSize(8),
- drv_data->ioaddr);
+ write_sscr0(0, drv_data->ioaddr);
+ switch (drv_data->ssp_type) {
+ case CE5X00_SSP:
+ write_sscr1(CE5X00_SSCR1_RxTresh(RX_THRESH_CE5X00_DFLT) |
+ CE5X00_SSCR1_TxTresh(TX_THRESH_CE5X00_DFLT),
+ drv_data->ioaddr);
+#ifdef CONFIG_INTEL_CLN_SOC
+ /* using the Motorola SPI protocol and use 8 bit frame */
+ write_sscr0(CE5X00_SSCR0_Motorola
+ | CE5X00_SSCR0_DataSize(8),
+ drv_data->ioaddr);
+#else
+ /* default using Motorola SPI protocol and use 8 bit frame */
+ write_sscr0(SSCR0_SCR(2)
+ | CE5X00_SSCR0_Motorola
+ | CE5X00_SSCR0_DataSize(8),
+ drv_data->ioaddr);
+#endif
+ break;
+ case CE4100_SSP:
+ case PXA25x_SSP:
+ default:
+ write_sscr1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+ SSCR1_TxTresh(TX_THRESH_DFLT),
+ drv_data->ioaddr);
+ write_sscr0(SSCR0_SCR(2)
+ | SSCR0_Motorola
+ | SSCR0_DataSize(8),
+ drv_data->ioaddr);
+ }
if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, drv_data->ioaddr);
- write_SSPSP(0, drv_data->ioaddr);
+ write_ssto(0, drv_data->ioaddr);
+#ifndef CONFIG_GEN3_SPI
+ /*
+ * SSPSP register is resrved on the CEXXXX SOCs.
+ */
+ write_sspsp(0, drv_data->ioaddr);
+#endif
- /* Initial and start queue */
- status = init_queue(drv_data);
- if (status != 0) {
- dev_err(&pdev->dev, "problem initializing queue\n");
- goto out_error_clock_enabled;
- }
- status = start_queue(drv_data);
- if (status != 0) {
- dev_err(&pdev->dev, "problem starting queue\n");
- goto out_error_clock_enabled;
- }
+ /* Initialise transfer pump */
+ tasklet_init(&drv_data->pump_transfers,
+ pump_transfers, (unsigned long)drv_data);
/* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data);
status = spi_register_master(master);
if (status != 0) {
dev_err(&pdev->dev, "problem registering spi master\n");
- goto out_error_queue_alloc;
+ goto out_error_clock_enabled;
}
return status;
-out_error_queue_alloc:
- destroy_queue(drv_data);
-
out_error_clock_enabled:
clk_disable(ssp->clk);
@@ -1687,28 +2187,13 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
{
struct driver_data *drv_data = platform_get_drvdata(pdev);
struct ssp_device *ssp;
- int status = 0;
if (!drv_data)
return 0;
ssp = drv_data->ssp;
- /* Remove the queue */
- status = destroy_queue(drv_data);
- if (status != 0)
- /* the kernel does not check the return status of this
- * this routine (mod->exit, within the kernel). Therefore
- * nothing is gained by returning from here, the module is
- * going away regardless, and we should not leave any more
- * resources allocated than necessary. We cannot free the
- * message memory in drv_data->queue, but we can release the
- * resources below. I think the kernel should honor -EBUSY
- * returns but... */
- dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
- "complete, message memory not freed\n");
-
/* Disable the SSP at the peripheral and SOC level */
- write_SSCR0(0, drv_data->ioaddr);
+ write_sscr0(0, drv_data->ioaddr);
clk_disable(ssp->clk);
/* Release DMA */
@@ -1725,6 +2210,9 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
/* Release SSP */
pxa_ssp_free(ssp);
+ /* Disable transfer pump */
+ tasklet_disable(&drv_data->pump_transfers);
+
/* Disconnect from the SPI framework */
spi_unregister_master(drv_data->master);
@@ -1738,7 +2226,8 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev)
{
int status = 0;
- if ((status = pxa2xx_spi_remove(pdev)) != 0)
+ status = pxa2xx_spi_remove(pdev);
+ if (status != 0)
dev_err(&pdev->dev, "shutdown failed with %d\n", status);
}
@@ -1749,10 +2238,15 @@ static int pxa2xx_spi_suspend(struct device *dev)
struct ssp_device *ssp = drv_data->ssp;
int status = 0;
- status = stop_queue(drv_data);
- if (status != 0)
+ status = spi_master_suspend(drv_data->master);
+ if (status) {
+ dev_warn(dev, "cannot suspend master\n");
return status;
- write_SSCR0(0, drv_data->ioaddr);
+ }
+
+ pm_runtime_get_sync(dev);
+
+ write_sscr0(0, drv_data->ioaddr);
clk_disable(ssp->clk);
return 0;
@@ -1774,14 +2268,14 @@ static int pxa2xx_spi_resume(struct device *dev)
/* Enable the SSP clock */
clk_enable(ssp->clk);
+ pm_runtime_put(dev);
+
/* Start the queue running */
- status = start_queue(drv_data);
- if (status != 0) {
+ status = spi_master_resume(drv_data->master);
+ if (status)
dev_err(dev, "problem starting queue (%d)\n", status);
- return status;
- }
- return 0;
+ return status;
}
static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 19ee901..493ce4a 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1248,10 +1248,10 @@ int spi_master_resume(struct spi_master *master)
}
EXPORT_SYMBOL_GPL(spi_master_resume);
-static int __spi_master_match(struct device *dev, void *data)
+static int __spi_master_match(struct device *dev, const void *data)
{
struct spi_master *m;
- u16 *bus_num = data;
+ const u16 *bus_num = data;
m = container_of(dev, struct spi_master, dev);
return m->bus_num == *bus_num;
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 733f22c..5f85dde 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -561,6 +561,59 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
}
}
+/* Uart divisor latch read */
+static inline int _serial_dl_read(struct uart_8250_port *up)
+{
+ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+{
+ serial_out(up, UART_DLL, value & 0xff);
+ serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#if defined(CONFIG_MIPS_ALCHEMY)
+/* Au1x00 haven't got a standard divisor latch */
+static int serial_dl_read(struct uart_8250_port *up)
+{
+ if (up->port.iotype == UPIO_AU)
+ return __raw_readl(up->port.membase + 0x28);
+ else
+ return _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+ if (up->port.iotype == UPIO_AU)
+ __raw_writel(value, up->port.membase + 0x28);
+ else
+ _serial_dl_write(up, value);
+}
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+static int serial_dl_read(struct uart_8250_port *up)
+{
+ return (up->port.iotype == UPIO_RM9000) ?
+ (((__raw_readl(up->port.membase + 0x10) << 8) |
+ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+ _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+ if (up->port.iotype == UPIO_RM9000) {
+ __raw_writel(value, up->port.membase + 0x08);
+ __raw_writel(value >> 8, up->port.membase + 0x10);
+ } else {
+ _serial_dl_write(up, value);
+ }
+}
+#else
+#define serial_dl_read(up) _serial_dl_read(up)
+#define serial_dl_write(up, value) _serial_dl_write(up, value)
+#endif
+
/*
* For the 16C950
*/
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 5cdb092..9f5d030 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -27,7 +27,13 @@
#include "8250.h"
-#undef SERIAL_DEBUG_PCI
+/* CLANTON FPGA */
+#define SERIAL_DEBUG_PCI
+
+/* TODO: Bryan remove ! */
+static unsigned int clanton_enable_msi = 0;
+module_param(clanton_enable_msi, uint, 0644);
+MODULE_PARM_DESC(clanton_enable_msi, "Enable MSI operation on Clanton 8250-PCI");
/*
* init function returns:
@@ -156,6 +162,20 @@ afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
}
/*
+ * UART parameters for Intel Clanton setup
+ */
+static int
+pci_intel_cln_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ unsigned int bar, offset = board->first_offset;
+ bar = FL_GET_BASE(board->flags);
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
* HP's Remote Management Console. The Diva chip came in several
* different versions. N-class, L2000 and A500 have two Diva chips, each
* with 3 UARTs (the third UART on the second chip is unused). Superdome
@@ -1410,6 +1430,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = kt_serial_setup,
},
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x0936,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_intel_cln_setup,
+ },
+
/*
* ITE
*/
@@ -2139,6 +2167,8 @@ enum pci_board_num_t {
pbn_oxsemi_2_4000000,
pbn_oxsemi_4_4000000,
pbn_oxsemi_8_4000000,
+ pbn_intel_cb,
+ pbn_intel_cln,
pbn_intel_i960,
pbn_sgi_ioc3,
pbn_computone_4,
@@ -2725,6 +2755,12 @@ static struct pciserial_board pci_boards[] = {
.reg_shift = 2,
.first_offset = 0x10000,
},
+ [pbn_intel_cln] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 2764800,
+ .reg_shift = 2,
+ },
[pbn_sgi_ioc3] = {
.flags = FL_BASE0|FL_NOIRQ,
.num_ports = 1,
@@ -3187,6 +3223,14 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
if (rc)
return rc;
+ /* TODO: Bryan remove ! */
+ if(clanton_enable_msi == 1){
+ if(pci_enable_msi(dev)!=0){
+ printk(KERN_ERR "CLANTON/DEBUG unable to enable MSIs on serial port!\n");
+ }
+ }
+
+
if (ent->driver_data == pbn_default) {
/*
* Use a copy of the pci_board entry for this;
@@ -3998,6 +4042,12 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b2_bt_2_115200 },
+ /*
+ * Clanton descriptor
+ */
+ { PCI_VENDOR_ID_INTEL, 0x0936,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_intel_cln },
/*
* EKF addition for i960 Boards form EKF with serial port
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 02e706e..a656d3b 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1327,6 +1327,26 @@ config SERIAL_IFX6X60
help
Support for the IFX6x60 modem devices on Intel MID platforms.
+config SERIAL_CLN_UART
+ tristate "Intel Clanton UART"
+ depends on PCI
+ select SERIAL_CORE
+ select DMADEVICES
+ select INTEL_CLN_DMAC
+ help
+ This driver is for Intel(R) Clanton UART with DMA enabled.
+ If you don't want DMA then you should use the standard 8250_pci
+ driver.
+
+config SERIAL_CLN_UART_CONSOLE
+ bool "Support for console on Intel Clanton UART"
+ depends on SERIAL_CLN_UART=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Say Y here if you wish to use the Clanton UART as the system console
+ (the system console is the device which receives all kernel messages and
+ warnings and which allows logins in single user mode).
+
config SERIAL_PCH_UART
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART"
depends on PCI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index df1b998..62a1833 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
+obj-$(CONFIG_SERIAL_CLN_UART) += intel_cln_uart.o
obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o
obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
diff --git a/drivers/tty/serial/intel_cln_uart.c b/drivers/tty/serial/intel_cln_uart.c
new file mode 100644
index 0000000..17454d0
--- /dev/null
+++ b/drivers/tty/serial/intel_cln_uart.c
@@ -0,0 +1,1759 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton DMA-UART driver
+ *
+ * The hardware here consists of
+ * 1 x MMIO BAR with 16550 compatible deisgnware UART regs - byte aligned
+ * 1 x MMIO BAR with a designware DMAC - modified for byte aligned bursts
+ * Lots of code stolen with pride from pch_uart.c/mfd.c
+ *
+ * DMA Config - set by hardware as a default
+ *
+ * Channel 0 : RX (Device to host)
+ * CTL0_LO : 0x00304837
+ * CTL0_HI : 0x00000002
+ * CFG0_LO : 0x00000C00 (HS_DST_SRC | HS_SEL_SRC)
+ * CFG0_HI : 0x00000004
+ *
+ *
+ * Channel 1 : TX (Host to device)
+ * CTL1_LO : 0x00304837
+ * CTL1_HI : 0x00000002
+ * CFG1_LO : 0x00000C20 (HS_DST_SRC | HS_SEL_SRC | CH_PRIOR:001)
+ * CFG1_HI : 0x00000004 (PROTCTL = 001)
+ *
+ */
+
+#include <asm/io.h>
+#include <linux/console.h>
+#include <linux/debugfs.h>
+#include <linux/intel_mid_dma.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/tty_flip.h>
+
+#define CLN_UART_MAX_INSTANCES 2
+#define CLN_UART_DMA_CHANNELS 2
+#define CLN_UART_DMA_TXCHAN 1
+#define CLN_UART_DMA_RXCHAN 0
+#define CLN_UART_FIFO_LEN 16
+#define CLN_UART_DRIVER_DEVICE "ttyCLN"
+#define CLN_UART_DMA_BUF_SIZE PAGE_SIZE
+
+#define CLN_UART_MODE_MSI 0x00000001
+#define CLN_UART_MODE_DMA 0x00000002
+
+#define CLN_UART_DEFAULT_UARTCLK 1843200 /* 1.8432 MHz */
+
+/* IIR bits - TO is non-standard */
+#define INTEL_CLN_UART_IIR_MS 0x00
+#define INTEL_CLN_UART_IIR_NOIRQ 0x01
+#define INTEL_CLN_UART_IIR_THRE 0x02
+#define INTEL_CLN_UART_IIR_RXD 0x04
+#define INTEL_CLN_UART_IIR_RLS 0x06
+#define INTEL_CLN_UART_IIR_BUSY 0x07
+#define INTEL_CLN_UART_IIR_TO 0x08
+
+static bool dma_enable = false;
+static int intel_cln_uart_port_ct = 0;
+module_param(dma_enable, bool, 0644);
+MODULE_PARM_DESC(dma_enable, "Enable/disable DMA - default true");
+
+/**
+ * struct inel_cln_uart_buffer
+ *
+ * Descriptor for a UART bufer
+ */
+struct intel_cln_uart_buffer {
+ dma_addr_t dma_addr;
+ unsigned char *buf_virt;
+ u32 offs;
+ int size;
+};
+
+/**
+ * struct intel_cln_uart
+ *
+ * Describes an individual UART
+ */
+struct intel_cln_uart {
+ char name[10];
+ int uartclk;
+ int tx_dma_use;
+ int start_tx;
+ int start_rx;
+ int dma_tx_nent;
+ int tx_empty;
+
+ spinlock_t lock;
+ struct dentry *debugfs;
+ struct device *dev;
+ struct dma_async_tx_descriptor *desc_tx;
+ struct dma_async_tx_descriptor *desc_rx;
+ struct dma_chan *tx_chan;
+ struct dma_chan *rx_chan;
+ struct middma_device mid_dma;
+ struct intel_cln_uart_buffer txbuf;
+ struct intel_cln_uart_buffer rxbuf;
+ struct intel_mid_dma_slave dmas_rx;
+ struct intel_mid_dma_slave dmas_tx;
+ struct scatterlist *sg_tx_p;
+ struct scatterlist sg_rx;
+ struct uart_port port;
+
+ unsigned char fcr;
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+
+ unsigned long paddr;
+ unsigned long iolen;
+ unsigned long tx_trigger_level;
+ unsigned long rx_trigger_level;
+ u32 irq;
+ u32 mode;
+};
+
+/**
+ * serial_in
+ *
+ * @param up: pointer to uart descriptor
+ * @param offset: register offset
+ *
+ * Reads a register @ offset
+ */
+static inline unsigned int serial_in(struct intel_cln_uart *up, int offset)
+{
+ return (unsigned int)readb(up->port.membase + offset);
+}
+
+/**
+ * serial_out
+ *
+ * @param up: pointer to uart descriptor
+ * @param offset: register offset
+ *
+ * Writes a register @ offset
+ */
+static inline void serial_out(struct intel_cln_uart *up, int offset, int value)
+{
+ unsigned char val = value & 0xff;
+ writeb(val, up->port.membase + offset);
+}
+
+/**
+ * intel_cln_uart_handle_rx_to
+ *
+ * For FIFO RX timeout just read the data until nothing else to read
+ */
+static int intel_cln_uart_hal_read(struct intel_cln_uart *up, unsigned char *buf,
+ int rx_size)
+{
+ int i;
+ u8 rbr, lsr;
+
+ lsr = serial_in(up, UART_LSR);
+ for (i = 0, lsr = serial_in(up, UART_LSR);
+ i < rx_size && lsr & UART_LSR_DR;
+ lsr = serial_in(up, UART_LSR)) {
+ rbr = serial_in(up, UART_RX);
+ buf[i++] = rbr;
+ }
+ return i;
+}
+
+/**
+ * intel_cln_uart_hal_write
+ *
+ * For FIFO RX timeout just read the data until nothing else to read
+ */
+static void intel_cln_uart_hal_write(struct intel_cln_uart *up, unsigned char *buf,
+ int tx_size)
+{
+ int i;
+ unsigned int thr;
+
+ for (i = 0; i < tx_size;) {
+ thr = buf[i++];
+ serial_out(up, UART_TX, thr);
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+#define INTEL_CLN_UART_REGS_BUFSIZE 1024
+
+/**
+ * port_show_regs
+ *
+ * @param file: pointer to uart descriptor
+ * @param user_buf: register offset
+ * @param count:
+ * @param ppos:
+ *
+ * Dump uart regs to string @ user_buf
+ */
+static ssize_t port_show_regs(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct intel_cln_uart *up = file->private_data;
+ char *buf;
+ u32 len = 0;
+ ssize_t ret;
+
+ buf = kzalloc(INTEL_CLN_UART_REGS_BUFSIZE, GFP_KERNEL);
+ if (!buf)
+ return 0;
+
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "INTEL_CLN_UART port regs:\n");
+
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "=================================\n");
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "IER: \t\t0x%08x\n", serial_in(up, UART_IER));
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR));
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR));
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR));
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR));
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR));
+ len += snprintf(buf + len, INTEL_CLN_UART_REGS_BUFSIZE - len,
+ "FCR: \t\t0x%08x\n", serial_in(up, UART_FCR));
+
+ if (len > INTEL_CLN_UART_REGS_BUFSIZE)
+ len = INTEL_CLN_UART_REGS_BUFSIZE;
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations port_regs_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = port_show_regs,
+ .llseek = default_llseek,
+};
+
+/**
+ * intel_cln_uart_debugfs_init
+ *
+ * @param up: pointer to uart descriptor
+ *
+ * Create a debug FS entry for the UART and associated register entries
+ */
+static int intel_cln_uart_debugfs_init(struct intel_cln_uart *up)
+{
+ up->debugfs = debugfs_create_dir("intel_cln_uart", NULL);
+ if (!up->debugfs)
+ return -ENOMEM;
+
+ debugfs_create_file(up->name, S_IFREG | S_IRUGO,
+ up->debugfs, (void *)up, &port_regs_ops);
+ return 0;
+}
+
+/**
+ * intel_cln_uart_debugfs_remove
+ *
+ * @param up: pointer to uart descriptor
+ *
+ * Remove recursive debug FS entries for the UART
+ */
+static void intel_cln_uart_debugfs_remove(struct intel_cln_uart *intel_cln_uart)
+{
+ if (intel_cln_uart->debugfs)
+ debugfs_remove_recursive(intel_cln_uart->debugfs);
+}
+
+#else
+static inline int intel_cln_uart_debugfs_init(struct intel_cln_uart *intel_cln_uart)
+{
+ return 0;
+}
+
+static inline void intel_cln_uart_debugfs_remove(struct intel_cln_uart *intel_cln_uart)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/**
+ * intel_cln_uart_enable_ms
+ *
+ * @param up: pointer to uart port structure
+ *
+ * Enable the modem status interrupt
+ */
+static void intel_cln_uart_enable_ms(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+
+ up->ier |= UART_IER_MSI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+/**
+ * intel_cln_uart_dma_tx_complete
+ *
+ * @param arg: Pointer to intel_cln_uart
+ *
+ * TX DMA completion callback
+ */
+static void intel_cln_uart_dma_tx_complete(void *arg)
+{
+ struct intel_cln_uart *up = arg;
+ struct uart_port *port = &up->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ struct scatterlist *sg = up->sg_tx_p;
+ int i;
+
+ for (i = 0; i < up->dma_tx_nent; i++, sg++) {
+ xmit->tail += sg_dma_len(sg);
+ port->icount.tx += sg_dma_len(sg);
+ }
+ xmit->tail &= UART_XMIT_SIZE - 1;
+ async_tx_ack(up->desc_tx);
+ dma_unmap_sg(port->dev, sg, up->dma_tx_nent, DMA_TO_DEVICE);
+ up->tx_dma_use = 0;
+ up->dma_tx_nent = 0;
+ kfree(up->sg_tx_p);
+
+ /* TODO: move to function */
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+static int pop_tx(struct intel_cln_uart *up, int size)
+{
+ int count = 0;
+ struct uart_port *port = &up->port;
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (uart_tx_stopped(port) || uart_circ_empty(xmit) || count >= size)
+ goto pop_tx_end;
+
+ do {
+ int cnt_to_end =
+ CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ int sz = min(size - count, cnt_to_end);
+ intel_cln_uart_hal_write(up, &xmit->buf[xmit->tail], sz);
+ xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
+ count += sz;
+ } while (!uart_circ_empty(xmit) && count < size);
+
+pop_tx_end:
+ dev_dbg(up->port.dev, "%d characters. Remained %d characters.(%lu)\n",
+ count, size - count, jiffies);
+
+ return count;
+}
+
+static int pop_tx_x(struct intel_cln_uart *up, unsigned char *buf)
+{
+ int ret = 0;
+ struct uart_port *port = &up->port;
+
+ if (port->x_char) {
+ dev_dbg(up->port.dev, "%s:X character send %02x (%lu)\n",
+ __func__, port->x_char, jiffies);
+ buf[0] = port->x_char;
+ port->x_char = 0;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int push_rx(struct intel_cln_uart *up, const unsigned char *buf,
+ int size)
+{
+ struct uart_port *port;
+ struct tty_struct *tty;
+
+ port = &up->port;
+ tty = tty_port_tty_get(&port->state->port);
+ if (!tty) {
+ dev_dbg(up->port.dev, "%s:tty is busy now", __func__);
+ return -EBUSY;
+ }
+
+ tty_insert_flip_string(tty, buf, size);
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+
+ return 0;
+}
+
+/**
+ * intel_cln_uart_dma_tx
+ *
+ * @param arg: Pointer to intel_cln_uart
+ *
+ * Initiate a TX DMA transaction
+ */
+void intel_cln_uart_dma_tx(struct intel_cln_uart *up)
+{
+ struct uart_port *port = &up->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ struct scatterlist *sg;
+ int nent;
+ int fifo_size;
+ //int tx_empty;
+ struct dma_async_tx_descriptor *desc;
+ int num;
+ int i;
+ int bytes;
+ int size;
+ int rem;
+
+ if (!up->start_tx) {
+ dev_info(up->port.dev, "%s:Tx isn't started. (%lu)\n",
+ __func__, jiffies);
+
+ /* TODO: move to function */
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+
+ up->tx_empty = 1;
+ return;
+ }
+
+ if (up->tx_dma_use) {
+ dev_dbg(up->port.dev, "%s:Tx is not completed. (%lu)\n",
+ __func__, jiffies);
+
+ /* TODO: move to function */
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+
+ up->tx_empty = 1;
+ return;
+ }
+
+ fifo_size = max((int)port->fifosize, 1);
+ if (pop_tx_x(up, xmit->buf)) {
+ intel_cln_uart_hal_write(up, xmit->buf, 1);
+ port->icount.tx++;
+ fifo_size--;
+ }
+
+ bytes = min((int)CIRC_CNT(xmit->head, xmit->tail,
+ UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
+ xmit->tail, UART_XMIT_SIZE));
+ if (!bytes) {
+ dev_dbg(up->port.dev, "%s 0 bytes return\n", __func__);
+
+ /* TODO: move to function */
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+
+ uart_write_wakeup(port);
+ return;
+ }
+
+ if (bytes > fifo_size) {
+ num = bytes / fifo_size + 1;
+ size = fifo_size;
+ rem = bytes % fifo_size;
+ } else {
+ num = 1;
+ size = bytes;
+ rem = bytes;
+ }
+
+ dev_dbg(up->port.dev, "%s num=%d size=%d rem=%d\n",
+ __func__, num, size, rem);
+
+ up->tx_dma_use = 1;
+
+ up->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+
+ sg_init_table(up->sg_tx_p, num); /* Initialize SG table */
+ sg = up->sg_tx_p;
+
+ for (i = 0; i < num; i++, sg++) {
+ if (i == (num - 1))
+ sg_set_page(sg, virt_to_page(xmit->buf),
+ rem, fifo_size * i);
+ else
+ sg_set_page(sg, virt_to_page(xmit->buf),
+ size, fifo_size * i);
+ }
+
+ sg = up->sg_tx_p;
+ nent = dma_map_sg(port->dev, sg, num, DMA_TO_DEVICE);
+ if (!nent) {
+ dev_err(up->port.dev, "%s:dma_map_sg Failed\n", __func__);
+ return;
+ }
+ up->dma_tx_nent = nent;
+
+ for (i = 0; i < nent; i++, sg++) {
+ sg->offset = (xmit->tail & (UART_XMIT_SIZE - 1)) +
+ fifo_size * i;
+ sg_dma_address(sg) = (sg_dma_address(sg) &
+ ~(UART_XMIT_SIZE - 1)) + sg->offset;
+ if (i == (nent - 1))
+ sg_dma_len(sg) = rem;
+ else
+ sg_dma_len(sg) = size;
+ }
+
+ desc = dmaengine_prep_slave_sg(up->tx_chan,
+ up->sg_tx_p, nent, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(up->port.dev, "%s:device_prep_slave_sg Failed\n",
+ __func__);
+ return;
+ }
+ dma_sync_sg_for_device(port->dev, up->sg_tx_p, nent, DMA_TO_DEVICE);
+ up->desc_tx = desc;
+ desc->callback = intel_cln_uart_dma_tx_complete;
+ desc->callback_param = up;
+
+ desc->tx_submit(desc);
+
+ dma_async_issue_pending(up->tx_chan);
+ up->tx_empty = 0;
+
+ return;
+}
+
+/**
+ * intel_cln_uart_start_tx
+ *
+ * @param arg: Pointer to intel_cln_uart
+ *
+ * Enable TX interrupts on the UART @ port
+ */
+static void intel_cln_uart_start_tx(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+
+ up->start_tx = 1;
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+/**
+ * intel_cln_uart_stop_tx
+ *
+ * @param arg: Pointer to intel_cln_uart
+ *
+ * Disable TX interrupts on the UART @ port
+ */
+static void intel_cln_uart_stop_tx(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+
+ up->start_tx = 0;
+ up->tx_dma_use = 0;
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+/**
+ * intel_cln_uart_tx
+ *
+ * @up: pointer to UART instance
+ *
+ * Transmit characters in non-DMA mode
+ */
+static void intel_cln_uart_tx(struct intel_cln_uart *up)
+{
+ struct uart_port *port = &up->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ int fifo_size;
+ int tx_size;
+ int size;
+ int tx_empty;
+
+ if (!up->start_tx) {
+ dev_info(up->port.dev, "%s:Tx isn't started. (%lu)\n",
+ __func__, jiffies);
+
+ /* TODO: move to function */
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+
+ up->tx_empty = 1;
+ return;
+ }
+
+ fifo_size = max((int)port->fifosize, 1);
+ tx_empty = 1;
+ if (pop_tx_x(up, xmit->buf)) {
+ intel_cln_uart_hal_write(up, xmit->buf, 1);
+ port->icount.tx++;
+ tx_empty = 0;
+ fifo_size--;
+ }
+ size = min(xmit->head - xmit->tail, fifo_size);
+ if (size < 0)
+ size = fifo_size;
+
+ tx_size = pop_tx(up, size);
+ if (tx_size > 0) {
+ port->icount.tx += tx_size;
+ tx_empty = 0;
+ }
+
+ up->tx_empty = tx_empty;
+
+ if (tx_empty) {
+ /* TODO: move to function */
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+
+ uart_write_wakeup(port);
+ }
+
+ return;
+}
+
+/**
+ * intel_cln_uart_stop_rx
+ *
+ * Stop RX on the given UART
+ */
+static void intel_cln_uart_stop_rx(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+
+ up->start_rx = 0;
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+}
+
+/**
+ * intel_cln_uart_handle_rx_to
+ *
+ * For FIFO RX timeout just read the data until nothing else to read
+ */
+static int intel_cln_uart_rx_to(struct intel_cln_uart *up)
+{
+ struct intel_cln_uart_buffer *buf;
+ int rx_size;
+ int ret;
+
+ if (!up->start_rx) {
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+ return 0;
+ }
+
+ buf = &up->rxbuf;
+ do {
+ rx_size = intel_cln_uart_hal_read(up, buf->buf_virt, buf->size);
+ ret = push_rx(up, buf->buf_virt, rx_size);
+ if (ret)
+ return 0;
+ } while (rx_size == buf->size);
+
+ return 0;
+}
+
+/**
+ * intel_cln_uart_dma_push_rx
+ *
+ * Take DMA RX data and push into the TTY layer
+ */
+static int intel_cln_uart_dma_push_rx(struct intel_cln_uart *up, int size)
+{
+ struct tty_struct *tty;
+ int room;
+ struct uart_port *port = &up->port;
+
+ port = &up->port;
+ tty = tty_port_tty_get(&port->state->port);
+ if (!tty) {
+ dev_dbg(up->port.dev, "%s:tty is busy now", __func__);
+ return 0;
+ }
+
+ room = tty_buffer_request_room(tty, size);
+
+ if (room < size)
+ dev_warn(up->dev, "Rx overrun: dropping %u bytes\n",
+ size - room);
+ if (!room)
+ return room;
+
+ tty_insert_flip_string(tty, sg_virt(&up->sg_rx), size);
+
+ port->icount.rx += room;
+ tty_kref_put(tty);
+
+ return room;
+}
+
+/**
+ * intel_cln_uart_dma_rx_complete
+ *
+ * Called when a UART RX interrupt happens - initiates a DMA transaction
+ */
+static void intel_cln_uart_dma_rx_complete(void *arg)
+{
+ struct intel_cln_uart *up = arg;
+ struct uart_port *port = &up->port;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+ int count;
+
+ if (!tty) {
+ dev_dbg(up->port.dev, "%s:tty is busy now", __func__);
+ return;
+ }
+
+ dma_sync_sg_for_cpu(up->dev, &up->sg_rx, 1, DMA_FROM_DEVICE);
+ count = intel_cln_uart_dma_push_rx(up, up->rx_trigger_level);
+ if (count)
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ async_tx_ack(up->desc_rx);
+}
+
+/**
+ * intel_cln_uart_dma_rx
+ *
+ * Called when a UART RX interrupt happens - initiates a DMA transaction
+ */
+void intel_cln_uart_dma_rx(struct intel_cln_uart *up)
+{
+ struct dma_async_tx_descriptor *desc;
+
+ sg_init_table(&up->sg_rx, 1); /* Initialize SG table */
+
+ sg_dma_len(&up->sg_rx) = up->rx_trigger_level;
+
+ sg_set_page(&up->sg_rx, virt_to_page(up->rxbuf.buf_virt),
+ sg_dma_len(&up->sg_rx), (unsigned long)up->rxbuf.buf_virt &
+ ~PAGE_MASK);
+
+ sg_dma_address(&up->sg_rx) = up->rxbuf.dma_addr;
+
+ desc = dmaengine_prep_slave_sg(up->rx_chan,
+ &up->sg_rx, 1, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ if (!desc)
+ return;
+
+ up->desc_rx = desc;
+ desc->callback = intel_cln_uart_dma_rx_complete;
+ desc->callback_param = up;
+ desc->tx_submit(desc);
+ dma_async_issue_pending(up->rx_chan);
+}
+
+/**
+ * check_modem_status
+ *
+ * @param up: pointer to UART descriptor
+ *
+ * Check modem status
+ */
+static inline void check_modem_status(struct intel_cln_uart *up)
+{
+ int status;
+
+ status = serial_in(up, UART_MSR);
+
+ if ((status & UART_MSR_ANY_DELTA) == 0)
+ return;
+
+ if (status & UART_MSR_TERI)
+ up->port.icount.rng++;
+ if (status & UART_MSR_DDSR)
+ up->port.icount.dsr++;
+ /* We may only get DDCD when HW init and reset */
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+ /* Will start/stop_tx accordingly */
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+
+ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+}
+
+/**
+ * intel_cln_uart_isr
+ *
+ * @param irq: interrupt identifier
+ * @param dev_id: pointer to the device structure data
+ *
+ * This handles the interrupt from one port. And calls into the DMAC interrupt
+ * handler directly which is what will run our asynchronous tx/rx DMA callbacks
+ *
+ */
+static void intel_cln_uart_err_ir(struct intel_cln_uart *up, unsigned int lsr)
+{
+ up->fcr = serial_in(up, UART_FCR);
+
+ /* Reset FIFO */
+ up->fcr |= UART_FCR_CLEAR_RCVR;
+ serial_out(up, UART_FCR, up->fcr);
+
+ if (lsr & UART_LSR_FIFOE)
+ dev_err(up->port.dev, "Error data in FIFO\n");
+
+ if (lsr & UART_LSR_FE)
+ dev_err(up->port.dev, "Framing Error\n");
+
+ if (lsr & UART_LSR_PE)
+ dev_err(up->port.dev, "Parity Error\n");
+
+ if (lsr & UART_LSR_OE)
+ dev_err(up->port.dev, "Overrun Error\n");
+}
+
+/**
+ * intel_cln_uart_isr
+ *
+ * @param irq: interrupt identifier
+ * @param dev_id: pointer to the device structure data
+ *
+ * This handles the interrupt from one port. And calls into the DMAC interrupt
+ * handler directly which is what will run our asynchronous tx/rx DMA callbacks
+ *
+ */
+static irqreturn_t intel_cln_uart_isr(int irq, void *dev_id)
+{
+ struct intel_cln_uart *up = dev_id;
+ unsigned int iid = 0, lsr, ret = IRQ_HANDLED;
+ unsigned long flags;
+
+ if(likely(up->mode & CLN_UART_MODE_MSI)){
+ /* TODO: see about moving this to the IO/APIC layer */
+ }
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ if (up->mode & CLN_UART_MODE_DMA) {
+ /* Run the ISR for the DMA directly */
+ intel_mid_dma_interrupt(irq, dev_id);
+ }
+
+ while ((iid = serial_in(up, UART_IIR)) > 1) {
+
+ switch (iid) {
+ case INTEL_CLN_UART_IIR_RLS:
+ /* Receiver Line Status */
+ lsr = serial_in(up, UART_LSR);
+ if (lsr & (UART_LSR_FIFOE | UART_LSR_FE |
+ UART_LSR_PE | UART_LSR_OE)) {
+ intel_cln_uart_err_ir(up, lsr);
+ }
+ break;
+ case INTEL_CLN_UART_IIR_RXD:
+ /* Received Data Ready */
+ if(up->mode & CLN_UART_MODE_DMA){
+ intel_cln_uart_dma_rx(up);
+ }else{
+ intel_cln_uart_rx_to(up);
+ }
+ break;
+ case INTEL_CLN_UART_IIR_TO:
+ /* Received Data Ready (FIFO Timeout) */
+ intel_cln_uart_rx_to(up);
+ break;
+ case INTEL_CLN_UART_IIR_THRE:
+ /* Transmitter Holding Register Empty */
+ if(up->mode & CLN_UART_MODE_DMA){
+ intel_cln_uart_dma_tx(up);
+ }else{
+ intel_cln_uart_tx(up);
+ }
+ break;
+ default:
+ /* Never junp to this label */
+ dev_err(up->port.dev, "%s:iid=%d (%lu)\n", __func__,
+ iid, jiffies);
+ ret = -1;
+ break;
+ }
+ }
+
+ check_modem_status(up);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ if(likely(up->mode & CLN_UART_MODE_MSI)){
+ /* TODO: see about moving this to the IO/APIC layer */
+ }
+
+ return ret;
+}
+
+static unsigned int intel_cln_uart_tx_empty(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ ret = up->tx_empty;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return ret;
+}
+
+static unsigned int intel_cln_uart_get_mctrl(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned char status;
+ unsigned int ret;
+
+ status = serial_in(up, UART_MSR);
+
+ ret = 0;
+ if (status & UART_MSR_DCD)
+ ret |= TIOCM_CAR;
+ if (status & UART_MSR_RI)
+ ret |= TIOCM_RNG;
+ if (status & UART_MSR_DSR)
+ ret |= TIOCM_DSR;
+ if (status & UART_MSR_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+static void intel_cln_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned char mcr = 0;
+
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ mcr |= up->mcr;
+
+ serial_out(up, UART_MCR, mcr);
+}
+
+static void intel_cln_uart_break_ctl(struct uart_port *port, int break_state)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned long flags;
+
+ pr_info("%s entry\n", __FUNCTION__);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(up, UART_LCR, up->lcr);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+/**
+ * intel_cln_uart_startup
+ *
+ * @port: Pointer to the uart port to be started
+ *
+ */
+static int intel_cln_uart_startup(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned long flags;
+
+ pr_info("%s entry\n", __FUNCTION__);
+
+ /*
+ * Clear the FIFO buffers and disable them.
+ * (they will be reenabled in set_termios())
+ */
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ serial_out(up, UART_FCR, 0);
+
+ /* Clear the interrupt registers. */
+ (void) serial_in(up, UART_LSR);
+ (void) serial_in(up, UART_RX);
+ (void) serial_in(up, UART_IIR);
+ (void) serial_in(up, UART_MSR);
+
+ /* Now, initialize the UART, default is 8n1 */
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ up->port.mctrl |= TIOCM_OUT2;
+ intel_cln_uart_set_mctrl(&up->port, up->port.mctrl);
+
+ /*
+ * Finally, enable interrupts. Note: Modem status interrupts
+ * are set via set_termios(), which will be occurring imminently
+ * anyway, so we don't enable them here.
+ */
+ if (!(up->mode & CLN_UART_MODE_DMA))
+ up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE;
+ else
+ up->ier = 0;
+ serial_out(up, UART_IER, up->ier);
+
+ /* And clear the interrupt registers again for luck. */
+ (void) serial_in(up, UART_LSR);
+ (void) serial_in(up, UART_RX);
+ (void) serial_in(up, UART_IIR);
+ (void) serial_in(up, UART_MSR);
+
+ up->start_rx = 1;
+
+ /* Coarse locking */
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return 0;
+}
+
+static void intel_cln_uart_shutdown(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned long flags;
+
+ pr_info("%s entry\n", __FUNCTION__);
+
+ /* Disable interrupts from this port */
+ up->ier = 0;
+ up->start_tx = up->start_rx = 0;
+ serial_out(up, UART_IER, 0);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ up->port.mctrl &= ~TIOCM_OUT2;
+ intel_cln_uart_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /* Disable break condition and FIFOs */
+ serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR |
+ UART_FCR_CLEAR_XMIT);
+ serial_out(up, UART_FCR, 0);
+
+ /* Unmap DMA */
+ if (up->mode & CLN_UART_MODE_DMA) {
+ dma_unmap_single(port->dev, up->txbuf.dma_addr,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+ dma_unmap_single(port->dev, up->rxbuf.dma_addr,
+ CLN_UART_DMA_BUF_SIZE, DMA_FROM_DEVICE);
+ }
+
+}
+
+/**
+ * intel_cln_uart_set_termios
+ *
+ * @param port: Pointer to UART structure
+ * @termios: Pointer to termios control structure
+ * @old: Pointer to old termios structure
+ *
+ * Set the UART into the mode specified by the termios structure
+ */
+static void
+intel_cln_uart_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ unsigned char cval;
+ unsigned long flags;
+ unsigned int baud, quot;
+// int div; TODO: on hardware
+
+ pr_info("%s up %p port %p termios %p ktermios %p\n",
+ __FUNCTION__, up, port, termios, old);
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ cval = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ cval = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ cval = UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ cval = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ cval |= UART_LCR_STOP;
+ if (termios->c_cflag & PARENB)
+ cval |= UART_LCR_PARITY;
+ if (!(termios->c_cflag & PARODD))
+ cval |= UART_LCR_EPAR;
+
+ termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 16);
+ quot = uart_get_divisor(port, baud);
+
+ pr_info("%s resulting baud rate was %d\n", __FUNCTION__, baud);
+
+ /* Init to FIFO enabled mode - RX-trig (FIFO-2) TX-trig TX-trig (FIFO/2) */
+ up->fcr = UART_FCR_ENABLE_FIFO | UART_FCR_T_TRIG_11 | UART_FCR_R_TRIG_11;
+ if (up->mode & CLN_UART_MODE_DMA)
+ up->fcr |= UART_FCR_DMA_SELECT;
+
+ up->rx_trigger_level = up->port.fifosize-2;
+ up->tx_trigger_level = up->port.fifosize/2;
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /* Update the per-port timeout */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (termios->c_iflag & INPCK)
+ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ up->port.read_status_mask |= UART_LSR_BI;
+
+ /* Characters to ignore */
+ up->port.ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ up->port.ignore_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_OE;
+ }
+
+ /* Ignore all characters if CREAD is not set */
+ if ((termios->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= UART_LSR_DR;
+
+ /*
+ * CTS flow control flag and modem status interrupts, disable
+ * MSI by default
+ */
+ up->ier &= ~UART_IER_MSI;
+ if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+ up->ier |= UART_IER_MSI;
+
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE | UART_MCR_RTS;
+ else
+ up->mcr &= ~UART_MCR_AFE;
+
+ serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
+ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
+ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
+ serial_out(up, UART_LCR, cval); /* reset DLAB */
+ up->lcr = cval; /* Save LCR */
+
+ intel_cln_uart_set_mctrl(&up->port, up->port.mctrl);
+ up->fcr = 0;
+ serial_out(up, UART_FCR, up->fcr);
+
+ /* Set IER state */
+ serial_out(up, UART_IER, up->ier);
+
+ /* Unlock spinlock */
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void
+intel_cln_uart_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+}
+
+static void intel_cln_uart_release_port(struct uart_port *port)
+{
+}
+
+static int intel_cln_uart_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+static void intel_cln_uart_config_port(struct uart_port *port, int flags)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ up->port.type = PORT_MFD;
+}
+
+/**
+ * intel_cln_uart_verify_port
+ *
+ * @param port: Pointer to UART descriptor
+ * @param ser: Serail configuration structure
+ *
+ * Sets the port into hi-speed/lo-speed mode
+ */
+static int
+intel_cln_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+
+ if (ser->flags & UPF_LOW_LATENCY) {
+ dev_info(up->port.dev,
+ "CLN UART : Use PIO Mode (without DMA)\n");
+ up->mode &= ~CLN_UART_MODE_DMA;
+ ser->flags &= ~UPF_LOW_LATENCY;
+ } else {
+ up->mode |= CLN_UART_MODE_DMA;
+ dev_info(up->port.dev, "CLN UART : Use DMA Mode\n");
+ }
+
+ return 0;
+}
+
+/**
+ * intel_cln_uart_type
+ *
+ * @param port: Pointer to UART descriptor
+ *
+ * Returns the type of the port
+ */
+static const char *
+intel_cln_uart_type(struct uart_port *port)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+ return up->name;
+}
+
+/* Mainly for uart console use */
+static struct uart_driver intel_cln_uart_driver;
+
+#ifdef CONFIG_INTEL_CLN_UART_CONSOLE
+
+static struct intel_cln_uart *intel_cln_uart_ports[2];
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/* Wait for transmitter & holding register to empty */
+static inline void wait_for_xmitr(struct intel_cln_uart *up)
+{
+ unsigned int status, tmout = 1000;
+
+ /* Wait up to 1ms for the character to be sent. */
+ do {
+ status = serial_in(up, UART_LSR);
+
+ if (status & UART_LSR_BI)
+ up->lsr_break_flag = UART_LSR_BI;
+
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while (!(status & BOTH_EMPTY));
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ tmout = 1000000;
+ while (--tmout &&
+ ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
+ udelay(1);
+ }
+}
+
+static void intel_cln_uart_console_putchar(struct uart_port *port, int ch)
+{
+ struct intel_cln_uart *up =
+ container_of(port, struct intel_cln_uart, port);
+
+ wait_for_xmitr(up);
+ serial_out(up, UART_TX, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void
+intel_cln_uart_console_write(struct console *co, const char *s, unsigned int count)
+{
+ struct intel_cln_uart *up = &intel_cln_uart_ports[co->index];
+ unsigned long flags;
+ unsigned int ier;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
+
+ /* First save the IER then disable the interrupts */
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
+
+ uart_console_write(&up->port, s, count, intel_cln_uart_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up);
+ serial_out(up, UART_IER, ier);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
+}
+
+static struct console intel_cln_uart_console;
+
+static int __init
+intel_cln_uart_console_setup(struct console *co, char *options)
+{
+ struct intel_cln_uart *up;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index == -1 || co->index >= intel_cln_uart_driver.nr)
+ co->index = 0;
+ up = intel_cln_uart_ports[co->index];
+ if (!up)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+
+static struct uart_driver intel_cln_uart_driver;
+static struct console intel_cln_uart_console = {
+ .name = "ttyCLN",
+ .write = intel_cln_uart_console_write,
+ .device = uart_console_device,
+ .setup = intel_cln_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &intel_cln_uart_driver,
+};
+
+#define INTEL_CLN_UART_CONSOLE (&intel_cln_uart_console)
+#else
+#define INTEL_CLN_UART_CONSOLE NULL
+#endif
+
+static struct uart_driver intel_cln_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = KBUILD_MODNAME,
+ .dev_name = CLN_UART_DRIVER_DEVICE,
+ .major = TTY_MAJOR,
+ .minor = 129,
+ .nr = CLN_UART_MAX_INSTANCES,
+ .cons = INTEL_CLN_UART_CONSOLE,
+};
+
+static struct uart_ops intel_cln_uart_ops = {
+ .tx_empty = intel_cln_uart_tx_empty,
+ .set_mctrl = intel_cln_uart_set_mctrl,
+ .get_mctrl = intel_cln_uart_get_mctrl,
+ .stop_tx = intel_cln_uart_stop_tx,
+ .start_tx = intel_cln_uart_start_tx,
+ .stop_rx = intel_cln_uart_stop_rx,
+ .enable_ms = intel_cln_uart_enable_ms,
+ .break_ctl = intel_cln_uart_break_ctl,
+ .startup = intel_cln_uart_startup,
+ .shutdown = intel_cln_uart_shutdown,
+ .set_termios = intel_cln_uart_set_termios,
+ .pm = intel_cln_uart_pm,
+ .type = intel_cln_uart_type,
+ .release_port = intel_cln_uart_release_port,
+ .request_port = intel_cln_uart_request_port,
+ .config_port = intel_cln_uart_config_port,
+ .verify_port = intel_cln_uart_verify_port,
+};
+
+/**
+ * intel_cln_dma_chan_filter
+ *
+ * Simple descriptor disjunct function
+ */
+static bool intel_cln_dma_chan_filter(struct dma_chan * chan, void *param)
+{
+// struct intel_mid_dma_slave *dws = param;
+
+// pr_info("%s compare device %p to %p\n", __FUNCTION__, dws->dma_dev, chan->device->dev);
+
+ //return dws->dmac && (&dws->dmac->dev == chan->device->dev);
+ return 1; // TBD
+}
+
+/**
+ * intel_cln_uart_probe
+ *
+ * @param dev: the PCI device matching
+ * @param id: entry in the match table
+ * @return 0
+ *
+ * Callback from PCI layer when dev/vendor ids match.
+ * Sets up necessary resources
+ */
+static int intel_cln_uart_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ dma_cap_mask_t mask;
+ int ret = 0;
+ struct intel_cln_uart *up = NULL;
+ unsigned long flags = 0, len = 0;
+
+ printk(KERN_INFO "Intel Clanton UART-DMA (ID: %04x:%04x)\n",
+ pdev->vendor, pdev->device);
+
+ /* Driver desc */
+ up = kzalloc(sizeof(struct intel_cln_uart), GFP_KERNEL);
+ if (up == NULL){
+ ret = -ENOMEM;
+ goto err;
+ }
+ up->mid_dma.pdev = pci_dev_get(pdev);
+
+ ret = pci_enable_device(pdev);
+ if (ret){
+ goto err;
+ }
+
+ /* Attempt MSI enable */
+ //if(pci_enable_msi(pdev)){
+ if(1){
+ dev_warn(&pdev->dev, "MSI enable fail\n");
+ flags = IRQF_SHARED;
+ }else{
+ /*
+ * MSI enable good - set IRQ type to level. This seems wrong
+ * since PCI is an edge triggered interrupt system - but, the IP
+ * block connected to the bridge is level triggered. Setting the
+ * IRQ type to LEVEL_HIGH will trigger the
+ * io_apic->irq_mask()/unmask() functions to be automagically
+ * called by the kernel - which saves us from having to do nasty
+ * PCI config space writes explicitely in the ISR - kernel
+ * entry/exit functions will do that for us
+ */
+ irq_set_irq_type(pdev->irq, IRQ_TYPE_LEVEL_HIGH);
+ up->mode |= CLN_UART_MODE_MSI;
+ }
+
+ /* DMA hook */
+ if(dma_enable == true){
+ up->mode |= CLN_UART_MODE_DMA;
+ }
+ up->mode = 0;
+
+ /* Hook an IRQ - in whichever mode */
+ ret = request_irq(pdev->irq, intel_cln_uart_isr, flags, KBUILD_MODNAME,
+ up);
+ if (ret) {
+ dev_err(&pdev->dev, "can not get IRQ\n");
+ goto err_dev;
+ }
+
+ /* Add debugfs entries */
+ intel_cln_uart_debugfs_init(up);
+
+ /* Init spinlock */
+ spin_lock_init(&up->lock);
+
+ /* UART regs on BAR0 */
+ up->port.mapbase = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+ up->port.membase = ioremap_nocache(up->port.mapbase, len);
+ if(up->port.membase == NULL){
+ ret = -ENODEV;
+ goto err_dev;
+ }
+
+ /* Init DMA driver */
+ up->mid_dma.max_chan = CLN_UART_DMA_CHANNELS; /* Max channels */
+ up->mid_dma.chan_base = 0; /* Index start */
+ up->mid_dma.block_size = CLN_UART_FIFO_LEN; /* MAX DMA block */
+ up->mid_dma.pimr_mask = 0; /* Per int regs bool */
+
+ ret = intel_cln_dma_probe(pdev, &up->mid_dma);
+ if(ret != 0){
+ dev_err(&pdev->dev, "Unable to init DMA sub-system\n");
+ goto err_dev;
+ }
+
+ /* Request DMA channels TODO: move to startup() once debugged on hw */
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ up->rx_chan = dma_request_channel(mask, intel_cln_dma_chan_filter, &up->dmas_rx);
+ if(up->rx_chan == NULL){
+ dev_err(&pdev->dev, "Unable to hook DMA RX channel\n");
+ goto err_bar0;
+ };
+ up->dmas_rx.hs_mode = LNW_DMA_SW_HS;
+ up->dmas_rx.cfg_mode = LNW_DMA_PER_TO_MEM;
+
+ up->tx_chan = dma_request_channel(mask, intel_cln_dma_chan_filter, &up->dmas_tx);
+ if(up->tx_chan == NULL){
+ dev_err(&pdev->dev, "Unable to hook DMA RX channel\n");
+ goto err_bar0;
+ };
+ up->dmas_tx.hs_mode = LNW_DMA_SW_HS;
+ up->dmas_tx.cfg_mode = LNW_DMA_MEM_TO_PER;
+
+ dev_info(&pdev->dev, "using %s for DMA RX %s for DMA TX\n",
+ dev_name(&up->rx_chan->dev->device), dev_name(&up->tx_chan->dev->device));
+
+ /* Enumerate port */
+ up->irq = pdev->irq;
+ up->dev = &pdev->dev;
+ up->tx_empty = 1;
+
+// up->port_type = PORT_MAX_8250 + 10; /* TODO: add to include/linux/serial_core.h */
+ up->uartclk = CLN_UART_DEFAULT_UARTCLK;
+ up->port.uartclk = up->uartclk;
+ up->port.dev = &pdev->dev;
+ up->port.irq = pdev->irq;
+ up->port.iotype = UPIO_MEM;
+ up->port.ops = &intel_cln_uart_ops;
+ up->port.flags = UPF_BOOT_AUTOCONF;
+ up->port.fifosize = 16;
+ up->port.line = pdev->dev.id;
+ snprintf(up->name, sizeof(up->name), "cln_port%d", intel_cln_uart_port_ct++);
+
+ /* Get Consistent memory for DMA TODO: move to startup() once debugged on hw */
+ up->rxbuf.buf_virt = dma_alloc_coherent(up->port.dev, up->port.fifosize,
+ &up->rxbuf.dma_addr, GFP_KERNEL);
+ up->rxbuf.size = up->port.fifosize;
+
+ /* Add UART */
+ uart_add_one_port(&intel_cln_uart_driver, &up->port);
+ pci_set_drvdata(pdev, up);
+
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_allow(&pdev->dev);
+
+ return 0;
+
+err_bar0:
+ iounmap(up->port.membase);
+err_dev:
+ free_irq(up->irq, NULL);
+ pci_disable_device(pdev);
+err:
+ kfree(up);
+ return ret;
+}
+
+/**
+ * uart_remove
+ *
+ * @param pdev: PCI device
+ * @return nothing
+ *
+ * Callback from PCI sub-system upon PCI dev removal
+ */
+static void intel_cln_uart_remove(struct pci_dev *pdev)
+{
+ struct intel_cln_uart *up = pci_get_drvdata(pdev);
+ if (!up)
+ return;
+
+ /* Shutdown DMA */
+ intel_cln_dma_remove(pdev, &up->mid_dma);
+
+ /* TODO: move to remove() when h/w proved out */
+ if (up->tx_chan) {
+ dma_release_channel(up->tx_chan);
+ up->tx_chan = NULL;
+ }
+ if (up->rx_chan) {
+ dma_release_channel(up->rx_chan);
+ up->rx_chan = NULL;
+ }
+
+ if (sg_dma_address(&up->sg_rx))
+ dma_free_coherent(up->port.dev, up->port.fifosize,
+ sg_virt(&up->sg_rx),
+ sg_dma_address(&up->sg_rx));
+
+ /* Remove UART */
+ uart_remove_one_port(&intel_cln_uart_driver, &up->port);
+
+ pci_set_drvdata(pdev, NULL);
+ free_irq(up->irq, NULL);
+ pci_disable_device(pdev);
+
+ /* Remove debugfs entries */
+ intel_cln_uart_debugfs_remove(up);
+
+ kfree(up);
+}
+
+#ifdef CONFIG_PM
+
+static int intel_cln_uart_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct intel_cln_uart *up = pci_get_drvdata(pdev);
+
+ /* Suspend DMA regs */
+ intel_cln_dma_suspend(&up->mid_dma);
+
+
+ /* Suspend UART */
+ uart_suspend_port(&intel_cln_uart_driver, &up->port);
+
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+static int intel_cln_uart_resume(struct pci_dev *pdev)
+{
+ struct intel_cln_uart *up = pci_get_drvdata(pdev);
+ int ret;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ ret = pci_enable_device(pdev);
+ if (ret){
+ dev_warn(&pdev->dev,
+ "INTEL_CLN_UART: can't re-enable device, try to continue\n");
+ }
+
+ uart_resume_port(&intel_cln_uart_driver, &up->port);
+
+ /* Resume DMA regs */
+ intel_cln_dma_resume(&up->mid_dma);
+
+ return 0;
+}
+
+#else
+
+#define intel_cln_uart_suspend NULL
+#define intel_cln_uart_resume NULL
+
+#endif
+
+struct pci_device_id intel_cln_uart_ids[] = {
+ { PCI_VDEVICE(INTEL, 0x0936), 0},
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, intel_cln_uart_ids);
+
+/* PCI callbacks */
+static struct pci_driver intel_cln_uart_pci_desc = {
+ .name = "intel_cln_uart",
+ .id_table = intel_cln_uart_ids,
+ .probe = intel_cln_uart_probe,
+ .remove = intel_cln_uart_remove,
+ .suspend = intel_cln_uart_suspend,
+ .resume = intel_cln_uart_resume,
+};
+
+/**
+ * intel_cln_uart_init
+ *
+ * Module entry point
+ */
+static int __init intel_cln_uart_init(void)
+{
+ int ret;
+
+ /* register as UART driver */
+ ret = uart_register_driver(&intel_cln_uart_driver);
+ if (ret < 0)
+ return ret;
+
+ /* register as PCI driver */
+ ret = pci_register_driver(&intel_cln_uart_pci_desc);
+ if (ret < 0)
+ uart_unregister_driver(&intel_cln_uart_driver);
+
+ return ret;
+}
+
+/**
+ * intel_cln_uart_exit
+ *
+ * Module exit
+ */
+static void __exit intel_cln_uart_exit(void)
+{
+ pci_unregister_driver(&intel_cln_uart_pci_desc);
+}
+
+MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Clanton UART-DMA driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_init(intel_cln_uart_init);
+module_exit(intel_cln_uart_exit);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index da9fde8..6b20fd6 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2906,9 +2906,9 @@ void do_SAK(struct tty_struct *tty)
EXPORT_SYMBOL(do_SAK);
-static int dev_match_devt(struct device *dev, void *data)
+static int dev_match_devt(struct device *dev, const void *data)
{
- dev_t *devt = data;
+ const dev_t *devt = data;
return dev->devt == *devt;
}
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index c578229..78f1be2 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -934,17 +934,17 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
* race with the set_ldisc code path.
*/
- tty_lock_pair(tty, o_tty);
tty_ldisc_halt(tty);
- tty_ldisc_flush_works(tty);
- if (o_tty) {
+ if (o_tty)
tty_ldisc_halt(o_tty);
+
+ tty_ldisc_flush_works(tty);
+ if (o_tty)
tty_ldisc_flush_works(o_tty);
- }
+ tty_lock_pair(tty, o_tty);
/* This will need doing differently if we need to lock */
tty_ldisc_kill(tty);
-
if (o_tty)
tty_ldisc_kill(o_tty);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 14625fd..21222a8 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -439,7 +439,7 @@ config USB_GOKU
gadget drivers to also be dynamically linked.
config USB_EG20T
- tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
+ tristate "Intel CLN/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
depends on PCI
help
This is a USB device driver for EG20T PCH.
@@ -459,7 +459,8 @@ config USB_EG20T
ML7831 is for general purpose use.
ML7213/ML7831 is companion chip for Intel Atom E6xx series.
ML7213/ML7831 is completely compatible for Intel EG20T PCH.
-
+
+ This driver can be used with Intel's Clanton SOC platform
#
# LAST -- dummy/emulated controller
#
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 6490c00..848c502 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -6,6 +6,7 @@
* the Free Software Foundation; version 2 of the License.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <asm/cln.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -18,6 +19,10 @@
#include <linux/gpio.h>
#include <linux/irq.h>
+static unsigned int enable_msi = 1;
+module_param(enable_msi, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_msi, "Enable PCI MSI mode");
+
/* GPIO port for VBUS detecting */
static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */
@@ -343,6 +348,7 @@ struct pch_vbus_gpio_data {
* @setup_data: Received setup data
* @phys_addr: of device memory
* @base_addr: for mapped device memory
+ * @bar: Indicates which PCI BAR for USB regs
* @irq: IRQ line for the device
* @cfg_data: current cfg, intf, and alt in use
* @vbus_gpio: GPIO informaton for detecting VBUS
@@ -371,13 +377,16 @@ struct pch_udc_dev {
struct usb_ctrlrequest setup_data;
unsigned long phys_addr;
void __iomem *base_addr;
+ unsigned bar;
unsigned irq;
struct pch_udc_cfg_data cfg_data;
struct pch_vbus_gpio_data vbus_gpio;
};
-#define PCH_UDC_PCI_BAR 1
+#define PCH_UDC_PCI_BAR_CLANTON 0
+#define PCH_UDC_PCI_BAR_EG20T 1
#define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808
+#define PCI_DEVICE_ID_INTEL_CLANTON_UDC 0x0939
#define PCI_VENDOR_ID_ROHM 0x10DB
#define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D
#define PCI_DEVICE_ID_ML7831_IOH_UDC 0x8808
@@ -2779,55 +2788,70 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev)
{
struct pch_udc_dev *dev = (struct pch_udc_dev *) pdev;
u32 dev_intr, ep_intr;
- int i;
-
- dev_intr = pch_udc_read_device_interrupts(dev);
- ep_intr = pch_udc_read_ep_interrupts(dev);
-
- /* For a hot plug, this find that the controller is hung up. */
- if (dev_intr == ep_intr)
- if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
- dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
- /* The controller is reset */
- pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
- return IRQ_HANDLED;
+ int i, events = 0;
+
+ mask_pvm(dev->pdev);
+ do {
+ events = 0;
+ dev_intr = pch_udc_read_device_interrupts(dev);
+ ep_intr = pch_udc_read_ep_interrupts(dev);
+
+ /* For a hot plug, this find that the controller is hung up. */
+ if (dev_intr == ep_intr)
+ if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
+ dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
+ /* The controller is reset */
+ pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+ unmask_pvm(dev->pdev);
+ return IRQ_HANDLED;
+ }
+ if (dev_intr){
+ /* Clear device interrupts */
+ pch_udc_write_device_interrupts(dev, dev_intr);
+ events = 1;
}
- if (dev_intr)
- /* Clear device interrupts */
- pch_udc_write_device_interrupts(dev, dev_intr);
- if (ep_intr)
- /* Clear ep interrupts */
- pch_udc_write_ep_interrupts(dev, ep_intr);
- if (!dev_intr && !ep_intr)
- return IRQ_NONE;
- spin_lock(&dev->lock);
- if (dev_intr)
- pch_udc_dev_isr(dev, dev_intr);
- if (ep_intr) {
- pch_udc_read_all_epstatus(dev, ep_intr);
- /* Process Control In interrupts, if present */
- if (ep_intr & UDC_EPINT_IN_EP0) {
- pch_udc_svc_control_in(dev);
- pch_udc_postsvc_epinters(dev, 0);
+ if (ep_intr){
+ /* Clear ep interrupts */
+ pch_udc_write_ep_interrupts(dev, ep_intr);
+ events = 1;
}
- /* Process Control Out interrupts, if present */
- if (ep_intr & UDC_EPINT_OUT_EP0)
- pch_udc_svc_control_out(dev);
- /* Process data in end point interrupts */
- for (i = 1; i < PCH_UDC_USED_EP_NUM; i++) {
- if (ep_intr & (1 << i)) {
- pch_udc_svc_data_in(dev, i);
- pch_udc_postsvc_epinters(dev, i);
+ if (!dev_intr && !ep_intr){
+ unmask_pvm(dev->pdev);
+ return IRQ_NONE;
+ }
+ spin_lock(&dev->lock);
+ if (dev_intr){
+ pch_udc_dev_isr(dev, dev_intr);
+ }
+ if (ep_intr) {
+ pch_udc_read_all_epstatus(dev, ep_intr);
+ /* Process Control In interrupts, if present */
+ if (ep_intr & UDC_EPINT_IN_EP0) {
+ pch_udc_svc_control_in(dev);
+ pch_udc_postsvc_epinters(dev, 0);
+ }
+ /* Process Control Out interrupts, if present */
+ if (ep_intr & UDC_EPINT_OUT_EP0)
+ pch_udc_svc_control_out(dev);
+ /* Process data in end point interrupts */
+ for (i = 1; i < PCH_UDC_USED_EP_NUM; i++) {
+ if (ep_intr & (1 << i)) {
+ pch_udc_svc_data_in(dev, i);
+ pch_udc_postsvc_epinters(dev, i);
+ }
}
+ /* Process data out end point interrupts */
+ for (i = UDC_EPINT_OUT_SHIFT + 1;
+ i < (UDC_EPINT_OUT_SHIFT + PCH_UDC_USED_EP_NUM);
+ i++)
+ if (ep_intr & (1 << i))
+ pch_udc_svc_data_out(dev,
+ i - UDC_EPINT_OUT_SHIFT);
}
- /* Process data out end point interrupts */
- for (i = UDC_EPINT_OUT_SHIFT + 1; i < (UDC_EPINT_OUT_SHIFT +
- PCH_UDC_USED_EP_NUM); i++)
- if (ep_intr & (1 << i))
- pch_udc_svc_data_out(dev, i -
- UDC_EPINT_OUT_SHIFT);
- }
- spin_unlock(&dev->lock);
+ spin_unlock(&dev->lock);
+ }while(events == 1);
+ unmask_pvm(dev->pdev);
+
return IRQ_HANDLED;
}
@@ -3108,7 +3132,7 @@ static void pch_udc_remove(struct pci_dev *pdev)
iounmap(dev->base_addr);
if (dev->mem_region)
release_mem_region(dev->phys_addr,
- pci_resource_len(pdev, PCH_UDC_PCI_BAR));
+ pci_resource_len(pdev, dev->bar));
if (dev->active)
pci_disable_device(pdev);
if (dev->registered)
@@ -3184,9 +3208,16 @@ static int pch_udc_probe(struct pci_dev *pdev,
dev->active = 1;
pci_set_drvdata(pdev, dev);
+ /* Determine BAR based on PCI ID */
+ if(id->device == PCI_DEVICE_ID_INTEL_CLANTON_UDC){
+ dev->bar = PCH_UDC_PCI_BAR_CLANTON;
+ }else {
+ dev->bar = PCH_UDC_PCI_BAR_EG20T;
+ }
+
/* PCI resource allocation */
- resource = pci_resource_start(pdev, 1);
- len = pci_resource_len(pdev, 1);
+ resource = pci_resource_start(pdev, dev->bar);
+ len = pci_resource_len(pdev, dev->bar);
if (!request_mem_region(resource, len, KBUILD_MODNAME)) {
dev_err(&pdev->dev, "%s: pci device used already\n", __func__);
@@ -3213,6 +3244,12 @@ static int pch_udc_probe(struct pci_dev *pdev,
retval = -ENODEV;
goto finished;
}
+
+ pci_set_master(pdev);
+ if (enable_msi == 1){
+ pci_enable_msi(pdev);
+ }
+
if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
dev)) {
dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
@@ -3223,7 +3260,7 @@ static int pch_udc_probe(struct pci_dev *pdev,
dev->irq = pdev->irq;
dev->irq_registered = 1;
- pci_set_master(pdev);
+
pci_try_set_mwi(pdev);
/* device struct setup */
@@ -3261,6 +3298,11 @@ finished:
static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
{
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CLANTON_UDC),
+ .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+ .class_mask = 0xffffffff,
+ },
+ {
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC),
.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
.class_mask = 0xffffffff,
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 44752f5..e02a4c9 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -127,6 +127,15 @@ static unsigned n_ports = 1;
module_param(n_ports, uint, 0);
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
+static __u16 vendor = GS_VENDOR_ID;
+module_param(vendor, ushort, 0);
+MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
+ __MODULE_STRING(GS_VENDOR_ID)")");
+
+static __u16 product = 0;
+module_param(product, ushort, 0);
+MODULE_PARM_DESC(product, "User specified product ID");
+
/*-------------------------------------------------------------------------*/
static int __init serial_bind_config(struct usb_configuration *c)
@@ -172,6 +181,14 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
status = strings_dev[STRING_DESCRIPTION_IDX].id;
serial_config_driver.iConfiguration = status;
+ /* Allow command line over-ride to set specific vendor/device id */
+ if (vendor != GS_VENDOR_ID)
+ device_desc.idVendor = cpu_to_le16(vendor);
+ if (product != 0)
+ device_desc.idProduct = cpu_to_le16(product);
+ pr_info("g_serial: Vendor 0x%04x Product 0x%04x\n",
+ device_desc.idVendor, device_desc.idProduct);
+
if (gadget_is_otg(cdev->gadget)) {
serial_config_driver.descriptors = otg_desc;
serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
@@ -201,6 +218,7 @@ static __refdata struct usb_composite_driver gserial_driver = {
.bind = gs_bind,
};
+static int bCfgVal;
static int __init init(void)
{
/* We *could* export two configs; that'd be much cleaner...
@@ -208,19 +226,19 @@ static int __init init(void)
*/
if (use_acm) {
serial_config_driver.label = "CDC ACM config";
- serial_config_driver.bConfigurationValue = 2;
+ serial_config_driver.bConfigurationValue = ++bCfgVal;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_PRODUCT_ID);
} else if (use_obex) {
serial_config_driver.label = "CDC OBEX config";
- serial_config_driver.bConfigurationValue = 3;
+ serial_config_driver.bConfigurationValue = ++bCfgVal;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
} else {
serial_config_driver.label = "Generic Serial config";
- serial_config_driver.bConfigurationValue = 1;
+ serial_config_driver.bConfigurationValue = ++bCfgVal;
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idProduct =
cpu_to_le16(GS_PRODUCT_ID);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 170b939..e34f67c 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -50,6 +50,10 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
if (!retval)
ehci_dbg(ehci, "MWI active\n");
+ /* Reset the threshold limit */
+ if(unlikely(usb_is_intel_cln(pdev)))
+ usb_set_cln_bulk_thresh(pdev);
+
return 0;
}
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 4c338ec..a1bee71 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -722,6 +722,48 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
return -ETIMEDOUT;
}
+#define PCI_DEVICE_ID_INTEL_CLN_SOC 0x0939
+bool usb_is_intel_cln(struct pci_dev *pdev)
+{
+ return pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_CLN_SOC;
+
+}
+EXPORT_SYMBOL_GPL(usb_is_intel_cln);
+
+#define EHCI_INSNREG01 0x84
+#define EHCI_INSNREG01_THRESH 0x007F007F /* Threshold value */
+void usb_set_cln_bulk_thresh(struct pci_dev *pdev)
+{
+ void __iomem *base, *op_reg_base;
+ u8 cap_length;
+ u32 val;
+
+ if (!mmio_resource_enabled(pdev, 0))
+ return;
+
+ base = pci_ioremap_bar(pdev, 0);
+ if (base == NULL)
+ return;
+
+ cap_length = readb(base);
+ op_reg_base = base + cap_length;
+
+ val = readl(op_reg_base + EHCI_INSNREG01);
+ dev_printk(KERN_INFO, &pdev->dev, "INSNREG01 is 0x%08x\n", val);
+
+ val = EHCI_INSNREG01_THRESH;
+
+ writel(val, op_reg_base + EHCI_INSNREG01);
+
+ val = readl(op_reg_base + EHCI_INSNREG01);
+ dev_printk(KERN_INFO, &pdev->dev, "INSNREG01 is 0x%08x\n", val);
+
+ iounmap(base);
+
+}
+EXPORT_SYMBOL_GPL(usb_set_cln_bulk_thresh);
+
#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31
#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 7f69a39..3bca8f7 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -9,6 +9,8 @@ void usb_amd_dev_put(void);
void usb_amd_quirk_pll_disable(void);
void usb_amd_quirk_pll_enable(void);
bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
+bool usb_is_intel_cln(struct pci_dev *pdev);
+void usb_set_cln_bulk_thresh(struct pci_dev *pdev);
void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
#else
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c
index 4d688c7..3eca6ce 100644
--- a/drivers/uwb/lc-rc.c
+++ b/drivers/uwb/lc-rc.c
@@ -40,9 +40,9 @@
#include "uwb-internal.h"
-static int uwb_rc_index_match(struct device *dev, void *data)
+static int uwb_rc_index_match(struct device *dev, const void *data)
{
- int *index = data;
+ const int *index = data;
struct uwb_rc *rc = dev_get_drvdata(dev);
if (rc->index == *index)
@@ -334,9 +334,9 @@ void uwb_rc_rm(struct uwb_rc *rc)
}
EXPORT_SYMBOL_GPL(uwb_rc_rm);
-static int find_rc_try_get(struct device *dev, void *data)
+static int find_rc_try_get(struct device *dev, const void *data)
{
- struct uwb_rc *target_rc = data;
+ const struct uwb_rc *target_rc = data;
struct uwb_rc *rc = dev_get_drvdata(dev);
if (rc == NULL) {
@@ -386,9 +386,9 @@ static inline struct uwb_rc *uwb_rc_get(struct uwb_rc *rc)
return rc;
}
-static int find_rc_grandpa(struct device *dev, void *data)
+static int find_rc_grandpa(struct device *dev, const void *data)
{
- struct device *grandpa_dev = data;
+ const struct device *grandpa_dev = data;
struct uwb_rc *rc = dev_get_drvdata(dev);
if (rc->uwb_dev.dev.parent->parent == grandpa_dev) {
@@ -419,7 +419,7 @@ struct uwb_rc *uwb_rc_get_by_grandpa(const struct device *grandpa_dev)
struct device *dev;
struct uwb_rc *rc = NULL;
- dev = class_find_device(&uwb_rc_class, NULL, (void *)grandpa_dev,
+ dev = class_find_device(&uwb_rc_class, NULL, grandpa_dev,
find_rc_grandpa);
if (dev)
rc = dev_get_drvdata(dev);
@@ -432,9 +432,9 @@ EXPORT_SYMBOL_GPL(uwb_rc_get_by_grandpa);
*
* @returns the pointer to the radio controller, properly referenced
*/
-static int find_rc_dev(struct device *dev, void *data)
+static int find_rc_dev(struct device *dev, const void *data)
{
- struct uwb_dev_addr *addr = data;
+ const struct uwb_dev_addr *addr = data;
struct uwb_rc *rc = dev_get_drvdata(dev);
if (rc == NULL) {
@@ -453,8 +453,7 @@ struct uwb_rc *uwb_rc_get_by_dev(const struct uwb_dev_addr *addr)
struct device *dev;
struct uwb_rc *rc = NULL;
- dev = class_find_device(&uwb_rc_class, NULL, (void *)addr,
- find_rc_dev);
+ dev = class_find_device(&uwb_rc_class, NULL, addr, find_rc_dev);
if (dev)
rc = dev_get_drvdata(dev);
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 20ca766..8265ccc 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -65,6 +65,7 @@ struct device_node;
* @direction_output: configures signal "offset" as output, or returns error
* @set_debounce: optional hook for setting debounce time for specified gpio in
* interrupt triggered gpio chips
+ * @set_drive: optional hook for setting the drive signal for "offset"
* @set: assigns output value for signal "offset"
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
* implementation may not sleep
@@ -113,6 +114,8 @@ struct gpio_chip {
unsigned offset, int value);
int (*set_debounce)(struct gpio_chip *chip,
unsigned offset, unsigned debounce);
+ int (*set_drive)(struct gpio_chip *chip,
+ unsigned offset, unsigned mode);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
@@ -172,6 +175,7 @@ extern int gpio_direction_input(unsigned gpio);
extern int gpio_direction_output(unsigned gpio, int value);
extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
+extern int gpio_set_drive(unsigned gpio, unsigned mode);
extern int gpio_get_value_cansleep(unsigned gpio);
extern void gpio_set_value_cansleep(unsigned gpio, int value);
diff --git a/include/linux/device.h b/include/linux/device.h
index 43dcda9..13de5ee 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -395,8 +395,8 @@ extern int class_for_each_device(struct class *class, struct device *start,
void *data,
int (*fn)(struct device *dev, void *data));
extern struct device *class_find_device(struct class *class,
- struct device *start, void *data,
- int (*match)(struct device *, void *));
+ struct device *start, const void *data,
+ int (*match)(struct device *, const void *));
struct class_attribute {
struct attribute attr;
diff --git a/include/linux/efi-bgrt.h b/include/linux/efi-bgrt.h
index 051b21f..165426b 100644
--- a/include/linux/efi-bgrt.h
+++ b/include/linux/efi-bgrt.h
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
void efi_bgrt_init(void);
+bool efi_bgrt_probe(void);
/* The BGRT data itself; only valid if bgrt_image != NULL. */
extern void *bgrt_image;
@@ -15,6 +16,7 @@ extern struct acpi_table_bgrt *bgrt_tab;
#else /* !CONFIG_ACPI_BGRT */
static inline void efi_bgrt_init(void) {}
+static inline bool efi_bgrt_probe(void) { return false; }
#endif /* !CONFIG_ACPI_BGRT */
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index bfe6656..cadd9d2 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -27,6 +27,11 @@
#define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT)
#define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+#define GPIOF_DRIVE_PULLUP (1 << 6)
+#define GPIOF_DRIVE_PULLDOWN (1 << 7)
+#define GPIOF_DRIVE_STRONG (1 << 8)
+#define GPIOF_DRIVE_HIZ (1 << 9)
+
/**
* struct gpio - a structure describing a GPIO with configuration
* @gpio: the GPIO number
@@ -156,6 +161,11 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
return -ENOSYS;
}
+static inline int gpio_set_drive(unsigned gpio, unsigned mode)
+{
+ return -ENOSYS;
+}
+
static inline int gpio_get_value(unsigned gpio)
{
/* GPIO can never have been requested or set as {in,out}put */
diff --git a/include/linux/intel_cln_sb.h b/include/linux/intel_cln_sb.h
new file mode 100644
index 0000000..6092fc0
--- /dev/null
+++ b/include/linux/intel_cln_sb.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton side-band driver
+ *
+ * Thread-safe sideband read/write routine.
+ *
+ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2012
+ */
+
+#ifndef __INTEL_CLN_SB_H__
+#define __INTEL_CLN_SB_H__
+
+#include <linux/types.h>
+
+typedef enum {
+ SB_ID_HUNIT = 0x03,
+ SB_ID_THERMAL = 0x04,
+ SB_ID_ESRAM = 0x05,
+ SB_ID_SOC = 0x31,
+}cln_sb_id;
+
+/**
+ * intel_cln_sb_read_reg
+ *
+ * @param cln_sb_id: Sideband identifier
+ * @param command: Command to send to destination identifier
+ * @param reg: Target register w/r to cln_sb_id
+ * @return nothing
+ *
+ * Utility function to allow thread-safe read of side-band
+ * command - can be different read op-code types - which is why we don't
+ * hard-code this value directly into msg
+ */
+void intel_cln_sb_read_reg(cln_sb_id id, u8 cmd, u8 reg, u32 *data, u8 lock);
+
+/**
+ * intel_cln_sb_write_reg
+ *
+ * @param cln_sb_id: Sideband identifier
+ * @param command: Command to send to destination identifier
+ * @param reg: Target register w/r to cln_sb_id
+ * @return nothing
+ *
+ * Utility function to allow thread-safe write of side-band
+ */
+void intel_cln_sb_write_reg(cln_sb_id id, u8 cmd, u8 reg, u32 data, u8 lock);
+
+/**
+ * intel_cln_sb_runfn_lock
+ *
+ * @param fn: Callback function - which requires side-band spinlock and !irq
+ * @param arg: Callback argument
+ * @return 0 on success < 0 on failure
+ *
+ * Runs the given function pointer inside of a call to the local spinlock using
+ * spin_lock_irqsave/spin_unlock_irqrestore. Needed for the eSRAMv1 driver to
+ * guarantee atomicity, but, available to any other user of sideband provided
+ * rules are respected.
+ * Rules:
+ * fn may not sleep
+ * fn may not change the state of irqs
+ */
+int intel_cln_sb_runfn_lock(int (*fn)( void * arg ), void * arg);
+
+/**
+ * intel_cln_sb_initialized
+ *
+ * False if sideband running on non-Clanton system
+ */
+int intel_cln_sb_initialized(void);
+
+#endif /* __INTEL_CLN_SB_H__ */
diff --git a/include/linux/intel_mid_dma.h b/include/linux/intel_mid_dma.h
index 10496bd..fdb8085 100644
--- a/include/linux/intel_mid_dma.h
+++ b/include/linux/intel_mid_dma.h
@@ -26,8 +26,10 @@
#define __INTEL_MID_DMA_H__
#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
#define DMA_PREP_CIRCULAR_LIST (1 << 10)
+#define MAX_CHAN 4
/*DMA mode configurations*/
enum intel_mid_dma_mode {
@@ -73,4 +75,163 @@ struct intel_mid_dma_slave {
struct dma_slave_config dma_slave;
};
+/**
+ * struct intel_mid_dma_chan - internal mid representation of a DMA channel
+ * @chan: dma_chan strcture represetation for mid chan
+ * @ch_regs: MMIO register space pointer to channel register
+ * @dma_base: MMIO register space DMA engine base pointer
+ * @ch_id: DMA channel id
+ * @lock: channel spinlock
+ * @active_list: current active descriptors
+ * @queue: current queued up descriptors
+ * @free_list: current free descriptors
+ * @slave: dma slave struture
+ * @descs_allocated: total number of decsiptors allocated
+ * @dma: dma device struture pointer
+ * @busy: bool representing if ch is busy (active txn) or not
+ * @in_use: bool representing if ch is in use or not
+ * @raw_tfr: raw trf interrupt received
+ * @raw_block: raw block interrupt received
+ */
+struct intel_mid_dma_chan {
+ struct dma_chan chan;
+ void __iomem *ch_regs;
+ void __iomem *dma_base;
+ int ch_id;
+ spinlock_t lock;
+ struct list_head active_list;
+ struct list_head queue;
+ struct list_head free_list;
+ unsigned int descs_allocated;
+ struct middma_device *dma;
+ bool busy;
+ bool in_use;
+ u32 raw_tfr;
+ u32 raw_block;
+ struct intel_mid_dma_slave *mid_slave;
+};
+
+struct intel_mid_dma_desc {
+ void __iomem *block; /*ch ptr*/
+ struct list_head desc_node;
+ struct dma_async_tx_descriptor txd;
+ size_t len;
+ dma_addr_t sar;
+ dma_addr_t dar;
+ u32 cfg_hi;
+ u32 cfg_lo;
+ u32 ctl_lo;
+ u32 ctl_hi;
+ struct pci_pool *lli_pool;
+ struct intel_mid_dma_lli *lli;
+ dma_addr_t lli_phys;
+ unsigned int lli_length;
+ unsigned int current_lli;
+ dma_addr_t next;
+ enum dma_transfer_direction dirn;
+ enum dma_status status;
+ enum dma_slave_buswidth width; /*width of DMA txn*/
+ enum intel_mid_dma_mode cfg_mode; /*mode configuration*/
+
+};
+
+
+enum intel_mid_dma_state {
+ RUNNING = 0,
+ SUSPENDED,
+};
+/**
+ * struct middma_device - internal representation of a DMA device
+ * @pdev: PCI device
+ * @dma_base: MMIO register space pointer of DMA
+ * @dma_pool: for allocating DMA descriptors
+ * @common: embedded struct dma_device
+ * @tasklet: dma tasklet for processing interrupts
+ * @ch: per channel data
+ * @pci_id: DMA device PCI ID
+ * @intr_mask: Interrupt mask to be used
+ * @mask_reg: MMIO register for periphral mask
+ * @chan_base: Base ch index (read from driver data)
+ * @max_chan: max number of chs supported (from drv_data)
+ * @block_size: Block size of DMA transfer supported (from drv_data)
+ * @pimr_mask: MMIO register addr for periphral interrupt (from drv_data)
+ * @state: dma PM device state
+ */
+struct middma_device {
+ struct pci_dev *pdev;
+ void __iomem *dma_base;
+ struct pci_pool *dma_pool;
+ struct dma_device common;
+ struct tasklet_struct tasklet;
+ struct intel_mid_dma_chan ch[MAX_CHAN];
+ unsigned int pci_id;
+ unsigned int intr_mask;
+ void __iomem *mask_reg;
+ int chan_base;
+ int max_chan;
+ int block_size;
+ bool ispci_fn;
+ unsigned int pimr_mask;
+ enum intel_mid_dma_state state;
+};
+
+/**
+ * intel_mid_dma_interrupt - DMA ISR
+ * @irq: IRQ where interrupt occurred
+ * @data: ISR cllback data (the controller structure)
+ *
+ * See if this is our interrupt if so then schedule the tasklet
+ * otherwise ignore
+ */
+irqreturn_t intel_mid_dma_interrupt(int irq, void *data);
+
+/**
+ * middma_shutdown - Shutdown the DMA controller
+ * @pdev: Controller PCI device structure
+ *
+ * Called by remove
+ * Unregister DMa controller, clear all structures and free interrupt
+ */
+void intel_mid_dma_shutdown(struct pci_dev *pdev, struct middma_device *device);
+
+/**
+ * intel_mid_dma_probe - PCI Probe
+ * @pdev: Controller PCI device structure
+ * @id: pci device id structure
+ *
+ * Initialize the PCI device, map BARs, query driver data.
+ * Call intel_setup_dma to complete contoller and chan initilzation
+ */
+int intel_cln_dma_probe(struct pci_dev *pdev,
+ struct middma_device *device);
+/**
+ * intel_mid_dma_remove - PCI remove
+ * @pdev: Controller PCI device structure
+ *
+ * Free up all resources and data
+ * Call shutdown_dma to complete contoller and chan cleanup
+ */
+void intel_cln_dma_remove(struct pci_dev *pdev, struct middma_device *device);
+
+/* Power Management */
+/*
+* dma_suspend - PCI suspend function
+*
+* @pci: PCI device structure
+* @state: PM message
+*
+* This function is called by OS when a power event occurs
+*/
+int intel_cln_dma_suspend(struct middma_device *device);
+
+/**
+* intel_cln_dma_resume - PCI resume function
+*
+* @pci: PCI device structure
+*
+* This function is called by OS when a power event occurs
+*/
+int intel_cln_dma_resume(struct middma_device *device);
+
+
#endif /*__INTEL_MID_DMA_H__*/
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 0eb6579..060fce2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2512,6 +2512,7 @@
#define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823
#define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824
#define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F
+#define PCI_DEVICE_ID_INTEL_CLANTON_ILB 0x095E
#define PCI_DEVICE_ID_INTEL_I960 0x0960
#define PCI_DEVICE_ID_INTEL_I960RM 0x0962
#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60
@@ -2534,6 +2535,7 @@
#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21
#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30
#define PCI_DEVICE_ID_INTEL_IOAT 0x1a38
+#define PCI_DEVICE_ID_INTEL_CLN_SD 0x08A7
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f
#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40
diff --git a/include/linux/platform_data/ad7298.h b/include/linux/platform_data/ad7298.h
index fbf8adf..721ed6f 100644
--- a/include/linux/platform_data/ad7298.h
+++ b/include/linux/platform_data/ad7298.h
@@ -9,12 +9,17 @@
#ifndef __LINUX_PLATFORM_DATA_AD7298_H__
#define __LINUX_PLATFORM_DATA_AD7298_H__
+#define AD7298_MAX_CHAN 8
+
/**
* struct ad7298_platform_data - Platform data for the ad7298 ADC driver
* @ext_ref: Whether to use an external reference voltage.
+ * @ext_vin_max: External input voltage range for each voltage input channel
+ * (set to non-zero if platform uses external voltage dividers)
**/
struct ad7298_platform_data {
bool ext_ref;
+ u16 ext_vin_max[AD7298_MAX_CHAN];
};
#endif /* IIO_ADC_AD7298_H_ */
diff --git a/include/linux/platform_data/clanton.h b/include/linux/platform_data/clanton.h
new file mode 100644
index 0000000..bd24df0
--- /dev/null
+++ b/include/linux/platform_data/clanton.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+/*
+ * Intel Clanton platform data definition
+ */
+
+#ifndef _PDATA_CLANTON_H
+#define _PDATA_CLANTON_H
+
+typedef enum {
+ CLANTON_PLAT_UNDEFINED = 0,
+ CLANTON_EMULATION = 1,
+ CLANTON_PEAK = 2,
+ KIPS_BAY = 3,
+ CROSS_HILL = 4,
+ CLANTON_HILL = 5,
+ IZMIR = 6,
+}cln_plat_id_t;
+
+typedef enum {
+ PLAT_DATA_ID = 1,
+ PLAT_DATA_SN = 2,
+ PLAT_DATA_MAC0 = 3,
+ PLAT_DATA_MAC1 = 4,
+}plat_dataid_t;
+
+
+#ifdef CONFIG_INTEL_CLN_SOC
+extern cln_plat_id_t intel_cln_plat_get_id(void);
+extern int intel_cln_plat_get_mac(plat_dataid_t id, char * mac);
+#else
+static inline cln_plat_id_t intel_cln_plat_get_id(void)
+{
+ return CLANTON_PLAT_UNDEFINED;
+}
+static int intel_cln_plat_get_mac(plat_dataid_t id, char * mac)
+{
+ return -ENODEV;
+}
+#endif
+#endif /* _PDATA_CLANTON_H */
diff --git a/include/linux/platform_data/st_accel_i2c.h b/include/linux/platform_data/st_accel_i2c.h
new file mode 100644
index 0000000..1dc3d93
--- /dev/null
+++ b/include/linux/platform_data/st_accel_i2c.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_ST_ACCEL_H__
+#define __LINUX_PLATFORM_DATA_ST_ACCEL_H__
+
+/**
+ * struct st_accel_i2c_platform_data - Platform data for the ST Micro accelerometer driver
+ * @irq2: IRQ number for the second INT pin.
+ **/
+struct st_accel_i2c_platform_data {
+ int irq2;
+};
+
+#endif /* LINUX_PLATFORM_DATA_ST_ACCEL_H_ */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 1f0ab90..86ecaa6 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -224,7 +224,7 @@ struct power_supply_info {
int use_for_apm;
};
-extern struct power_supply *power_supply_get_by_name(char *name);
+extern struct power_supply *power_supply_get_by_name(const char *name);
extern void power_supply_changed(struct power_supply *psy);
extern int power_supply_am_i_supplied(struct power_supply *psy);
extern int power_supply_set_battery_charged(struct power_supply *psy);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 6d661f3..6842d11 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -76,6 +76,7 @@ enum pwm_polarity {
enum {
PWMF_REQUESTED = 1 << 0,
PWMF_ENABLED = 1 << 1,
+ PWMF_EXPORTED = 1 << 2,
};
struct pwm_device {
@@ -86,7 +87,9 @@ struct pwm_device {
struct pwm_chip *chip;
void *chip_data;
- unsigned int period; /* in nanoseconds */
+ unsigned int period; /* in nanoseconds */
+ unsigned int duty_cycle; /* in nanoseconds */
+ enum pwm_polarity polarity;
};
static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period)
@@ -100,6 +103,17 @@ static inline unsigned int pwm_get_period(struct pwm_device *pwm)
return pwm ? pwm->period : 0;
}
+static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty)
+{
+ if (pwm)
+ pwm->duty_cycle = duty;
+}
+
+static inline unsigned int pwm_get_duty_cycle(struct pwm_device *pwm)
+{
+ return pwm ? pwm->duty_cycle : 0;
+}
+
/*
* pwm_set_polarity - configure the polarity of a PWM signal
*/
@@ -252,4 +266,17 @@ static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
}
#endif
+#ifdef CONFIG_PWM_SYSFS
+void pwmchip_sysfs_export(struct pwm_chip *chip);
+void pwmchip_sysfs_unexport(struct pwm_chip *chip);
+#else
+static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
+{
+}
+
+static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
+{
+}
+#endif /* CONFIG_PWM_SYSFS */
+
#endif /* __LINUX_PWM_H */
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
index f366320..9810c71 100644
--- a/include/linux/pxa2xx_ssp.h
+++ b/include/linux/pxa2xx_ssp.h
@@ -104,6 +104,28 @@
#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */
#define SSCR1_RFT (0x00000c00) /* Receive FIFO Threshold (mask) */
#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
+
+/* CE5X00 SSCR0 bit definition */
+#define CE5X00_SSCR0_DSS ((1<<5)-1) /* Data Size Select (mask) */
+#define CE5X00_SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..32] */
+#define CE5X00_SSCR0_FRF (((1<<2)-1) << 5) /* FRame Format (mask) */
+#define CE5X00_SSCR0_Motorola (0x0 << 5) /* Motorola's Serial Peripheral Interface (SPI) */
+#define CE5X00_SSCR0_TI (0x1 << 5) /* Texas Instruments' Synchronous Serial Protocol (SSP) */
+#define CE5X00_SSCR0_National (0x2 << 5) /* National Microwire */
+
+#define RX_THRESH_CE5X00_DFLT 16
+#define TX_THRESH_CE5X00_DFLT 16
+
+#define CE5X00_SSSR_TFL_MASK (0x1F << 8) /* Transmit FIFO Level mask */
+#define CE5X00_SSSR_RFL_MASK (0x1F << 13) /* Receive FIFO Level mask */
+
+#define CE5X00_SSCR1_TFT (((1<<5)-1) << 6) /* Transmit FIFO Threshold (mask) */
+#define CE5X00_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..32] */
+#define CE5X00_SSCR1_RFT (((1<<5)-1) << 11) /* Receive FIFO Threshold (mask) */
+#define CE5X00_SSCR1_RxTresh(x) (((x) - 1) << 11) /* level [1..32] */
+#define CE5X00_SSCR1_STRF (1 << 17) /* Select FIFO or EFWR */
+#define CE5X00_SSCR1_EFWR (1 << 16) /* Enable FIFO Write/Read */
+
#endif
/* extra bits in PXA255, PXA26x and PXA27x SSP ports */
@@ -164,6 +186,7 @@ enum pxa_ssp_type {
PXA168_SSP,
PXA910_SSP,
CE4100_SSP,
+ CE5X00_SSP,
};
struct ssp_device {
@@ -181,6 +204,7 @@ struct ssp_device {
int irq;
int drcmr_rx;
int drcmr_tx;
+ struct pci_dev *pcidev;
};
/**
@@ -208,4 +232,5 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
struct ssp_device *pxa_ssp_request(int port, const char *label);
void pxa_ssp_free(struct ssp_device *);
+int pxa_msi_enabled(void);
#endif
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 9531845c..445fe6e 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -148,7 +148,7 @@ extern int rtc_initialize_alarm(struct rtc_device *rtc,
extern void rtc_update_irq(struct rtc_device *rtc,
unsigned long num, unsigned long events);
-extern struct rtc_device *rtc_class_open(char *name);
+extern struct rtc_device *rtc_class_open(const char *name);
extern void rtc_class_close(struct rtc_device *rtc);
extern int rtc_irq_register(struct rtc_device *rtc,
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
index c73d144..acac9ae 100644
--- a/include/linux/spi/pxa2xx_spi.h
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -130,23 +130,12 @@ static inline void pxa_free_dma(int dma_ch)
{
}
-/*
- * The CE4100 does not have the clk framework implemented and SPI clock can
- * not be switched on/off or the divider changed.
- */
-static inline void clk_disable(struct clk *clk)
-{
-}
-
-static inline int clk_enable(struct clk *clk)
-{
- return 0;
-}
-
+#ifndef CONFIG_GEN3_SPI
static inline unsigned long clk_get_rate(struct clk *clk)
{
return 3686400;
}
+#endif
#endif
#endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index f629189..307d218 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -80,6 +80,8 @@ struct spi_device {
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
+#define SPI_MODE_QUAD_IO 0x05 /* Quad IO mode using 4 wire */
+#define SPI_MODE_DUAL_IO 0x06 /* Dual IO mode using 2 wire */
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
#define SPI_LOOP 0x20 /* loopback mode */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 1d1b634..a2b49f2 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -81,9 +81,9 @@ struct uuidcmp {
*
* Returns 1 if the device matches, and 0 otherwise.
*/
-static int match_dev_by_uuid(struct device *dev, void *data)
+static int match_dev_by_uuid(struct device *dev, const void *data)
{
- struct uuidcmp *cmp = data;
+ const struct uuidcmp *cmp = data;
struct hd_struct *part = dev_to_part(dev);
if (!part->info)
diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c
index 25596e4..9b2a1d5 100644
--- a/kernel/power/suspend_test.c
+++ b/kernel/power/suspend_test.c
@@ -112,7 +112,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
rtc_set_alarm(rtc, &alm);
}
-static int __init has_wakealarm(struct device *dev, void *name_ptr)
+static int __init has_wakealarm(struct device *dev, const void *data)
{
struct rtc_device *candidate = to_rtc_device(dev);
@@ -121,7 +121,6 @@ static int __init has_wakealarm(struct device *dev, void *name_ptr)
if (!device_may_wakeup(candidate->dev.parent))
return 0;
- *(const char **)name_ptr = dev_name(dev);
return 1;
}
@@ -159,8 +158,8 @@ static int __init test_suspend(void)
static char warn_no_rtc[] __initdata =
KERN_WARNING "PM: no wakealarm-capable RTC driver is ready\n";
- char *pony = NULL;
struct rtc_device *rtc = NULL;
+ struct device *dev;
/* PM is initialized by now; is that state testable? */
if (test_state == PM_SUSPEND_ON)
@@ -171,9 +170,9 @@ static int __init test_suspend(void)
}
/* RTCs have initialized by now too ... can we use one? */
- class_find_device(rtc_class, NULL, &pony, has_wakealarm);
- if (pony)
- rtc = rtc_class_open(pony);
+ dev = class_find_device(rtc_class, NULL, NULL, has_wakealarm);
+ if (dev)
+ rtc = rtc_class_open(dev_name(dev));
if (!rtc) {
printk(warn_no_rtc);
goto done;
diff --git a/meta/cfg/kernel-cache/bsp/clanton/clanton.cfg b/meta/cfg/kernel-cache/bsp/clanton/clanton.cfg
new file mode 100644
index 0000000..5c2673a
--- /dev/null
+++ b/meta/cfg/kernel-cache/bsp/clanton/clanton.cfg
@@ -0,0 +1,2846 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/i386 3.8.7 Kernel Configuration
+#
+# CONFIG_64BIT is not set
+CONFIG_X86_32=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_CPU_AUTOPROBE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ZONE_DMA32 is not set
+# CONFIG_AUDIT_ARCH is not set
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_32_LAZY_GS=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CGROUP_DEVICE is not set
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_MEMCG is not set
+# CONFIG_CGROUP_HUGETLB is not set
+# CONFIG_CGROUP_PERF is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_UIDGID_CONVERTED=y
+# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_HAVE_UID16=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_HAVE_PCSPKR_PLATFORM=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_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_GENERIC_SIGALTSTACK=y
+CONFIG_CLONE_BACKWARDS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+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 is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY 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=y
+# 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 is not set
+# CONFIG_SYSV68_PARTITION 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_UNINLINE_SPIN_UNLOCK=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+# CONFIG_ZONE_DMA is not set
+# CONFIG_SMP is not set
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+CONFIG_INTEL_CLN_SOC=y
+# CONFIG_INTEL_CLN_SOC_FPGAEMU is not set
+CONFIG_INTEL_CLN_SOC_SVP=y
+# CONFIG_X86_WANT_INTEL_MID is not set
+# CONFIG_X86_RDC321X is not set
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+
+#
+# Intel Media SOC Gen3 support
+#
+CONFIG_ARCH_GEN3=y
+# CONFIG_X86_32_IRIS is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_PARAVIRT_GUEST is not set
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+CONFIG_M586TSC=y
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MELAN is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+# CONFIG_X86_PPRO_FENCE is not set
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_ALIGNMENT_16=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CPU_SUP_UMC_32=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_DMI is not set
+CONFIG_NR_CPUS=1
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_UP_APIC=y
+CONFIG_X86_UP_IOAPIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_INTEL=y
+# CONFIG_X86_MCE_AMD is not set
+# CONFIG_X86_ANCIENT_MCE is not set
+CONFIG_X86_MCE_THRESHOLD=y
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_THERMAL_VECTOR=y
+CONFIG_VM86=y
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+CONFIG_X86_REBOOTFIXUPS=y
+CONFIG_MICROCODE=y
+CONFIG_MICROCODE_INTEL=y
+# CONFIG_MICROCODE_AMD is not set
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+# CONFIG_NOHIGHMEM is not set
+# CONFIG_HIGHMEM4G is not set
+CONFIG_HIGHMEM64G=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_X86_PAE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+# CONFIG_MEMORY_FAILURE is not set
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_HIGHPTE is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_MTRR is not set
+# CONFIG_ARCH_RANDOM is not set
+CONFIG_X86_SMAP=y
+CONFIG_EFI=y
+CONFIG_EFI_STUB=y
+CONFIG_EFI_CAPSULE=y
+CONFIG_SECCOMP=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+# CONFIG_COMPAT_VDSO is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+CONFIG_PM_SLEEP_DEBUG=y
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_EC_DEBUGFS=y
+# CONFIG_ACPI_PROC_EVENT is not set
+CONFIG_ACPI_AC=y
+# CONFIG_ACPI_BATTERY is not set
+CONFIG_ACPI_BUTTON=y
+# CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_I2C=m
+CONFIG_ACPI_PROCESSOR=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+CONFIG_ACPI_DEBUG=y
+# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
+CONFIG_ACPI_PCI_SLOT=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+# CONFIG_ACPI_SBS is not set
+# CONFIG_ACPI_HED is not set
+# CONFIG_ACPI_CUSTOM_METHOD is not set
+# CONFIG_ACPI_BGRT is not set
+# CONFIG_ACPI_APEI is not set
+# CONFIG_SFI is not set
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+# CONFIG_INTEL_IDLE is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_PCI_LABEL=y
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISA is not set
+# CONFIG_SCx200 is not set
+# CONFIG_ALIX is not set
+# CONFIG_NET5501 is not set
+CONFIG_AMD_NB=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+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 is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI 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=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# 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=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL 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_STP=m
+CONFIG_GARP=m
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# 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_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_DNS_RESOLVER is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_NETPRIO_CGROUP is not set
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTSDIO is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_MRVL is not set
+# CONFIG_BT_ATH3K is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=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_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 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=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+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=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_CMA is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# 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_TS5500 is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# 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_MTD_CLN_ROM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=2
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=81920
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_INTEL_MID_PTI is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO 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_VMWARE_BALLOON is not set
+# CONFIG_BMP085_I2C is not set
+# CONFIG_BMP085_SPI is not set
+# CONFIG_PCH_PHUB is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+# 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_EEPROM_93XX46 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL 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=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# 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 is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_FC is not set
+CONFIG_MII=y
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+CONFIG_NET_CADENCE=y
+# CONFIG_ARM_AT91_ETHER is not set
+# CONFIG_MACB is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+CONFIG_E1000=m
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_NET_VENDOR_I825XX is not set
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_SFC is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_NET_VENDOR_STMICRO=y
+CONFIG_STMMAC_ETH=m
+# CONFIG_STMMAC_PLATFORM is not set
+CONFIG_STMMAC_PCI=y
+# CONFIG_STMMAC_DEBUG_FS is not set
+CONFIG_STMMAC_DA=y
+# CONFIG_STMMAC_PTP is not set
+CONFIG_STMMAC_RING=y
+# CONFIG_STMMAC_CHAINED is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# 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_BCM87XX_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_MICREL_KS8995MA is not set
+CONFIG_PPP=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPPOE is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+
+#
+# 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 is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AIRO is not set
+# CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8180 is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_ADM8211 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
+# CONFIG_ATH_CARDS is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_IWLWIFI=m
+CONFIG_IWLDVM=m
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+# CONFIG_IWLWIFI_P2P is not set
+# CONFIG_IWL4965 is not set
+# CONFIG_IWL3945 is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_HERMES is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CE is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192DE is not set
+# CONFIG_RTL8723AE is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_WL_TI is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC 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_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=32
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_ISI is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_PNP is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_MFD_HSU is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# 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_SERIAL_CLN_UART is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_MMAP is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_I2C_SCMI is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_EG20T is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_INTEL_MID is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_SCx200_ACB is not set
+# 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=y
+CONFIG_GEN3_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PXA2XX=m
+CONFIG_SPI_PXA2XX_PCI=m
+# CONFIG_SPI_CE5XX_SPI_SLAVE is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_TOPCLIFF_PCH is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_LPC_SCH is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+CONFIG_PPS=m
+# CONFIG_PPS_DEBUG is not set
+
+#
+# PPS clients support
+#
+# CONFIG_PPS_CLIENT_KTIMER is not set
+# CONFIG_PPS_CLIENT_LDISC is not set
+# CONFIG_PPS_CLIENT_GPIO is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+CONFIG_PTP_1588_CLOCK=m
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PTP_1588_CLOCK_PCH=m
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_ACPI=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_TS5500 is not set
+CONFIG_GPIO_SCH=m
+# CONFIG_GPIO_ICH is not set
+# CONFIG_GPIO_VX855 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_AMD8111 is not set
+# CONFIG_GPIO_LANGWELL is not set
+# CONFIG_GPIO_PCH is not set
+# CONFIG_GPIO_ML_IOH is not set
+# CONFIG_GPIO_RDC321X is not set
+
+#
+# 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:
+#
+
+#
+# USB 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_GENERIC_ADC_BATTERY is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_FAIR_SHARE is not set
+CONFIG_STEP_WISE=y
+# CONFIG_USER_SPACE is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_CS5535 is not set
+# CONFIG_MFD_TIMBERDALE is not set
+CONFIG_CY8C9540A=m
+CONFIG_INTEL_CLN_GIP=m
+# CONFIG_INTEL_CLN_GIP_TEST is not set
+CONFIG_LPC_SCH=y
+# CONFIG_LPC_ICH is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2=m
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEOBUF2_MEMOPS=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_USB_SN9C102 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_MEDIA_PCI_SUPPORT is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, frontends)
+#
+
+#
+# Encoders, decoders, sensors and other helper chips
+#
+
+#
+# Audio decoders, processors and mixers
+#
+# 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_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_ADV7183 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_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X 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_SAA717X is not set
+# 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_ADV7343 is not set
+# CONFIG_VIDEO_ADV7393 is not set
+# CONFIG_VIDEO_AK881X is not set
+
+#
+# Camera sensor devices
+#
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_VS6624 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# Miscelaneous helper chips
+#
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_M52790 is not set
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_AU8522_V4L is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
+# CONFIG_DVB_TUNER_DIB0090 is not set
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+# CONFIG_VGA_SWITCHEROO is not set
+# CONFIG_DRM is not set
+# CONFIG_STUB_POULSBO is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_EXYNOS_VIDEO 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 is not set
+# CONFIG_BACKLIGHT_APPLE is not set
+# CONFIG_BACKLIGHT_SAHARA is not set
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+# CONFIG_BACKLIGHT_LM3630 is not set
+# CONFIG_BACKLIGHT_LM3639 is not set
+# CONFIG_BACKLIGHT_LP855X is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO_TPKBD is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_PS3REMOTE is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB_ARCH_HAS_XHCI=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=m
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# 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_DWC3 is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=m
+# 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_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_PLATFORM is not set
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_RENESAS_USBHS is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+# 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=m
+# 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
+# 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_STORAGE_ENE_UB6250 is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# 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_F81232 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_METRO 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=m
+# 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_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_ZTE is not set
+# CONFIG_USB_SERIAL_SSU100 is not set
+# CONFIG_USB_SERIAL_QT2 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_EZUSB_FX2 is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_RCAR_PHY is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_AMD5536UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_NET2280 is not set
+# CONFIG_USB_GOKU is not set
+CONFIG_USB_EG20T=m
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_ACM_MS 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_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# 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_PCI=y
+# CONFIG_MMC_RICOH_MMC is not set
+# CONFIG_MMC_SDHCI_ACPI is not set
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_WBSD is not set
+# CONFIG_MMC_TIFM_SD is not set
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LM3642 is not set
+# 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_PCA9633 is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_LM355x is not set
+# CONFIG_LEDS_OT200 is not set
+# CONFIG_LEDS_BLINKM is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_CPU is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_MID_DMAC=m
+CONFIG_INTEL_MID_PCI=m
+CONFIG_INTEL_CLN_DMAC=m
+# CONFIG_INTEL_IOATDMA is not set
+# CONFIG_TIMB_DMA is not set
+# CONFIG_PCH_DMA is not set
+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=m
+# CONFIG_UIO_CIF is not set
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_DMEM_GENIRQ is not set
+# CONFIG_UIO_AEC is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_UIO_PCI_GENERIC is not set
+# CONFIG_UIO_NETX is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_HYPERV is not set
+CONFIG_STAGING=y
+# CONFIG_ET131X is not set
+# CONFIG_SLICOSS is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_R8712U is not set
+# CONFIG_RTS5139 is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+# CONFIG_DX_SEP is not set
+
+#
+# IIO staging drivers
+#
+# CONFIG_IIO_SW_RING is not set
+
+#
+# Accelerometers
+#
+# CONFIG_ADIS16201 is not set
+# CONFIG_ADIS16203 is not set
+# CONFIG_ADIS16204 is not set
+# CONFIG_ADIS16209 is not set
+# CONFIG_ADIS16220 is not set
+# CONFIG_ADIS16240 is not set
+# CONFIG_KXSD9 is not set
+# CONFIG_LIS3L02DQ is not set
+# CONFIG_SCA3000 is not set
+
+#
+# Analog to digital converters
+#
+# CONFIG_AD7291 is not set
+# CONFIG_AD7606 is not set
+# CONFIG_AD799X is not set
+# CONFIG_AD7780 is not set
+# CONFIG_AD7816 is not set
+# CONFIG_AD7192 is not set
+# CONFIG_ADT7410 is not set
+# CONFIG_AD7280 is not set
+
+#
+# Analog digital bi-direction converters
+#
+# CONFIG_ADT7316 is not set
+
+#
+# Capacitance to digital converters
+#
+# CONFIG_AD7150 is not set
+# CONFIG_AD7152 is not set
+# CONFIG_AD7746 is not set
+
+#
+# Direct Digital Synthesis
+#
+# CONFIG_AD5930 is not set
+# CONFIG_AD9832 is not set
+# CONFIG_AD9834 is not set
+# CONFIG_AD9850 is not set
+# CONFIG_AD9852 is not set
+# CONFIG_AD9910 is not set
+# CONFIG_AD9951 is not set
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16060 is not set
+# CONFIG_ADIS16080 is not set
+# CONFIG_ADIS16130 is not set
+# CONFIG_ADIS16260 is not set
+# CONFIG_ADXRS450 is not set
+
+#
+# Network Analyzer, Impedance Converters
+#
+# CONFIG_AD5933 is not set
+
+#
+# Inertial measurement units
+#
+# CONFIG_ADIS16400 is not set
+
+#
+# Light sensors
+#
+# CONFIG_SENSORS_ISL29018 is not set
+# CONFIG_SENSORS_ISL29028 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_TSL2583 is not set
+# CONFIG_TSL2x7x is not set
+
+#
+# Magnetometer sensors
+#
+# CONFIG_SENSORS_AK8975 is not set
+# CONFIG_SENSORS_HMC5843 is not set
+
+#
+# Active energy metering IC
+#
+# CONFIG_ADE7753 is not set
+# CONFIG_ADE7754 is not set
+# CONFIG_ADE7758 is not set
+# CONFIG_ADE7759 is not set
+# CONFIG_ADE7854 is not set
+
+#
+# Resolver to digital converters
+#
+# CONFIG_AD2S90 is not set
+# CONFIG_AD2S1200 is not set
+# CONFIG_AD2S1210 is not set
+
+#
+# Triggers - standalone
+#
+# CONFIG_IIO_GPIO_TRIGGER is not set
+CONFIG_IIO_SYSFS_TRIGGER=m
+# CONFIG_IIO_SIMPLE_DUMMY is not set
+# CONFIG_ZSMALLOC is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_ACPI_QUICKSTART is not set
+# 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_STAGING_MEDIA is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_USB_WPAN_HCD is not set
+# CONFIG_WIMAX_GDM72XX is not set
+# CONFIG_CSR_WIFI is not set
+CONFIG_NET_VENDOR_SILICOM=y
+# CONFIG_SBYPASS is not set
+# CONFIG_BPCTL is not set
+# CONFIG_CED1401 is not set
+# CONFIG_DGRP is not set
+# CONFIG_SB105X is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+# CONFIG_ACERHDF is not set
+# CONFIG_ASUS_LAPTOP is not set
+# CONFIG_FUJITSU_LAPTOP is not set
+# CONFIG_FUJITSU_TABLET is not set
+# CONFIG_AMILO_RFKILL is not set
+# CONFIG_HP_ACCEL is not set
+# CONFIG_PANASONIC_LAPTOP is not set
+# CONFIG_SONY_LAPTOP is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_INTEL_MENLOW is not set
+# CONFIG_ACPI_WMI is not set
+# CONFIG_TOPSTAR_LAPTOP is not set
+# CONFIG_TOSHIBA_BT_RFKILL is not set
+# CONFIG_ACPI_CMPC is not set
+CONFIG_INTEL_CLN_ESRAM=y
+CONFIG_INTEL_CLN_ECC_REFRESH_PERIOD=24
+CONFIG_INTEL_CLN_ECC_SCRUB=y
+# CONFIG_INTEL_CLN_ECC_SCRUB_OVERRIDE_CONFIG is not set
+# CONFIG_INTEL_CLN_ECC_SCRUB_S3_CONFIG is not set
+CONFIG_INTEL_CLN_THERMAL=y
+# CONFIG_INTEL_IPS is not set
+# CONFIG_IBM_RTL is not set
+# CONFIG_XO15_EBOOK is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_INTEL_OAKTRAIL is not set
+# CONFIG_APPLE_GMUX is not set
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_CLKBLD_I8253=y
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+CONFIG_IIO=m
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_CB=y
+CONFIG_IIO_KFIFO_BUF=m
+CONFIG_IIO_TRIGGERED_BUFFER=m
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+
+#
+# Accelerometers
+#
+
+#
+# Analog to digital converters
+#
+# CONFIG_AD7266 is not set
+CONFIG_AD7298=m
+# CONFIG_AD7791 is not set
+# CONFIG_AD7793 is not set
+# CONFIG_AD7476 is not set
+# CONFIG_AD7887 is not set
+# CONFIG_MAX1363 is not set
+# CONFIG_TI_ADC081C is not set
+
+#
+# Amplifiers
+#
+# CONFIG_AD8366 is not set
+
+#
+# Hid Sensor IIO Common
+#
+
+#
+# Digital to analog converters
+#
+# CONFIG_AD5064 is not set
+# CONFIG_AD5360 is not set
+# CONFIG_AD5380 is not set
+# CONFIG_AD5421 is not set
+# CONFIG_AD5624R_SPI is not set
+# CONFIG_AD5446 is not set
+# CONFIG_AD5449 is not set
+# CONFIG_AD5504 is not set
+# CONFIG_AD5755 is not set
+# CONFIG_AD5764 is not set
+# CONFIG_AD5791 is not set
+# CONFIG_AD5686 is not set
+# CONFIG_MAX517 is not set
+# CONFIG_MCP4725 is not set
+
+#
+# Frequency Synthesizers DDS/PLL
+#
+
+#
+# Clock Generator/Distribution
+#
+# CONFIG_AD9523 is not set
+
+#
+# Phase-Locked Loop (PLL) frequency synthesizers
+#
+# CONFIG_ADF4350 is not set
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16136 is not set
+
+#
+# Inertial measurement units
+#
+# CONFIG_ADIS16480 is not set
+
+#
+# Light sensors
+#
+# CONFIG_ADJD_S311 is not set
+# CONFIG_VCNL4000 is not set
+
+#
+# Magnetometer sensors
+#
+# CONFIG_VME_BUS is not set
+CONFIG_PWM=y
+CONFIG_PWM_SYSFS=y
+# CONFIG_IPACK_BUS is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_EFI_VARS=m
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_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 is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# 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 is not set
+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_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# 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
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# 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=y
+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_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_CHECK=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE 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_VIRTUAL is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# 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_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# 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_LKDTM is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_BUILD_DOCSRC is not set
+# CONFIG_DYNAMIC_DEBUG 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_HAVE_ARCH_KMEMCHECK=y
+# CONFIG_KMEMCHECK is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_X86_PTDUMP=y
+CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA_TEST is not set
+CONFIG_DEBUG_SET_MODULE_RONX=y
+# CONFIG_DEBUG_NX_TEST is not set
+# CONFIG_DOUBLEFAULT is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+CONFIG_DEBUG_BOOT_PARAMS=y
+# CONFIG_CPA_DEBUG is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_ENCRYPTED_KEYS is not set
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_SMACK is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_YAMA is not set
+# CONFIG_IMA is not set
+# CONFIG_EVM 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=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+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 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 is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# 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=y
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# 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=m
+# 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_AES_586 is not set
+# CONFIG_CRYPTO_AES_NI_INTEL is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# 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 is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SALSA20_586 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_SERPENT_SSE2_586 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+# CONFIG_CRYPTO_DEV_GEODE is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+CONFIG_HAVE_KVM=y
+# CONFIG_VIRTUALIZATION is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_PERCPU_RWSEM=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index 1627ef2..13571ea 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -91,7 +91,7 @@ static struct class wpan_phy_class = {
static DEFINE_MUTEX(wpan_phy_mutex);
static int wpan_phy_idx;
-static int wpan_phy_match(struct device *dev, void *data)
+static int wpan_phy_match(struct device *dev, const void *data)
{
return !strcmp(dev_name(dev), (const char *)data);
}
@@ -103,8 +103,7 @@ struct wpan_phy *wpan_phy_find(const char *str)
if (WARN_ON(!str))
return NULL;
- dev = class_find_device(&wpan_phy_class, NULL,
- (void *)str, wpan_phy_match);
+ dev = class_find_device(&wpan_phy_class, NULL, str, wpan_phy_match);
if (!dev)
return NULL;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index aa64ea4..0f4a6de 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -734,10 +734,10 @@ struct class nfc_class = {
};
EXPORT_SYMBOL(nfc_class);
-static int match_idx(struct device *d, void *data)
+static int match_idx(struct device *d, const void *data)
{
struct nfc_dev *dev = to_nfc_dev(d);
- unsigned int *idx = data;
+ const unsigned int *idx = data;
return dev->idx == *idx;
}
#!/bin/sh
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git clanton-kernel
cd clanton-kernel
git branch linux-3.8.y
patch -p0 -E < clanton.patch
cp clanton.cfg .config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment