Makefile | 7 arch/arm/Kconfig | 10 arch/arm/common/dmabounce.c | 23 - arch/arm/configs/cm_x270_defconfig | 1312 ++++++++++++++++++++++++++++++ arch/arm/kernel/bios32.c | 36 + arch/arm/kernel/vmlinux.lds.S | 4 arch/arm/mach-pxa/Kconfig | 16 arch/arm/mach-pxa/Makefile | 9 arch/arm/mach-pxa/cm-x270-pci.c | 152 +++ arch/arm/mach-pxa/cm-x270.c | 975 ++++++++++++++++++++++ arch/arm/mach-pxa/it8152.c | 248 ++++++ arch/arm/mach-pxa/leds-cm-x270.c | 134 +++ arch/arm/mach-pxa/leds.c | 2 arch/arm/mach-pxa/leds.h | 1 arch/arm/mach-pxa/pxa27x.c | 6 drivers/block/Kconfig | 5 drivers/block/Makefile | 1 drivers/block/cl_flash/CL_Logic.h | 245 ++++++ drivers/block/cl_flash/Kconfig | 11 drivers/block/cl_flash/Makefile | 12 drivers/block/cl_flash/cl_blkdev.c | 731 +++++++++++++++++ drivers/block/cl_flash/cl_blkdev.h | 43 + drivers/block/cl_flash/cl_common.c | 52 + drivers/block/cl_flash/cl_nanddev_x270.c | 233 +++++ drivers/block/cl_flash/cl_nordev.c | 594 ++++++++++++++ drivers/char/Kconfig | 6 drivers/char/Makefile | 1 drivers/char/emv3020.c | 365 ++++++++ drivers/ide/Kconfig | 7 drivers/ide/arm/Makefile | 1 drivers/ide/arm/cm-x270-ide.c | 135 +++ drivers/mfd/Kconfig | 10 drivers/mfd/Makefile | 7 drivers/mfd/mcp-ac97.c | 151 +++ drivers/mfd/mcp-core.c | 1 drivers/mfd/mcp.h | 9 drivers/mfd/ucb1x00-core.c | 127 ++- drivers/mfd/ucb1x00-ts.c | 44 + drivers/mfd/ucb1x00.h | 4 drivers/mtd/nand/Kconfig | 4 drivers/mtd/nand/Makefile | 1 drivers/mtd/nand/cmx270-nand.c | 281 ++++++ drivers/net/Kconfig | 8 drivers/net/dm9000.c | 11 drivers/pcmcia/Makefile | 2 drivers/pcmcia/pxa2xx_cm_x270.c | 198 +++++ drivers/serial/pxa.c | 55 + drivers/video/Kconfig | 10 drivers/video/Makefile | 1 drivers/video/mbx/Makefile | 7 drivers/video/mbx/mbxfb.c | 659 +++++++++++++++ drivers/video/mbx/mbxsysfs.c | 129 +++ drivers/video/mbx/reg_bits.h | 489 +++++++++++ drivers/video/mbx/regs.h | 192 ++++ drivers/video/pxafb.c | 104 ++ include/asm-arm/arch-pxa/cm-x270.h | 72 ++ include/asm-arm/arch-pxa/hardware.h | 11 include/asm-arm/arch-pxa/irqs.h | 24 + include/asm-arm/arch-pxa/marathonfb.h | 28 + include/asm-arm/arch-pxa/memory.h | 13 include/asm-arm/arch-pxa/pxafbsetup.h | 39 + include/asm-arm/hardware/it8152.h | 104 ++ include/linux/pci_ids.h | 1 sound/pci/ac97/ac97_codec.c | 2 sound/pci/ac97/ac97_patch.c | 30 + sound/pci/ac97/ac97_patch.h | 1 66 files changed, 8115 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index cb57905..dd02f27 100644 --- a/Makefile +++ b/Makefile @@ -172,8 +172,11 @@ # Alternatively CROSS_COMPILE can be set # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile -ARCH ?= $(SUBARCH) -CROSS_COMPILE ?= +#ARCH ?= $(SUBARCH) +#CROSS_COMPILE ?= + +ARCH = arm +CROSS_COMPILE = arm-linux- # Architecture as present in compile.h UTS_MACHINE := $(ARCH) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 32ba00b..2de9ceb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -331,7 +331,7 @@ config ISA_DMA_API bool config PCI - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || MACH_ARMCORE help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside @@ -349,6 +349,12 @@ config PCI_HOST_VIA82C505 depends on PCI && ARCH_SHARK default y +config PCI_HOST_ITE8152 + bool + depends on PCI && MACH_ARMCORE + default y + select DMABOUNCE + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" @@ -484,7 +490,7 @@ config LEDS ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ - ARCH_AT91RM9200 + ARCH_AT91RM9200 || MACH_ARMCORE help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index ad6c89a..dc2bbd0 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -235,7 +235,7 @@ map_single(struct device *dev, void *ptr /* * Figure out if we need to bounce from the DMA mask. */ - needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask; + needs_bounce = ((dma_addr | (dma_addr + size - 1)) - PHYS_OFFSET) & ~mask; } if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) { @@ -275,6 +275,7 @@ unmap_single(struct device *dev, dma_add { struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); struct safe_buffer *buf = NULL; + unsigned long flags; /* * Trying to unmap an invalid mapping @@ -284,6 +285,8 @@ unmap_single(struct device *dev, dma_add return; } + local_irq_save(flags); + if (device_info) buf = find_safe_buffer(device_info, dma_addr); @@ -316,8 +319,11 @@ unmap_single(struct device *dev, dma_add ptr = (unsigned long)buf->ptr; dmac_clean_range(ptr, ptr + size); } + local_irq_restore(flags); free_safe_buffer(device_info, buf); } + else + local_irq_restore(flags); } static inline void @@ -424,18 +430,12 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - unmap_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } int @@ -471,7 +471,6 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -479,16 +478,12 @@ dma_unmap_sg(struct device *dev, struct BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; unmap_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } void @@ -632,7 +627,7 @@ #endif list_add(&device_info->node, &dmabounce_devs); printk(KERN_INFO "dmabounce: registered device %s on %s bus\n", - dev->bus_id, dev->bus->name); + dev->bus_id, dev->bus ? dev->bus->name : "no"); return 0; @@ -677,7 +672,7 @@ #endif kfree(device_info); printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n", - dev->bus_id, dev->bus->name); + dev->bus_id, dev->bus ? dev->bus->name : "no"); } diff --git a/arch/arm/configs/cm_x270_defconfig b/arch/arm/configs/cm_x270_defconfig new file mode 100644 index 0000000..f87d617 --- /dev/null +++ b/arch/arm/configs/cm_x270_defconfig @@ -0,0 +1,1312 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16 +# Tue Sep 26 10:07:36 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="-cm-x270" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_MAINSTONE is not set +CONFIG_MACH_ARMCORE=y +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +CONFIG_ARMCORE_REV12=y +# CONFIG_ARMCORE_REV11 is not set +CONFIG_PXA27x=y +CONFIG_IWMMXT=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_XSCALE_PMU=y +CONFIG_DMABOUNCE=y + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_HOST_ITE8152=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +# CONFIG_PCMCIA_LOAD_CIS is not set +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set +CONFIG_PCMCIA_PXA2XX=m +CONFIG_PCCARD_NONSTATIC=m + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +# CONFIG_IEEE80211_CRYPT_TKIP is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# 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_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=12000 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_ARMCORE_FLASH=y +# CONFIG_ARMCORE_NOR is not set +CONFIG_ARMCORE_NAND=y + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=m +CONFIG_BLK_DEV_IDE=m + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=m +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDESCSI=m +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=m +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDE_CM_X270=m +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +CONFIG_DM9000=y +CONFIG_DM9000_NOEPROM=y + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +# CONFIG_PRISM54 is not set +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# 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_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_CS is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_EMV3020_RTC=y + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# +CONFIG_UCB1400=m +CONFIG_UCB1400_TS=m + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_PARAMETERS is not set +CONFIG_FB_MBX=m +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# PCI devices +# +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# ALSA ARM devices +# +CONFIG_SND_PXA2XX_PCM=m +CONFIG_SND_PXA2XX_AC97=m + +# +# USB devices +# +# CONFIG_SND_USB_AUDIO is not set + +# +# PCMCIA devices +# + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM 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_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# 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_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD 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_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_PXA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY 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_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=y +# CONFIG_SMB_NLS_DEFAULT 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_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_DETECT_SOFTLOCKUP is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index c4923fa..4ff2a62 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -280,6 +280,34 @@ static void __devinit pci_fixup_cy82c693 } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693); +static void __init pci_fixup_it8152(struct pci_dev *dev) +{ + int i; + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } + } + if (dev->class == 0x68000) { + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } + } + if (dev->class == 0x80103) { + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8152, pci_fixup_it8152); + + void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) { if (debug_pci) @@ -293,9 +321,11 @@ void __devinit pcibios_update_irq(struct */ static inline int pdev_bad_for_parity(struct pci_dev *dev) { - return (dev->vendor == PCI_VENDOR_ID_INTERG && - (dev->device == PCI_DEVICE_ID_INTERG_2000 || - dev->device == PCI_DEVICE_ID_INTERG_2010)); + return ((dev->vendor == PCI_VENDOR_ID_INTERG && + (dev->device == PCI_DEVICE_ID_INTERG_2000 || + dev->device == PCI_DEVICE_ID_INTERG_2010)) || + (dev->vendor == PCI_VENDOR_ID_ITE && + dev->device == PCI_DEVICE_ID_ITE_IT8152)); } /* diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 2b254e8..310ccf5 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -175,5 +175,5 @@ #endif * If you have to comment these two assert statements out, your * binutils is too old (for other reasons as well) */ -ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") -ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") +/* ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") */ +/* ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") */ diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index c1d77f5..0a62a62 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -15,6 +15,11 @@ config MACH_MAINSTONE select PXA27x select IWMMXT +config MACH_ARMCORE + bool "CompuLab CM-X270 modules" + select PXA27x + select IWMMXT + config ARCH_PXA_IDP bool "Accelent Xscale IDP" select PXA25x @@ -50,6 +55,17 @@ endchoice endif +if MACH_ARMCORE +choice + prompt "Select CM-X270 revision" + config ARMCORE_REV12 + bool "CM-X270 revision 1.2" + config ARMCORE_REV11 + bool "CM-X270 revision 1.1" +endchoice + +endif + endmenu config MACH_POODLE diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 32526a0..d78d061 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -16,12 +16,14 @@ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o obj-$(CONFIG_MACH_POODLE) += poodle.o obj-$(CONFIG_MACH_TOSA) += tosa.o +obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o # Support for blinky lights led-y := leds.o led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o +led-$(CONFIG_MACH_ARMCORE) += leds-cm-x270.o obj-$(CONFIG_LEDS) += $(led-y) @@ -32,3 +34,10 @@ obj-$(CONFIG_PXA_SSP) += ssp.o ifeq ($(CONFIG_PXA27x),y) obj-$(CONFIG_PM) += standby.o endif + +# PCI support on CM-X270 +obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o + +ifeq ($(CONFIG_PCI),y) +obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o +endif diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c new file mode 100644 index 0000000..73243d3 --- /dev/null +++ b/arch/arm/mach-pxa/cm-x270-pci.c @@ -0,0 +1,152 @@ +/* + * arch/arm/kernel/cm-x270-pci.c + * + * PCI bios-type initialisation for PCI machines + * + * Bits taken from various places. + * + * Copyright (C) 2006 Compulab, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +unsigned long armcore_pcibios_min_mem = 0x10000000; +unsigned long armcore_pcibios_min_io = CMX270_IT8152_VIRT + 0x03e00000 + 0x120000; +unsigned long it8152_base_address = CMX270_IT8152_VIRT; + +/* these symbols needed for CardBus driver (yenta_socket) */ +EXPORT_SYMBOL(armcore_pcibios_min_io); +EXPORT_SYMBOL(armcore_pcibios_min_mem); + +static u8 __init cmx270_pci_swizzle(struct pci_dev *dev, u8 *pin) +{ + return PCI_SLOT(dev->devfn); +} + +/* Platform specific IRQ mapping */ +static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if((dev->vendor==0x1283) && (dev->device==0x8152) && + ((dev->class >> 8)==0x801)) return(CDMA_INT); + if((dev->vendor==0x1283) && (dev->device==0x0801) && + ((dev->class >> 8)==0x401)) return(AUDIO_INT); + if((dev->vendor==0x1283) && (dev->device==0x8152) && + ((dev->class >> 8)==0xc03)) return(USB_INT); + + /* ATXBASE PCI slot */ + if ( slot == 7 ) + return(PCI_INTA); + + /* ATXBASE/SB-X270 CardBus */ + if ( (slot == 8) || (slot == 0) ) + return(PCI_INTB); + + /* ATXBASE ETH */ + if ( slot == 9 ) + return(PCI_INTA); + + /* ARMCore onboard ETH */ + if ( slot == 15 ) + return(PCI_INTC); + + /* ARMBase ETH */ + if ( slot == 16 ) + return(PCI_INTA); + + /* PC104+ interrupt routing */ + if ( (slot == 17) || (slot == 19) ) + return(PCI_INTA); + if ( (slot == 18) || (slot == 20) ) + return(PCI_INTB); + + return(0); +} + +extern int it8152_pci_setup(int nr, struct pci_sys_data *sys); +extern struct pci_bus * it8152_pci_scan_bus(int nr, struct pci_sys_data *sys); + +static struct pci_bus* __init cmx270_pci_scan_bus(int nr, struct pci_sys_data *sys) +{ + IT8152_PCI_CFG_ADDR = 0x800; + if(IT8152_PCI_CFG_DATA == 0x81521283) { + printk("PCI Bridge found.\n"); + + IT8152_GPIO_GPLR=0x20; + +/*********** CardBus Controller on ATXBASE configuration ********/ + IT8152_PCI_CFG_ADDR = 0x4000; + if(IT8152_PCI_CFG_DATA == 0xAC51104C) { + unsigned int temp; + printk("CardBus Bridge found.\n"); + + // Configure socket 0 + IT8152_PCI_CFG_ADDR = 0x408C; + IT8152_PCI_CFG_DATA = 0x1022; + + IT8152_PCI_CFG_ADDR = 0x4080; + IT8152_PCI_CFG_DATA = 0x3844d060; + + IT8152_PCI_CFG_ADDR = 0x4090; + temp = IT8152_PCI_CFG_DATA; + temp = temp & 0xFFFF; + temp = temp | (0x60440000); + IT8152_PCI_CFG_ADDR = 0x4090; + IT8152_PCI_CFG_DATA = temp; + + IT8152_PCI_CFG_ADDR = 0x4018; + IT8152_PCI_CFG_DATA = 0xb0000000; + + // Configure socket 1 + IT8152_PCI_CFG_ADDR = 0x418C; + IT8152_PCI_CFG_DATA = 0x1022; + + IT8152_PCI_CFG_ADDR = 0x4180; + IT8152_PCI_CFG_DATA = 0x3844d060; + + IT8152_PCI_CFG_ADDR = 0x4190; + temp = IT8152_PCI_CFG_DATA; + temp = temp & 0xFFFF; + temp = temp | (0x60440000); + IT8152_PCI_CFG_ADDR = 0x4190; + IT8152_PCI_CFG_DATA = temp; + + IT8152_PCI_CFG_ADDR = 0x4118; + IT8152_PCI_CFG_DATA = 0xb0000000; + } +/*********** End of CardBus controller configuration **************/ + } + return it8152_pci_scan_bus(nr, sys); +} + +static struct hw_pci cmx270_pci __initdata = { + .swizzle = cmx270_pci_swizzle, + .map_irq = cmx270_pci_map_irq, + .nr_controllers = 1, + .setup = it8152_pci_setup, + .scan = cmx270_pci_scan_bus, +}; + +static int __init cmx270_init_pci(void) +{ + if (machine_is_armcore()) { + pci_common_init(&cmx270_pci); + } + return 0; +} + +subsys_initcall(cmx270_init_pci); diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c new file mode 100644 index 0000000..b006a8f --- /dev/null +++ b/arch/arm/mach-pxa/cm-x270.c @@ -0,0 +1,975 @@ +/* + * linux/arch/arm/mach-pxa/cm-x270.c + * + * Copyright (C) 2006 CompuLab, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "generic.h" + +#define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22)) +#define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22)) + +static struct resource cmx270_dm9k_resource[] = { + [0] = { + .start = DM9000_PHYS_BASE, + .end = DM9000_PHYS_BASE + 4, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DM9000_PHYS_BASE + 8, + .end = DM9000_PHYS_BASE + 8 + 500, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = CMX270_ETHIRQ, + .end = CMX270_ETHIRQ, + .flags = IORESOURCE_IRQ, + } +}; + +/* for the moment we limit ourselves to 32bit IO until some + * better IO routines can be written and tested + */ +static struct dm9000_plat_data cmx270_dm9k_platdata = { + .flags = DM9000_PLATF_32BITONLY, +}; + +/* Ethernet device */ +static struct platform_device cmx270_device_dm9k = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(cmx270_dm9k_resource), + .resource = cmx270_dm9k_resource, + .dev = { + .platform_data = &cmx270_dm9k_platdata, + } +}; + +/* audio device */ +static struct platform_device cmx270_audio_device = { + .name = "pxa2xx-ac97", + .id = -1, +}; + +/* touchscreen controller */ +static struct platform_device cmx270_ts_device = { + .name = "ucb1x00", + .id = -1, +}; + +/* RTC */ +static struct resource cmx270_v3020_resource[] = { + [0] = { + .start = RTC_PHYS_BASE, + .end = RTC_PHYS_BASE + 4, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device cmx270_rtc_device = { + .name = "emv3020-rtc", + .num_resources = ARRAY_SIZE(cmx270_v3020_resource), + .resource = cmx270_v3020_resource, + .id = -1, +}; + +/* UART on the ITE8152 chip */ +#ifdef CONFIG_PCI +static struct plat_serial8250_port ite_uart_port[] = { + { + .irq = IRQ_ITESER, /* interrupt number */ + .uartclk = 115200 * 16, /* UART clock rate */ + .iotype = UPIO_MEM, /* UPIO_* */ + .flags = UPF_BOOT_AUTOCONF, + }, + {} +}; + +static struct platform_device iteuart_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = ite_uart_port, + }, +}; +#endif + +/* 2700G graphics */ +static u64 fb_dma_mask = ~(u64)0; + +static struct resource cmx270_2700G_resource[] = { + /* frame buffer memory including ODFB and External SDRAM */ + [0] = { + .start = MARATHON_PHYS, + .end = MARATHON_PHYS + 0x02000000, + .flags = IORESOURCE_MEM, + }, + /* Marathon registers */ + [1] = { + .start = MARATHON_PHYS + 0x03fe0000, + .end = MARATHON_PHYS + 0x03ffffff, + .flags = IORESOURCE_MEM, + }, +}; + +static unsigned long save_lcd_regs[10]; + +#define LB_TROTTLE_OFF (PXA_CS1_PHYS | (1 << 25)) +#define LB_TROTTLE_MAX (PXA_CS1_PHYS | (1 << 25) | (1 << 22)) +static int cmx270_marathon_probe(struct fb_info *fb) +{ + volatile unsigned long *cpld; + + cpld = (volatile unsigned long*)ioremap(LB_TROTTLE_OFF, 4); + + if ( !cpld ) { + return -ENODEV; + } + *cpld = 0; + iounmap((void*)cpld); + + + /* save PXA-270 pin settings before enabling 2700G */ + save_lcd_regs[0] = GPDR1; + save_lcd_regs[1] = GPDR2; + save_lcd_regs[2] = GAFR1_U; + save_lcd_regs[3] = GAFR2_L; + save_lcd_regs[4] = GAFR2_U; + + /* Disable PXA-270 on-chip controller driving pins */ + GPDR1 &= ~(0xfc000000); + GPDR2 &= ~(0x00c03fff); + GAFR1_U &= ~(0xfff00000); + GAFR2_L &= ~(0x0fffffff); + GAFR2_U &= ~(0x0000f000); + return 0; +} + +static int cmx270_marathon_remove(struct fb_info *fb) +{ + volatile unsigned long *cpld; + + cpld = (volatile unsigned long*)ioremap(LB_TROTTLE_MAX, 4); + + if ( !cpld ) { + return -ENODEV; + } + *cpld = 0; + iounmap((void*)cpld); + + GPDR1 = save_lcd_regs[0]; + GPDR2 = save_lcd_regs[1]; + GAFR1_U = save_lcd_regs[2]; + GAFR2_L = save_lcd_regs[3]; + GAFR2_U = save_lcd_regs[4]; + return 0; +} + +static struct mbxfb_platform_data cmx270_2700G_data = { + .xres = { + .min = 240, + .max = 1200, + .defval = 640, + }, + .yres = { + .min = 240, + .max = 1200, + .defval = 480, + }, + .bpp = { + .min = 16, + .max = 32, + .defval = 16, + }, + .memsize = 8*1024*1024, + .probe = cmx270_marathon_probe, + .remove = cmx270_marathon_remove, +}; + +static struct platform_device cmx270_2700G = { + .name = "mbx-fb", + .dev = { + .platform_data = &cmx270_2700G_data, + .dma_mask = &fb_dma_mask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(cmx270_2700G_resource), + .resource = cmx270_2700G_resource, + .id = -1, +}; + +/* platform devices */ +static struct platform_device *platform_devices[] __initdata = { + &cmx270_device_dm9k, + &cmx270_audio_device, + &cmx270_ts_device, + &cmx270_rtc_device, + &cmx270_2700G, +#ifdef CONFIG_PCI + &iteuart_device, +#endif +}; + +#ifdef CONFIG_PCI +/* + * Install handler for IT8152 IRQ. Yes, yes... we are way down the IRQ + * cascade which is not good for IRQ latency, but the hardware has been + * designed that way... + */ +static inline void cmx270_irq(int irq, struct pt_regs *regs) +{ + struct irqdesc *desc; + desc = irq_desc + irq; + desc->handle(irq, desc, regs); +} + +static void cmx270_irq_demux(unsigned int irq, struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned long pdcnimr, ldcnimr; + int pdcnirr, ldcnir; + + /* clear our parent irq */ + GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ); + + /* read pending IRQs in the chip registers and clear them */ + pdcnirr = IT8152_INTC_PDCNIRR; + ldcnir = IT8152_INTC_LDCNIRR; + IT8152_INTC_PDCNIRR = ~pdcnirr; + IT8152_INTC_LDCNIRR = ~ldcnir; + + /* mask ITE irqs */ + pdcnimr = IT8152_INTC_PDCNIMR; + ldcnimr = IT8152_INTC_LDCNIMR; + IT8152_INTC_PDCNIMR = 0xffff; + IT8152_INTC_LDCNIMR = 0xffff; + + pdcnirr &= (PCISERR_BIT | H2PTADR_BIT | H2PMAR_BIT | + PCI_INTD_BIT | PCI_INTC_BIT | PCI_INTB_BIT | PCI_INTA_BIT | + USB_INT_BIT | CDMA_INT_BIT); + + ldcnir &= ITESER_BIT; + + IT8152_INTC_PDCNIRR = ~pdcnirr; + IT8152_INTC_LDCNIRR = ~ldcnir; + + /* are there interrupts pending ? */ + if( (pdcnirr | ldcnir) ) { + if (pdcnirr) { + if( pdcnirr & PCISERR_BIT ) + cmx270_irq(PCISERR, regs); + if( pdcnirr & H2PTADR_BIT ) + cmx270_irq(H2PTADR, regs); + if( pdcnirr & H2PMAR_BIT ) + cmx270_irq(H2PMAR, regs); + if( pdcnirr & PCI_INTA_BIT ) + cmx270_irq(PCI_INTA, regs); + if( pdcnirr & PCI_INTB_BIT ) + cmx270_irq(PCI_INTB, regs); + if( pdcnirr & PCI_INTC_BIT ) + cmx270_irq(PCI_INTC, regs); + if( pdcnirr & PCI_INTD_BIT ) + cmx270_irq(PCI_INTD, regs); + if( pdcnirr & USB_INT_BIT ) + cmx270_irq(USB_INT, regs); + if( pdcnirr & CDMA_INT_BIT ) + cmx270_irq(CDMA_INT, regs); + } + if(ldcnir) { + if( ldcnir & ITESER_BIT ) + cmx270_irq(IRQ_ITESER, regs); + } + } + + /* re-enable ITE interrupts */ + IT8152_INTC_PDCNIMR = pdcnimr; + IT8152_INTC_LDCNIMR = ldcnimr; +} +#else +unsigned long it8152_base_address = CMX270_IT8152_VIRT; +#endif + +#define CMX270_FLASH_VIRT (CMX270_IDE104_VIRT + PXA_CS_SIZE - (8<<20)) +/* Map PCI companion and IDE/General Purpose CS statically */ +static struct map_desc cmx270_io_desc[] __initdata = { + [0] = { /* IDE/general purpose space */ + .virtual = CMX270_IDE104_VIRT, + .pfn = __phys_to_pfn(CMX270_IDE104_PHYS), + .length = PXA_CS_SIZE - (8<<20), + .type = MT_DEVICE + }, + [1] = { /* NOR flash */ + .virtual = CMX270_FLASH_VIRT, + .pfn = __phys_to_pfn(PXA_CS0_PHYS), + .length = (8<<20), /* up to 8 MByte flash */ + .type = MT_DEVICE + }, + [2] = { /* PCI bridge */ + .virtual = CMX270_IT8152_VIRT, + .pfn = __phys_to_pfn(CMX270_IT8152_PHYS), + .length = PXA_CS_SIZE, + .type = MT_DEVICE + }, +}; + +/*********************** Display definitions ****************************/ +static int mtype=MTYPE_CRT640x480; +static int mbpp=-1; + +struct cmx270_display_info { + struct pxafb_mach_info fb_info; + char *display_name; +}; + +static struct __initdata cmx270_display_info cmx270_displays[] = { + [ MTYPE_STN320x240 ] = { + .fb_info = { + .pixclock = 76923, + .bpp = 8, + .xres = 320, + .yres = 240, + .hsync_len = 3, + .vsync_len = 2, + .left_margin = 3, + .upper_margin = 0, + .right_margin = 3, + .lower_margin = 0, + .sync = (FB_SYNC_HOR_HIGH_ACT | + FB_SYNC_VERT_HIGH_ACT), + .lccr0 = 0, + .lccr3 = (LCCR3_PixClkDiv(0x03) | + LCCR3_Acb(0xff) | + LCCR3_PCP), + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + }, + .display_name = "STN 320x240", + }, + [ MTYPE_TFT640x480 ] = { + .fb_info = { + .pixclock = 38461, + .bpp = 8, + .xres = 640, + .yres = 480, + .hsync_len = 60, + .vsync_len = 2, + .left_margin = 70, + .upper_margin = 10, + .right_margin = 70, + .lower_margin = 5, + .sync = 0, + .lccr0 = (LCCR0_PAS), + .lccr3 = (LCCR3_PixClkDiv(0x01) | + LCCR3_Acb(0xff) | + LCCR3_PCP), + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + }, + .display_name = "TFT 640x480", + }, + [ MTYPE_CRT640x480 ] = { + .fb_info = { + .pixclock = 38461, + .bpp = 8, + .xres = 640, + .yres = 480, + .hsync_len = 63, + .vsync_len = 2, + .left_margin = 81, + .upper_margin = 33, + .right_margin = 16, + .lower_margin = 10, + .sync = (FB_SYNC_HOR_HIGH_ACT | + FB_SYNC_VERT_HIGH_ACT), + .lccr0 = (LCCR0_PAS), + .lccr3 = (LCCR3_PixClkDiv(0x01) | + LCCR3_Acb(0xff)), + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + }, + .display_name = "CRT 640x480", + }, + [ MTYPE_CRT800x600 ] = { + .fb_info = { + .pixclock = 28846, + .bpp = 8, + .xres = 800, + .yres = 600, + .hsync_len = 63, + .vsync_len = 2, + .left_margin = 26, + .upper_margin = 21, + .right_margin = 26, + .lower_margin = 11, + .sync = (FB_SYNC_HOR_HIGH_ACT | + FB_SYNC_VERT_HIGH_ACT), + .lccr0 = (LCCR0_PAS), + .lccr3 = (LCCR3_PixClkDiv(0x02) | + LCCR3_Acb(0xff)), + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + }, + .display_name = "CRT 800x600", + }, + [ MTYPE_CRT1024x768 ] = { + .fb_info = { + .pixclock = 0, + .xres = 0, + .yres = 0, + }, + .display_name = "CRT 1024x768", + }, + [ MTYPE_USER_DEFINED ] = { + .fb_info = { + .pixclock = LCD_PIXCLOCK, + .bpp = LCD_BPP, + .xres = LCD_XRES, + .yres = LCD_YRES, + .hsync_len = LCD_HORIZONTAL_SYNC_PULSE_WIDTH, + .vsync_len = LCD_VERTICAL_SYNC_PULSE_WIDTH, + .left_margin = LCD_BEGIN_OF_LINE_WAIT_COUNT, + .upper_margin = LCD_BEGIN_FRAME_WAIT_COUNT, + .right_margin = LCD_END_OF_LINE_WAIT_COUNT, + .lower_margin = LCD_END_OF_FRAME_WAIT_COUNT, + .sync = LCD_SYNC, + .lccr0 = LCD_LCCR0, + .lccr3 = LCD_LCCR3, + .cmap_greyscale = CMAP_GREYSCALE, + .cmap_inverse = CMAP_INVERSE, + .cmap_static = CMAP_STATIC, + }, + .display_name = LCD_NAME, + }, + [ MTYPE_TFT320x240 ] = { + .fb_info = { + .pixclock = 134615, + .bpp = 16, + .xres = 320, + .yres = 240, + .hsync_len = 63, + .vsync_len = 7, + .left_margin = 75, + .upper_margin = 0, + .right_margin = 15, + .lower_margin = 15, + .sync = 0, + .lccr0 = (LCCR0_PAS), + .lccr3 = (LCCR3_PixClkDiv(0x06) | + LCCR3_Acb(0xff) | + LCCR3_PCP), + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + }, + .display_name = "TFT 320x240", + }, + [ MTYPE_STN640x480 ] = { + .fb_info = { + .pixclock = 57692, + .bpp = 8, + .xres = 640, + .yres = 480, + .hsync_len = 4, + .vsync_len = 2, + .left_margin = 10, + .upper_margin = 5, + .right_margin = 10, + .lower_margin = 5, + .sync = (FB_SYNC_HOR_HIGH_ACT | + FB_SYNC_VERT_HIGH_ACT), + .lccr0 = 0, + .lccr3 = (LCCR3_PixClkDiv(0x02) | + LCCR3_Acb(0xff)), + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + }, + .display_name = "STN 640x480", + }, +}; + +static int __init monitor_params(char *str) +{ + mtype = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("monitor=", monitor_params); + +static int __init fb_bpp(char *str) +{ + mbpp = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("bpp=", fb_bpp); + +/* PXA27x OHCI controller setup */ +static int cmx270_ohci_init(struct device *dev) +{ + /* Set the Power Control Polarity Low */ + UHCHR = (UHCHR | UHCHR_PCPL) & + ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE); + + return 0; +} + +static struct pxaohci_platform_data cmx270_ohci_platform_data = { + .port_mode = PMM_PERPORT_MODE, + .init = cmx270_ohci_init, +}; + + +static int cmx270_mci_init(struct device *dev, irqreturn_t (*mstone_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + + /* + * setup GPIO for PXA27x MMC controller + */ + pxa_gpio_mode(GPIO32_MMCCLK_MD); + pxa_gpio_mode(GPIO112_MMCCMD_MD); + pxa_gpio_mode(GPIO92_MMCDAT0_MD); + pxa_gpio_mode(GPIO109_MMCDAT1_MD); + pxa_gpio_mode(GPIO110_MMCDAT2_MD); + pxa_gpio_mode(GPIO111_MMCDAT3_MD); + + /* SB-X270 uses GPIO105 as SD power enable */ + pxa_gpio_mode(105 | GPIO_OUT); + + /* card detect IRQ on GPIO 83 */ + pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ)); + set_irq_type(CMX270_MMC_IRQ, IRQT_FALLING); + + err = request_irq(CMX270_MMC_IRQ, mstone_detect_int, SA_INTERRUPT, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "cmx270_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + + return 0; +} + +static void cmx270_mci_setpower(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) { + printk(KERN_DEBUG "%s: on\n", __FUNCTION__); + GPCR(105) = GPIO_bit(105); + } else { + GPSR(105) = GPIO_bit(105); + printk(KERN_DEBUG "%s: off\n", __FUNCTION__); + } +} + +static void cmx270_mci_exit(struct device *dev, void *data) +{ + free_irq(CMX270_MMC_IRQ, data); +} + +static struct pxamci_platform_data cmx270_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = cmx270_mci_init, + .setpower = cmx270_mci_setpower, + .exit = cmx270_mci_exit, +}; + + +#ifdef CONFIG_PM +/* timeout for RTC wakeup */ +unsigned int cmx270_suspend_timeout; + +static ssize_t timeout_show(struct subsystem * subsys, char * buf) +{ + char * s = buf; + + s += sprintf(s,"%d seconds\n", cmx270_suspend_timeout); + return (s - buf); +} + +static ssize_t timeout_store(struct subsystem * subsys, const char * buf, size_t n) +{ + char *endp = 0; + int timeout; + + timeout = simple_strtoul(buf, &endp, 10); + if ( *endp && *endp != '\n') + return -EINVAL; + + cmx270_suspend_timeout = timeout; + return n; +} + +static struct subsys_attribute timeout_attr = { + .attr = { + .name = __stringify(timeout), + .mode = 0644, + }, + .show = timeout_show, + .store = timeout_store, +}; + +static struct attribute * g[] = { + &timeout_attr.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = g, +}; + +extern struct subsystem power_subsys; +static unsigned long sleep_save_ite[10]; +static unsigned long sleep_save_msc[10]; + +static int cmx270_suspend(struct sys_device *dev, pm_message_t state) +{ +#ifdef CONFIG_PCI + /* save ITE state */ + sleep_save_ite[0] = IT8152_INTC_PDCNIMR; + sleep_save_ite[1] = IT8152_INTC_LPCNIMR; + sleep_save_ite[2] = IT8152_INTC_LPNIAR; + + /* Clear ITE IRQ's */ + IT8152_INTC_PDCNIRR = 0; + IT8152_INTC_LPCNIRR = 0; +#endif + + /* save MSC registers */ + sleep_save_msc[0] = MSC0; + sleep_save_msc[1] = MSC1; + sleep_save_msc[2] = MSC2; + + /* setup power saving mode registers */ + PCFR = 0x0; + PSLR = 0xff400000; + PMCR = 0x00000005; + PWER = 0x80000000; + PFER = 0x00000000; + PRER = 0x00000000; + PGSR0 = 0xC0018800; + PGSR1 = 0x004F0002; + PGSR2 = 0x6021C000; + PGSR3 = 0x00020000; + + if ( cmx270_suspend_timeout ) { + RTAR = RCNR + cmx270_suspend_timeout; + cmx270_suspend_timeout = 0; + } + + return 0; +} + +static int cmx270_resume(struct sys_device *dev) +{ +#ifdef CONFIG_PCI + /* restore IT8152 state */ + IT8152_INTC_PDCNIMR = sleep_save_ite[0]; + IT8152_INTC_LPCNIMR = sleep_save_ite[1]; + IT8152_INTC_LPNIAR = sleep_save_ite[2]; +#endif + + /* restore MSC registers */ + MSC0 = sleep_save_msc[0]; + MSC1 = sleep_save_msc[1]; + MSC2 = sleep_save_msc[2]; + + return 0; +} + +static struct sysdev_class cmx270_pm_sysclass = { + set_kset_name("pm"), + .resume = cmx270_resume, + .suspend = cmx270_suspend, +}; + +static struct sys_device cmx270_pm_device = { + .cls = &cmx270_pm_sysclass, +}; + +static int __init cmx270_pm_init(void) +{ + int error; + error = sysdev_class_register(&cmx270_pm_sysclass); + if (error == 0) + error = sysdev_register(&cmx270_pm_device); + + error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group); + return error; +} +#else +static int __init cmx270_pm_init(void) { return 0; } +#endif + +/* SA1111 compatibiliy 8 bit read register needed for proper function + of ITE8152 UART */ +#define MEMC_SA1111 __REG(0x48000064) + +static void __init cmx270_init(void) +{ + /* set display timings for VGA 640x480 by default */ + struct cmx270_display_info *tfbi = &cmx270_displays[2]; + + MEMC_SA1111 = 0x3c; + + cmx270_pm_init(); + + if ( mtype >= 0 && mtype < ARRAY_SIZE(cmx270_displays) ) + tfbi = &cmx270_displays[mtype]; + + /* use default instead of unsupported displays */ + if ( tfbi->fb_info.pixclock == 0 && + tfbi->fb_info.xres == 0 && + tfbi->fb_info.yres == 0 ) { + printk(KERN_WARNING "CM-X270 does not support %s display\n", cmx270_displays[mtype].display_name); + tfbi = &cmx270_displays[2]; + } + + /* setup color depth */ + if( mtype == MTYPE_USER_DEFINED ) { + mbpp = tfbi->fb_info.bpp; + } + if( mbpp > 0 ) { + if( (mbpp!=1) && (mbpp!=2) && (mbpp!=4) && + (mbpp!=8) && (mbpp!=16)) { + printk(KERN_WARNING "Illegal BPP value " + "supplied, leaving default\n"); + mbpp = 8; + } + } + else mbpp = 8; + tfbi->fb_info.bpp = mbpp; + + printk(KERN_INFO "Running a %s display with %d bits per pixel\n", + tfbi->display_name, tfbi->fb_info.bpp); + set_pxa_fb_info(&tfbi->fb_info); + +#ifdef CONFIG_PCI + /* setup ITE8152 UART base addresses */ + ite_uart_port[0].membase = (void *)&IT8152_UART_BASE; + ite_uart_port[0].mapbase = IT8152_UART_BASE; +#endif + + /* register CM-X270 platform devices */ + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); + + /* set MCI and OHCI platform parameters */ + pxa_set_mci_info(&cmx270_mci_platform_data); + pxa_set_ohci_info(&cmx270_ohci_platform_data); + + /* This enables the STUART */ + pxa_gpio_mode(GPIO46_STRXD_MD); + pxa_gpio_mode(GPIO47_STTXD_MD); + + /* This enables the BTUART */ + pxa_gpio_mode(GPIO42_BTRXD_MD); + pxa_gpio_mode(GPIO43_BTTXD_MD); + pxa_gpio_mode(GPIO44_BTCTS_MD); + pxa_gpio_mode(GPIO45_BTRTS_MD); +} + +int machine_is_cmx270l(void) +{ + int is_l = 0; + volatile unsigned char *flash = + (volatile unsigned char *)(CMX270_FLASH_VIRT + 0x3ffe8UL); + char rev[10]; + int i; + + memset(rev, 0, 10); + for ( i = 0; i < 8; i++ ) + rev[i] = flash[i]; + if ( (rev[6] - '0') > 1 ) + is_l = 1; + + printk(KERN_DEBUG "%s: revision read: %s, is_l = %d\n", + __FUNCTION__, rev, is_l); + + return is_l; +} + +#ifdef CONFIG_PCI +static void cmx270_mask_irq(unsigned int irq) +{ + switch(irq) { + case IT8152_IRQ(0): + IT8152_INTC_PDCNIMR |= PCISERR_BIT; + break; + case IT8152_IRQ(1): + IT8152_INTC_PDCNIMR |= H2PTADR_BIT; + break; + case IT8152_IRQ(2): + IT8152_INTC_PDCNIMR |= H2PMAR_BIT; + break; + case IT8152_IRQ(3): + IT8152_INTC_PDCNIMR |= PCI_INTA_BIT; + break; + case IT8152_IRQ(4): + IT8152_INTC_PDCNIMR |= PCI_INTB_BIT; + break; + case IT8152_IRQ(5): + IT8152_INTC_PDCNIMR |= PCI_INTC_BIT; + break; + case IT8152_IRQ(6): + IT8152_INTC_PDCNIMR |= PCI_INTD_BIT; + break; + case IT8152_IRQ(7): + IT8152_INTC_PDCNIMR |= USB_INT_BIT; + break; + case IT8152_IRQ(9): + IT8152_INTC_PDCNIMR |= CDMA_INT_BIT; + break; + case IT8152_IRQ(10): + IT8152_INTC_LDCNIMR |= ITESER_BIT; + break; + } +} + +static void cmx270_unmask_irq(unsigned int irq) +{ + switch(irq) { + case IT8152_IRQ(0): + IT8152_INTC_PDCNIMR &= (~PCISERR_BIT); + break; + case IT8152_IRQ(1): + IT8152_INTC_PDCNIMR &= (~H2PTADR_BIT); + break; + case IT8152_IRQ(2): + IT8152_INTC_PDCNIMR &= (~H2PMAR_BIT); + break; + case IT8152_IRQ(3): + IT8152_INTC_PDCNIMR &= (~PCI_INTA_BIT); + break; + case IT8152_IRQ(4): + IT8152_INTC_PDCNIMR &= (~PCI_INTB_BIT); + break; + case IT8152_IRQ(5): + IT8152_INTC_PDCNIMR &= (~PCI_INTC_BIT); + break; + case IT8152_IRQ(6): + IT8152_INTC_PDCNIMR &= (~PCI_INTD_BIT); + break; + case IT8152_IRQ(7): + IT8152_INTC_PDCNIMR &= (~USB_INT_BIT); + break; + case IT8152_IRQ(9): + IT8152_INTC_PDCNIMR &= (~CDMA_INT_BIT); + break; + case IT8152_IRQ(10): + IT8152_INTC_LDCNIMR &= (~ITESER_BIT); + break; + } +} + +static struct irqchip cmx270_irq_chip = { + .ack = cmx270_mask_irq, + .mask = cmx270_mask_irq, + .unmask = cmx270_unmask_irq, +}; +#endif + +static void __init cmx270_init_irq(void) +{ + int irq; + + pxa_init_irq(); + + /* LED and NAND GPIOs should not be probed for IRQ */ + irq_desc[IRQ_GPIO(11)].probe_ok = 0; + irq_desc[IRQ_GPIO(89)].probe_ok = 0; + irq_desc[IRQ_GPIO(93)].probe_ok = 0; + irq_desc[IRQ_GPIO(94)].probe_ok = 0; + + IT8152_INTC_PDCNIMR = 0xffff; + +#ifdef CONFIG_PCI + /* Disable and clear IRQ's for ITE8152 */ + IT8152_INTC_PDCNIMR = 0xffff; + IT8152_INTC_PDCNIRR = 0; + IT8152_INTC_LPCNIMR = 0xffff; + IT8152_INTC_LPCNIRR = 0; + IT8152_INTC_LDCNIMR = 0xffff; + IT8152_INTC_LDCNIRR = 0; + + /* Set IT8152 serial port IRQ as active high*/ + IT8152_INTC_LDNIAR |= ITESER_BIT; + + for(irq = IT8152_IRQ(0); irq <= IT8152_IRQ_MAX; irq++) { + set_irq_chip(irq, &cmx270_irq_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + /* INTC signal from IT8152 is connected to GPIO0 */ + pxa_gpio_mode(IRQ_GPIO_IT8152_IRQ); + set_irq_chained_handler(IRQ_GPIO_IT8152_IRQ, cmx270_irq_demux); + set_irq_type(IRQ_GPIO_IT8152_IRQ, IRQT_RISING); +#endif + + /* Setup interrupt for dm9000 */ + pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ)); + set_irq_type(CMX270_ETHIRQ, IRQT_RISING); + + /* Setup interrupt for 2700G */ + pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ)); + set_irq_type(CMX270_GFXIRQ, IRQT_FALLING); +} + +static void __init cmx270_map_io(void) +{ + pxa_map_io(); + iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc)); +} + + +MACHINE_START(ARMCORE, "Compulab CM-x270") + .boot_params = 0xa0000100, + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .map_io = cmx270_map_io, + .init_irq = cmx270_init_irq, + .timer = &pxa_timer, + .init_machine = cmx270_init, +MACHINE_END diff --git a/arch/arm/mach-pxa/it8152.c b/arch/arm/mach-pxa/it8152.c new file mode 100644 index 0000000..91bb49c --- /dev/null +++ b/arch/arm/mach-pxa/it8152.c @@ -0,0 +1,248 @@ +/* + * arch/arm/common/it8152.c: PCI functions for IT8152 + * + * Compulab Ltd, 2002-2006 + * + * The DMA bouncing is taken from arch/arm/mach-ixp4xx/common-pci.c + * (see this file for respective copyrights) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#define MAX_SLOTS 21 + +static unsigned long +it8152_pci_dev_base_address(struct pci_bus *bus, unsigned int devfn) +{ + unsigned long addr = 0; + + if (bus->number == 0) { + if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) + addr = (devfn << 8); + } else + addr = (bus->number << 16) | (devfn << 8); + + return addr; +} + +static int +it8152_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) +{ + unsigned long addr = it8152_pci_dev_base_address(bus, devfn); + u32 v; + int shift; + +#ifdef CONFIG_MACH_ARMCORE + if(devfn!=0) IT8152_GPIO_GPLR=0x00; +#endif + shift = (where & 3); + + IT8152_PCI_CFG_ADDR = (addr + where); + v = (IT8152_PCI_CFG_DATA >> (8 * (shift))); + + *value = v; + +#ifdef CONFIG_MACH_ARMCORE + if(devfn!=0) IT8152_GPIO_GPLR=0x20; +#endif + + return PCIBIOS_SUCCESSFUL; +} + + +static int +it8152_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) +{ + unsigned long addr = it8152_pci_dev_base_address(bus, devfn); + u32 v, vtemp, mask=0; + int shift; + +#ifdef CONFIG_MACH_ARMCORE + if(devfn!=0) IT8152_GPIO_GPLR=0x00; +#endif + + if(size==1) mask=0xff; + if(size==2) mask=0xffff; + + shift = (where & 3); + + IT8152_PCI_CFG_ADDR = addr + where; + vtemp = IT8152_PCI_CFG_DATA; + + if(mask) vtemp &= ~(mask << (8 * shift)); + else vtemp = 0; + + v = (value << (8 * shift)); + IT8152_PCI_CFG_ADDR = addr + where; + IT8152_PCI_CFG_DATA = (v | vtemp); + +#ifdef CONFIG_MACH_ARMCORE + if(devfn!=0) IT8152_GPIO_GPLR=0x20; +#endif + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops it8152_ops = { + .read = it8152_pci_read_config, + .write = it8152_pci_write_config, +}; + +static struct resource it8152_io = { + .name = "IT8152 PCI I/O region", + .flags = IORESOURCE_IO, +}; + +static struct resource it8152_mem1 = { + .name = "First IT8152 PCI memory region", + .start = 0x10000000, + .end = 0x13e00000, + .flags = IORESOURCE_MEM, +}; + +/* + * The following functions are needed for DMA bouncing. + * ITE8152 chip can addrees up to 64MByte, so all the devices + * connected to ITE8152 (PCI and USB) should have limited DMA window + */ + +/* + * Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all + * other devices. + */ +static int it8152_pci_platform_notify(struct device *dev) +{ + if ( dev->bus == &pci_bus_type ) { + if ( dev->dma_mask ) + *dev->dma_mask = SZ_64M - 1; + dev->coherent_dma_mask = SZ_64M - 1; + dmabounce_register_dev(dev, 2048, 4096); + } + return 0; +} + +static int it8152_pci_platform_notify_remove(struct device *dev) +{ + if ( dev->bus == &pci_bus_type ) { + dmabounce_unregister_dev(dev); + } + return 0; +} + +int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) +{ + dev_dbg(dev, "%s: dma_addr %08x, size %08x\n", + __FUNCTION__, dma_addr, size); + return (dev->bus == &pci_bus_type ) && + ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); +} + +/* + * Only first 64MB of memory can be accessed via PCI. + * We use GFP_DMA to allocate safe buffers to do map/unmap. + * This is really ugly and we need a better way of specifying + * DMA-capable regions of memory. + */ +void __init it8152_adjust_zones(int node, unsigned long *zone_size, + unsigned long *zhole_size) +{ + unsigned int sz = SZ_64M >> PAGE_SHIFT; + + /* + * Only adjust if > 64M on current system + */ + if (node || (zone_size[0] <= sz)) + return; + + zone_size[1] = zone_size[0] - sz; + zone_size[0] = sz; + zhole_size[1] = zhole_size[0]; + zhole_size[0] = 0; +} + +/* + * We override these so we properly do dmabounce otherwise drivers + * are able to set the dma_mask to 0xffffffff and we can no longer + * trap bounces. :( + * + * We just return true on everyhing except for < 64MB in which case + * we will fail miseralby and die since we can't handle that case. + */ +int +pci_set_dma_mask(struct pci_dev *dev, u64 mask) +{ + if (mask >= SZ_64M - 1 ) + return 0; + + return -EIO; +} + +int +pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) +{ + if (mask >= SZ_64M - 1 ) + return 0; + + return -EIO; +} + +EXPORT_SYMBOL(pci_set_dma_mask); +EXPORT_SYMBOL(pci_set_consistent_dma_mask); + + +int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) +{ + it8152_io.start = IT8152_IO_BASE + 0x12000; + it8152_io.end = IT8152_IO_BASE + 0x100000; + + if (request_resource(&ioport_resource, &it8152_io)) { + printk(KERN_ERR "PCI: unable to allocate IO region\n"); + return -EBUSY; + } + if (request_resource(&iomem_resource, &it8152_mem1)) { + printk(KERN_ERR "PCI: unable to allocate memory region\n"); + return -EBUSY; + } + + sys->resource[0] = &it8152_io; + sys->resource[1] = &it8152_mem1; + + if (platform_notify || platform_notify_remove) { + printk(KERN_ERR "PCI: Can't use platform_notify\n"); + return -EBUSY; + } + + platform_notify = it8152_pci_platform_notify; + platform_notify_remove = it8152_pci_platform_notify_remove; + + return 1; +} + + +struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys) +{ + return pci_scan_bus(nr, &it8152_ops, sys); +} + diff --git a/arch/arm/mach-pxa/leds-cm-x270.c b/arch/arm/mach-pxa/leds-cm-x270.c new file mode 100644 index 0000000..5402b69 --- /dev/null +++ b/arch/arm/mach-pxa/leds-cm-x270.c @@ -0,0 +1,134 @@ +/* + * linux/arch/arm/mach-pxa/leds-cm-x270.c + * + * Compulab Ltd., 2003 + * + * Original (leds-footbridge.c) by Russell King + * + * Macros for actual LED manipulation should be in machine specific + * files in this 'mach' directory. + */ + + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "leds.h" + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +#define RED_LED_ON 1 +#define GREEN_LED_ON 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +void armcore_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = GREEN_LED_ON | RED_LED_ON; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = GREEN_LED_ON | RED_LED_ON; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = GREEN_LED_ON | RED_LED_ON; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= GREEN_LED_ON; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~RED_LED_ON; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= RED_LED_ON; + break; +#endif + + case led_halted: + break; + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~GREEN_LED_ON; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= GREEN_LED_ON; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~RED_LED_ON; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= RED_LED_ON; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + { + if(hw_led_state & RED_LED_ON) { + CMX270_RED_ON(); +// printk("Red on\n"); + } + else { +// printk("Red off\n"); + CMX270_RED_OFF(); + } + if(hw_led_state & GREEN_LED_ON) { +// printk("Green on\n"); + CMX270_GREEN_ON(); + } + else { +// printk("Green off\n"); + CMX270_GREEN_OFF(); + } + } + + local_irq_restore(flags); +} diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c index bbe4d5f..a27d027 100644 --- a/arch/arm/mach-pxa/leds.c +++ b/arch/arm/mach-pxa/leds.c @@ -24,6 +24,8 @@ pxa_leds_init(void) leds_event = mainstone_leds_event; if (machine_is_pxa_idp()) leds_event = idp_leds_event; + if (machine_is_armcore()) + leds_event = armcore_leds_event; leds_event(led_start); return 0; diff --git a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h index d98f6e9..0dcc346 100644 --- a/arch/arm/mach-pxa/leds.h +++ b/arch/arm/mach-pxa/leds.h @@ -10,3 +10,4 @@ extern void idp_leds_event(led_event_t evt); extern void lubbock_leds_event(led_event_t evt); extern void mainstone_leds_event(led_event_t evt); +extern void armcore_leds_event(led_event_t evt); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 3baa708..823c32d 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -140,10 +140,12 @@ void pxa_cpu_pm_enter(suspend_state_t st extern void pxa_cpu_suspend(unsigned int); extern void pxa_cpu_resume(void); +#ifndef CONFIG_MACH_ARMCORE if (state == PM_SUSPEND_STANDBY) CKEN = CKEN22_MEMC | CKEN9_OSTIMER | CKEN16_LCD |CKEN0_PWM0; else CKEN = CKEN22_MEMC | CKEN9_OSTIMER; +#endif /* ensure voltage-change sequencer not initiated, which hangs */ PCFR &= ~PCFR_FVC; @@ -158,7 +160,11 @@ void pxa_cpu_pm_enter(suspend_state_t st case PM_SUSPEND_MEM: /* set resume return address */ PSPR = virt_to_phys(pxa_cpu_resume); +#ifdef CONFIG_MACH_ARMCORE + pxa_cpu_suspend(PWRMODE_DEEPSLEEP); +#else pxa_cpu_suspend(PWRMODE_SLEEP); +#endif break; } } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 8b13316..8ffaad0 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -453,4 +453,9 @@ config ATA_OVER_ETH This driver provides Support for ATA over Ethernet block devices like the Coraid EtherDrive (R) Storage Blade. +config ARMCORE_FLASH + tristate "ARMCORE flash drivers" + depends on MACH_ARMCORE + source "drivers/block/cl_flash/Kconfig" + endmenu diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 3ec1f8d..ebeb4c6 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_VIODASD) += viodasd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o obj-$(CONFIG_BLK_DEV_UB) += ub.o +obj-$(CONFIG_ARMCORE_FLASH) += cl_flash/ diff --git a/drivers/block/cl_flash/CL_Logic.h b/drivers/block/cl_flash/CL_Logic.h new file mode 100644 index 0000000..fe3e8d7 --- /dev/null +++ b/drivers/block/cl_flash/CL_Logic.h @@ -0,0 +1,245 @@ +/* Module: CL_Logic.h + Author: Vova Lifliand + Description: Controls Nand flash management logic + Notes: +*/ + +#ifndef __CL_LOGIC__ +#define __CL_LOGIC__ +/*#define CL_NAND_BIG_DELAYS*/ +#if defined(FLASH_PLATFORM_LINUX) || defined(FLASH_PLATFORM_ARMonitor) +/* Structure packaging */ + #define PACKAGE __attribute__ ((packed,aligned(1))) + #define CL_ST static +#else + #define PACKAGE + #define CL_ST +#endif + #define FAR + #define far +/* NOR Flash management constants */ +#define CL_NOR_FLASH_PAGE_SIZE 512 /* bytes */ + +#ifdef FLASH_PLATFORM_DOS + #define cl_error_log(x,...){} +#endif /* MS-DOS */ +/* Nand Flash management constants */ + +/* Page size must not be changed because this value is also used for + page size of Nand flash */ +/*#define CL_FLASH_PAGE_SIZE 512 // bytes */ +#define CL_FLASH_MAXIMUM_PAGE_SIZE 2048/* bytes */ +#define CL_FLASH_MINIMAL_SECTOR_SIZE 512 /* Sectors can't be less than 512 bytes */ +/*#define CL_FLASH_SPARE_AREA_SIZE 16 // bytes */ +/*#define CL_FLASH_MAXIMUM_SPARE_AREA_SIZE 128 bytes - twice the needed for biggest + flash today 2004/05 */ +#define CL_FLASH_MAXIMUM_SPARE_AREA_SIZE 128 /*Stingy with space...*/ + +/* Maximum blocks number in flash - adjust according to maximum flash size */ +#define CL_MAX_BLKS_NUMBER 8192 /* good for 128MB flash */ + /* Good up to 512 MB flash, if 64kb is the smallest block */ +/* Number of pages in Nand flash block */ +/* #define CL_FLASH_PAGES_PER_NAND_BLK 32 */ +/* Maximum Number of pages in Nand flash block */ +#define CL_FLASH_MAXIMUM_PAGES_PER_NAND_BLK 128 /* 32 */ /* Can't be more than 255 + to fit in unsigned char arrays*/ +/* Number of pages to make free */ +#define CL_FLASH_FREE_PAGE_PER_BLK 1 +/* Usable pages per 16 KB Nand flash block */ +/*#define CL_FLASH_USE_PAGE_PER_BLK (CL_FLASH_PAGES_PER_NAND_BLK - CL_FLASH_FREE_PAGE_PER_BLK)*/ +#define CL_FLASH_USE_PAGE_PER_BLK (flogic->nand->pages_per_block - CL_FLASH_FREE_PAGE_PER_BLK) +/* Number of logical to physical page translation tables stored in memory + Each table size is ~40 bytes */ +#define CL_LTF_PAGE_TBLS 30 +/* Always leave a number of blocks unused - just for sure */ +#define CL_EXTRA_SPARE_BLKS 10 +/* Define maximum number of different blocks with cached pages */ +#define CL_MAX_CACHED_BLKS 4 +/* Number of erases per one launching of anti wearing procedure */ +#define CL_ERASE_PER_ANTI_WEARING 1000 + + +#define CLBYTEPTR unsigned char far* + + +/* Flash mapping and accessing interface */ +typedef struct PACKAGE cl_nand_map_if_t +{ + /* Destroy function must free all allocated resources (such as virtual memory) */ + void (*init) (void); + void (*destroy) (void); + /* Chip select operation. When on = 1: chip select, on = 0: disable chip select */ + /* need_auto_operation - Whe the ON is false, the pin is expected to pulse in accordance + with bus transactions. This function exists on x86, but not on ARM */ + void (*chip_select) (int on, int need_auto_operation); + /* Reading from flash (HW read access, not actual data reading) */ + unsigned char (*readb) (unsigned char offset); + /* Writing to flash (HW write access, not actual data writing) */ + void (*writeb) (unsigned char offset, unsigned char data); + /* Reads block from flash: reads data from address 0 while incrementing data pointer */ + void (*blockread) (CLBYTEPTR data, int count); + /* Writes block to flash: writes data to address 0 while incrementing data pointer */ + void (*blockwrite) ( CLBYTEPTR data, int count); + /* Turns on/off activity indication leds */ + void (*activity_leds) (short operation, short reclaim); + /* Performs specified delay (parameter in microsecond units) */ + int (*sleep) (unsigned long microseconds); + /* Wait for completion using R/B line */ + /* Use microseconds, if R/B line not implemented */ + int (*rbwait) (unsigned long microseconds); +} cl_nand_map_if; + + +/* Internal flash logic structure */ +typedef struct cl_logic_t far*cl_logic; + + +/* Parameter retrive enum */ +typedef enum +{ + CL_FLASH_TOTAL_SIZE, /* Total size of the flash in bytes */ + CL_FLASH_HEADS_NUM, /* Number of heads */ + CL_FLASH_SECTOR_SIZE = 512, /* Sector size (in bytes) =512 - is legacy for ARMonitor only*/ + CL_FLASH_SECTORS_NUM, /* Number of sectors per tracks */ + CL_FLASH_CYLINDERS_NUM, /* Number of cylinders */ + CL_FLASH_PAGE_SIZE, /* Size of the page without spare area */ + CL_FLASH_READ_PAGE_CNT, /* Read page operations count */ + CL_FLASH_WRITE_PAGE_CNT, /* Write page operations count */ + CL_FLASH_RECLAIM_CNT, /* Reclaim block count */ + CL_FLASH_BURSTS_NUM, /* Bursts of length 'var' numbers */ + CL_FLASH_ERASE_CNT, /* Erase cnt of block specified by 'var' */ + CL_FLASH_BAD_BLOCK_CNT, +} PACKAGE cl_logic_param; + +/* Direct access type enum */ +typedef enum +{ + CL_FLASH_READ_PAGE, + CL_FLASH_READ_SPARE_AREA, + CL_FLASH_READ_BLK_SPARES, /* All spare areas of specified block */ + CL_FLASH_WRITE_PAGE, + CL_FLASH_WRITE_SPARE_AREA, + CL_FLASH_ERASE_BLOCK /* Data ignored */ +} PACKAGE cl_nand_direct_access_type; + +/* memory access type enum */ +typedef enum //Memory areas usage is dscribed in separate document. +{ + CL_FLOGIC = 0, + CL_NAND, + CL_CACHE, + CL_CACHE_ORDERED_ARRAY, + CL_SP_AREA, + CL_SP_AREA_2, + CL_SP_AREA_3, + CL_PAGE, + CL_CACHE_REF +} PACKAGE cl_memory_region_name; + +#define NUMBER_OF_MEMORY_REGIONS 9 + + +typedef enum +{ + CL_FIRST_ALLOCATION_STAGE, + CL_SECOND_ALLOCATION_STAGE +}PACKAGE cl_memory_allocation_stages; + +typedef struct cl_memory_pointer_type +{ + void far* pMemory; + char IN_USE; +} PACKAGE cl_memory_pointer; + +void far* cl_memory_request (cl_memory_region_name mem_name); + +void cl_memory_return (cl_memory_region_name mem_name); + +/* Creates flash logic object and attaches it to specified HW nand flash. + cache_size is max. number of pages, the cache can hold. + The flash is formatted prior initialization if format != 0. + When formatting reseved blocks and bad are not erased. */ +cl_logic cl_logic_create (cl_nand_map_if* nand_if, long cache_size, int format, unsigned short sector_size); + +/* Removes flash logic object and frees all allocated resources. */ +void cl_logic_free (cl_logic flogic); + +/* Parameters retrival function. */ +long cl_logic_get_param (cl_logic flogic, cl_logic_param prm, long var); + +/* Read page command. */ +int cl_logic_read_page (cl_logic flogic, long fs_sectn, + CLBYTEPTR sector_data); + +/* Write page command. */ +int cl_logic_write_page (cl_logic flogic, long fs_pagen, + CLBYTEPTR page_data); + +/* Flushes too old cache. If force_one_flush is TRUE, at least one + cached block is flushed. */ +void cl_logic_on_idle (cl_logic flogic, int force_one_flush); + +/* Flushes all cached data to disk. */ +void cl_logic_sync (cl_logic flogic); + +/* Direct accessing commands */ +int cl_logic_direct_access (cl_logic flogic, cl_nand_direct_access_type type, + unsigned short block, unsigned char page, CLBYTEPTR data); + + +/* NOR Flash Disk Driver */ + +/* The header describes block information */ +typedef struct +{ + unsigned short Signature; /* 0x1998 for initialized blocks */ + unsigned short State; + unsigned short EraseCounter; + unsigned short PageIndex[128]; + unsigned short Unused[10]; + unsigned short BlockReserved; /* 0xFFFF - usable block, 0 - reserved block */ +} PACKAGE cl_nor_block_header; + +/* Abstract class for flash access */ +typedef struct +{ + /* Constructor */ + void (*Constructor)(void); + /* Destructor */ + void (*Destructor)(void); + /* Define flash access functions */ + /* Returns usable size */ + unsigned long (*GetSize)(void); + /* Remaps or unmaps MMS windows, allocated by flash */ + void (*EnableFlashMap)(int EnableFlag); + /* Returns number of usable pages, 512 bytes each. */ + /* Doesn't include first page that is used for header - signature, state . . . */ + int (*GetPagesPerBlock)(void); + /* Header */ + int (*ReadHeader)(unsigned short BlockN, cl_nor_block_header* Header); + /* The PageNum == 0 is first data page and not the header. Max. value of PageNum */ + /* is GetBlockSize() / BytesPerPage - 1 (min. is 0) */ + int (*ReadPage)(unsigned short BlockN, unsigned char PageNum, CLBYTEPTR DestBuff); + int (*SetBlockState) (unsigned short BlockN, unsigned short Signature, + unsigned short State, unsigned short Reserved); + /* Sets logical page index to zero - invalidates page. PageN is like in WritePage */ + int (*InvalidatePage)(unsigned short BlockN, unsigned char PageN); + /* BlockN and PageN - destination location, where PageN doesn't include header */ + /* information (PageN = 0 means first logical page and it's seconds physical page). */ + /* PageIndex is physical page number for further identification (by ReadHeader) */ + int (*WritePage)(unsigned short BlockN, unsigned char PageN, + const CLBYTEPTR PageData, unsigned short PageIndex); + int (*EraseBlock)(unsigned short BlockN); +} PACKAGE cl_nor_flash_access; + +/* Define flash access functions */ +int cl_nor_init_flash (void); +int cl_nor_free_mem (void); +int cl_nor_format_flash (int (*ProgressCallback)(int Percentage)); +int cl_nor_write_page (int PageIndex, CLBYTEPTR Data); +int cl_nor_read_page (int PageIndex, CLBYTEPTR Data); +int cl_nor_get_disk_param (unsigned long* TotalPage, unsigned long* BytesPerPage, + unsigned long* Cylinders, unsigned long* PagesPerTrk, + unsigned long* Heads); +#endif /* __CL_LOGIC__ */ + diff --git a/drivers/block/cl_flash/Kconfig b/drivers/block/cl_flash/Kconfig new file mode 100644 index 0000000..60aa80d --- /dev/null +++ b/drivers/block/cl_flash/Kconfig @@ -0,0 +1,11 @@ +# +# Block device driver configuration +# + +config ARMCORE_NOR + bool "CompuLab NOR flash driver" + depends on ARMCORE_FLASH +config ARMCORE_NAND + bool "CompuLab NAND flash driver" + depends on ARMCORE_FLASH + diff --git a/drivers/block/cl_flash/Makefile b/drivers/block/cl_flash/Makefile new file mode 100644 index 0000000..538cb2c --- /dev/null +++ b/drivers/block/cl_flash/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for Compulab flash disk driver +# + +EXTRA_CFLAGS += -DTARGET_ARM_CORE -DFLASH_PLATFORM_LINUX + +obj-$(CONFIG_ARMCORE_FLASH) += fdrv.o + +fdrv-y += cl_nordev.o cl_blkdev.o CL_FlashDrv + + +fdrv-$(CONFIG_MACH_ARMCORE) += cl_nanddev_x270.o diff --git a/drivers/block/cl_flash/cl_blkdev.c b/drivers/block/cl_flash/cl_blkdev.c new file mode 100644 index 0000000..adb030d --- /dev/null +++ b/drivers/block/cl_flash/cl_blkdev.c @@ -0,0 +1,731 @@ +/* + * Flash Disk Driver for Linux. + * Generic block device and genric disk implementation + * + * Copyright Compulab 2003-2006 (c). + */ + +#include +#include +#include +#include +#include +#include + +#include "CL_Logic.h" +#include "cl_blkdev.h" + +/* I/O Controls */ +#define CL_FLASH_IOC_MAGIC 'f' +#define CL_FLASH_IO_GET_PARAM _IOWR (CL_FLASH_IOC_MAGIC, 1, char[12]) +#define CL_FLASH_IO_DIRECT_ACCESS _IOWR (CL_FLASH_IOC_MAGIC, 2, char[524]) + +#define FLUSH_INTERVAL 100 + +struct cl_blkdev; + +struct flash_blkdev_ops { + /* timer for periodic flushes of NAND flash */ + void (*flush_proc)(void* dev); + + /* HW specific ioctl */ + int (*flash_hw_ioctl)(struct cl_blkdev *dev, struct inode *inode, + struct file *file, unsigned int cmd, + unsigned long arg); + + /* HW specific request handling */ + int (*do_flash_hw_request)(struct cl_blkdev *dev, struct request *q); + /* HW specific cleanups */ + int (*flash_hw_release)(struct cl_blkdev *dev, struct inode *inode, + struct file *file); +}; + +struct cl_blkdev_priv { + /* thread is dead indication */ + struct completion thread_dead; + /* flag to notify the thread that we are done */ + int exiting; + /* thread wait queue head for requests */ + wait_queue_head_t thread_wq; + /* block device request queue */ + struct request_queue *rq; + /* request queue lock */ + spinlock_t queue_lock; +}; + +struct cl_blkdev { + struct cl_blkdev_priv *blkdev_priv; + struct gendisk *flash_disk; + struct flash_blkdev_ops *ops; + struct semaphore sem; + char name[32]; + + int major; + void *hw_private; /* Low level hook */ + +#ifdef CONFIG_PROC_FS + /* proc entry */ + struct proc_dir_entry *pde; +#endif +}; + +#define FLASH_SECTOR 512 + +/* declarations of cl_mem_set etc */ +#include "cl_common.c" + + +/***************************************************************/ +/* Flash software write protect setup */ +/***************************************************************/ +unsigned long wpstart=0, wpend=0; + +static int __init wpstart_det(char *str) /*30-May-04, interrupts */ +{ + wpstart = simple_strtol(str, NULL, 0); + return 1; +} + +static int __init wpend_det(char *str) /*30-May-04, interrupts */ +{ + wpend = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("wpstart=", wpstart_det); +__setup("wpend=", wpend_det); + + +/***************************************************************/ +/* generic block device interface */ +/***************************************************************/ +/* cl_blkdev_open: open a device */ +static int cl_blkdev_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int cl_blkdev_check_media_change(struct gendisk* dev) +{ + return 0; /* Disk not changed */ +} + +static int cl_blkdev_revalidate(struct gendisk* dev) +{ + return 0; +} + +/* cl_blkdev_release: release the device */ +static int cl_blkdev_release(struct inode *inode, struct file *file) +{ + struct cl_blkdev *dev; + dev = inode->i_bdev->bd_disk->private_data; + + down (&dev->sem); + dev->ops->flash_hw_release(dev, inode, file); + up (&dev->sem); + + return 0; +} + +/* + cl_blkdev_ioctl: handle device ioctl's + common ioctls (if any) for NAND and NOR flash are handled here + then HW specific ioctl handler is invoked + */ +static int cl_blkdev_ioctl(struct inode *inode, + struct file *file, u_int cmd, u_long arg) +{ + struct cl_blkdev *dev; + + if ((!inode) || !(inode->i_rdev)) + return -EINVAL; + + dev = inode->i_bdev->bd_disk->private_data; + return dev->ops->flash_hw_ioctl(dev, inode, file, cmd, arg); +} + +static struct block_device_operations flash_fops = +{ + .owner = THIS_MODULE, + .open = cl_blkdev_open, + .release = cl_blkdev_release, + .ioctl = cl_blkdev_ioctl, + .media_changed = cl_blkdev_check_media_change, + .revalidate_disk = cl_blkdev_revalidate +}; + +static int cl_nand_request (struct cl_blkdev *_dev, struct request * req); + +/* wake up the flashdiskd thread to handle the request */ +static void do_cl_blkdev_request(struct request_queue *rq) +{ + struct cl_blkdev *dev = rq->queuedata; + wake_up(&dev->blkdev_priv->thread_wq); +} + +void cl_blkdev_suspend(struct cl_blkdev* dev) +{ + dev->ops->flush_proc(dev); +} + +/***************************************************************/ +/* flashdiskd thread is handling all transfer requests */ +/***************************************************************/ +static int cl_flashdisk_thread(void *arg) +{ + struct cl_blkdev *dev = (struct cl_blkdev*)arg; + struct request_queue *rq = dev->blkdev_priv->rq; + unsigned long flush_period = msecs_to_jiffies(FLUSH_INTERVAL); + unsigned long last_flush_jiffies = jiffies; + + current->flags |= PF_MEMALLOC/* | PF_NOFREEZE */; + daemonize("%sd", "flashdisk"); + + while (!dev->blkdev_priv->exiting) { + struct request *req; + int res = 0; + DECLARE_WAITQUEUE(wait, current); + + try_to_freeze(); + + spin_lock_irq(rq->queue_lock); + req = elv_next_request(rq); + + if (!req) { + add_wait_queue(&dev->blkdev_priv->thread_wq, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + spin_unlock_irq(rq->queue_lock); + + schedule(); + remove_wait_queue(&dev->blkdev_priv->thread_wq, &wait); + + continue; + } + + dev = req->rq_disk->private_data; + spin_unlock_irq(rq->queue_lock); + + down(&dev->sem); + res = dev->ops->do_flash_hw_request(dev, req); + + if ( jiffies - last_flush_jiffies > flush_period ) { + if ( dev->ops->flush_proc ) + dev->ops->flush_proc(dev); + last_flush_jiffies = jiffies; + } + up(&dev->sem); + + spin_lock_irq(rq->queue_lock); + end_request(req, res); + spin_unlock_irq(rq->queue_lock); + } + complete_and_exit(&dev->blkdev_priv->thread_dead, 0); +} + +/***************************************************************/ +/* block device initialization routines */ +/***************************************************************/ + +/* + cl_blkdev_init: + - initialize and register generic block device, + - initialize timers for peroidic flushes + - initialize thread syncronization data + - start request processing thread + + dev - preallocated device that should be initialized + ops - HW specific implementation of block device ioctl, do_request etc + name - device name +*/ +int cl_blkdev_init(struct cl_blkdev *dev, + struct flash_blkdev_ops *ops, const char *name) +{ + int ret; + + /* allocate the thread synchronization structure */ + dev->blkdev_priv = kmalloc(sizeof(*dev->blkdev_priv), GFP_KERNEL); + if (!dev->blkdev_priv) + return -ENOMEM; + memset(dev->blkdev_priv, 0, sizeof(*dev->blkdev_priv)); + + dev->ops = ops; + dev->major = 0; + strcpy(dev->name, name); + + /* register block device */ + if ((dev->major = register_blkdev(dev->major, dev->name)) <= 0) { + printk("flash: Unable to get major number.\n"); + return -ENODEV; + } + else + printk("Major number received: %d\n", dev->major); + + /* initialize data for 'flashdiskd' thread */ + spin_lock_init(&dev->blkdev_priv->queue_lock); + init_completion(&dev->blkdev_priv->thread_dead); + init_waitqueue_head(&dev->blkdev_priv->thread_wq); + init_MUTEX(&dev->sem); + + /* initialize block device request queue */ + dev->blkdev_priv->rq = blk_init_queue(do_cl_blkdev_request, + &dev->blkdev_priv->queue_lock); + if(!dev->blkdev_priv->rq) { + printk ("Could not initialize queue.\n"); + unregister_blkdev(dev->major, dev->name); + kfree(dev->blkdev_priv); + return -ENOMEM; + } + dev->blkdev_priv->rq->queuedata = dev; + blk_queue_hardsect_size(dev->blkdev_priv->rq, FLASH_SECTOR); + + /* start thread */ + ret = kernel_thread(cl_flashdisk_thread, dev, CLONE_KERNEL); + if (ret < 0) { + blk_cleanup_queue(dev->blkdev_priv->rq); + unregister_blkdev(dev->major, dev->name); + kfree(dev->blkdev_priv); + printk(KERN_ERR "%s: kernel_thread returned %d\n", __FUNCTION__, ret); + return ret; + } + + return 0; +} + +/* + cl_blkdev_register_disk: + - allocate generic dik object + - setup the disk (major, minors, name, ops) + - register the disk + + dev - block device enclosing the disk + name - disk name + size - size of the disk in sectors +*/ +int cl_blkdev_register_disk(struct cl_blkdev *dev, + const char* name, sector_t size) +{ + /* allocate disk data structure */ + dev->flash_disk = alloc_disk(16); + if (! dev->flash_disk) + return -ENOMEM; + + /* initialize disk parameters */ + dev->flash_disk->major = dev->major; + dev->flash_disk->first_minor = 0; + dev->flash_disk->fops = &flash_fops; + dev->flash_disk->private_data = dev; + dev->flash_disk->queue = dev->blkdev_priv->rq; + + /* set /dev node names */ + strcpy(dev->flash_disk->disk_name, name); + strcpy(dev->flash_disk->devfs_name, name); + set_capacity(dev->flash_disk, size); + + /* Insert this disk into linked list of disks */ + add_disk(dev->flash_disk); + + return 0; +} + +/* + cl_blkdev_unregister: unregister flash disk and associated block device +*/ +void cl_blkdev_unregister(struct cl_blkdev *dev) +{ + dev->blkdev_priv->exiting = 1; + wake_up(&dev->blkdev_priv->thread_wq); + wait_for_completion(&dev->blkdev_priv->thread_dead); + + del_gendisk(dev->flash_disk); + put_disk(dev->flash_disk); + blk_cleanup_queue(dev->blkdev_priv->rq); + + unregister_blkdev(dev->major, dev->name); +} + +/***************************************************************/ +/* NAND flash specific */ +/***************************************************************/ +int format = 0; +MODULE_PARM(format, "i"); + +#define CACHE_SIZE 128 + +/* This buffer is used for cach allocation, when cash size is bigger + than 128kb. 300 KB is the approximate amount needed for cache of 128 + pages, 2kb each. */ +#define BUFFER_SIZE (300 * 1024) +#define MAXIMUM_ALLOCATABLE_MEMORY (128 * 1024) +char tmp_buff[BUFFER_SIZE]; + +/* + cl_nand_mem_alloc: allocates memory for driver cache +*/ +void* cl_nand_mem_alloc (unsigned long size) +{ + static int buf_not_used = 1; + if ((size > MAXIMUM_ALLOCATABLE_MEMORY) && + (size < BUFFER_SIZE) && buf_not_used) { + buf_not_used = 0; + return (void*)tmp_buff; + } + return kmalloc (size, GFP_KERNEL); +} + +/* + cl_nand_mem_free: frees memory allocated for driver cache +*/ +void cl_nand_mem_free (void* ptr) +{ + kfree (ptr); +} + +/* + cl_nand_flush_proc: flushes driver caches to the device +*/ +static void cl_nand_flush_proc (void* _dev) +{ + struct cl_blkdev *blkdev = (struct cl_blkdev*)_dev; + struct cl_nand_dev *dev = (struct cl_nand_dev*)blkdev->hw_private; + + dev->logic_sync(dev->logic); + cl_trace_log ("Data synced\n"); + dev->last_end_write_cmd = 0; +} + +/* + cl_nand_request: handles an incoming IO request +*/ +static int cl_nand_request (struct cl_blkdev *_dev, struct request * req) +{ + struct cl_blkdev *blkdev = (struct cl_blkdev*)_dev; + struct cl_nand_dev *dev = (struct cl_nand_dev*)blkdev->hw_private; + + u_int block, count; + int code=1, i; + + block = req->sector; + count = req->current_nr_sectors; + + switch (rq_data_dir(req)) { + case 0: /* READ */ + for (i = 0, code = 1; i < count; i++) + if (!dev->logic_read_page( + dev->logic, block + i, + (char*)req->buffer + i * 512)) { + cl_trace_log ("Reading failed.\n"); + code = 0; /* failure */ + break; + } + break; + case 1: /* WRITE */ + for (i = 0, code = 1; i < count; i++) { + if(wpend) { + if (((block + i) >= wpstart) || + ((block + i) <= wpend)) { + code=0; + break; + } + } + if (!dev->logic_write_page( + dev->logic, block + i, + (char*)req->buffer + i * 512)) { + cl_trace_log ("Writing failed.\n"); + code = 0; /* failure */ + break; + } + } + dev->last_end_write_cmd = jiffies; + break; + default: + printk("do_flash_request: unknown request\n"); + break; + } + + return code; +} + +/* + cl_nand_ioctl: handles device ioctl's +*/ +static int cl_nand_ioctl(struct cl_blkdev *_dev, struct inode *inode, + struct file *file,unsigned int cmd,unsigned long arg) +{ + struct cl_nand_dev *dev = (struct cl_nand_dev*)_dev->hw_private; + + cl_trace_log ("flash_ioctl called.\n"); + printk("fdrv.o ioctl\n"); + if ((!inode) || !(inode->i_rdev)) + return -EINVAL; + + switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry *geometry = (struct hd_geometry*)arg; + if (!geometry) + return -EINVAL; /* Bad arguments to ioctl */ + put_user(dev->logic_get_param(dev->logic, + CL_FLASH_CYLINDERS_NUM, + 0), + &geometry->cylinders); + put_user(dev->logic_get_param(dev->logic, + CL_FLASH_HEADS_NUM, 0), + &geometry->heads); + put_user(dev->logic_get_param(dev->logic, + CL_FLASH_SECTORS_NUM, 0), + &geometry->sectors); + put_user(0, &geometry->start); + return 0; + } + case BLKGETSIZE: + if (!arg) + return -EINVAL; + return put_user(dev->logic_get_param( + dev->logic, + CL_FLASH_TOTAL_SIZE, 0) / 512, + (long *) arg); + case HDIO_SET_DMA: + /* We don't use DMA for flash. + This has no meaning */ + if (!capable (CAP_SYS_ADMIN)) + return -EACCES; + return 0; + case HDIO_GET_DMA: + return put_user( 0, (long *) arg); /* No DMA */ + case HDIO_GET_MULTCOUNT: + /* We don't have a limitation of number of + sectors in op. */ + return put_user (128, (long *) arg); + case BLKRRPART: + case BLKFLSBUF: + case BLKROSET: + case BLKROGET: + case BLKRASET: + case BLKRAGET: + case BLKPG: + case CL_FLASH_IO_GET_PARAM: + { + int err; + long* prm = (long*)arg; + err = access_ok(VERIFY_READ, prm, + sizeof(long) * 2) ? 0 : -EFAULT; + if (err) + return err; + err = access_ok(VERIFY_WRITE, prm, + sizeof (long)) ? 0 : -EFAULT; + if (err) + return err; + prm[0] = dev->logic_get_param(dev->logic, + prm[0], prm[1]); + return 0; + } + + case CL_FLASH_IO_DIRECT_ACCESS: + { + int err; + printk("====> CL_FLASH_IO_DIRECT_ACCESS\n"); + long* prm = (long*)arg; + err = access_ok(VERIFY_READ, prm, + sizeof(long) * 3) ? 0 : -EFAULT; + if(err) return err; + err = access_ok(VERIFY_WRITE, prm, + CL_FLASH_SECTOR_SIZE) ? 0 : -EFAULT; + if(err) return err; + return dev->logic_direct_access( + dev->logic, + (cl_nand_direct_access_type)prm[0], + (unsigned short)prm[1], + (unsigned short)prm[2], + (unsigned char*)(prm + 3)); + } + + default: + return -EINVAL; + } +} + +/* + cl_nand_release: releases the device +*/ +static int cl_nand_release (struct cl_blkdev *_dev, + struct inode *inode, struct file *file) +{ + struct cl_nand_dev *dev = (struct cl_nand_dev*)_dev->hw_private; + + dev->logic_sync(dev->logic); + cl_trace_log ("Data synced after RELEASE command\n"); + dev->last_end_write_cmd = 0; + + return 0; +} + +static struct flash_blkdev_ops nand_blkdev_ops = { + .flush_proc = cl_nand_flush_proc, + .flash_hw_ioctl = cl_nand_ioctl, + .do_flash_hw_request = cl_nand_request, + .flash_hw_release = cl_nand_release +}; + +#ifdef CONFIG_PROC_FS +/***************************************************************/ +/* proc entry /proc/flashdisk implementation */ +/***************************************************************/ +#include +#include + +static void cl_nand_proc_show(struct seq_file *s, struct cl_blkdev *_dev) +{ + struct cl_nand_dev *dev = _dev->hw_private; + + unsigned long heads, sects, tot_size, cylinders; + unsigned short sector_size, page_size; + long read_page_cnt, write_page_cnt, reclaim_cnt; + + tot_size = dev->logic_get_param(dev->logic, CL_FLASH_TOTAL_SIZE, 0); + heads = dev->logic_get_param(dev->logic, CL_FLASH_HEADS_NUM, 0); + sects = dev->logic_get_param(dev->logic, CL_FLASH_SECTOR_SIZE, 0); + cylinders = dev->logic_get_param(dev->logic, CL_FLASH_CYLINDERS_NUM, 0); + sector_size = dev->logic_get_param(dev->logic, CL_FLASH_SECTOR_SIZE, 0); + page_size = dev->logic_get_param(dev->logic, CL_FLASH_PAGE_SIZE, 0); + read_page_cnt = dev->logic_get_param(dev->logic, + CL_FLASH_READ_PAGE_CNT, 0); + write_page_cnt = dev->logic_get_param(dev->logic, + CL_FLASH_WRITE_PAGE_CNT, 0); + reclaim_cnt = dev->logic_get_param(dev->logic, CL_FLASH_RECLAIM_CNT, 0); + + + seq_printf(s, "NAND flash disk:\n"); + seq_printf(s, "\ttotal size: %lu Mbytes (%lu bytes)\n", + (tot_size >> 20), tot_size); + seq_printf(s, "\theads: %lu \tcylinders: %lu\tsectors: %lu\n", heads, + cylinders, sects); + seq_printf(s, "\tsector: %d\tpage: %d\n", sector_size, page_size); + seq_printf(s, "Stats:\n"); + seq_printf(s, "\tread: %ld\twritten: %ld\treclaimed: %ld\n", + read_page_cnt, write_page_cnt, reclaim_cnt); +} + +static int cl_blkdev_proc_show(struct seq_file *s, void *unused) +{ + struct cl_blkdev *dev = s->private; + + seq_printf(s, "CompuLab flash disks:\n"); + cl_nand_proc_show(s, dev); + + return 0; +} + +static int cl_blkdev_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, cl_blkdev_proc_show, PDE(inode)->data); +} + +static struct file_operations proc_ops = { + .open = cl_blkdev_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const char proc_filename[] = "flashdisk"; + +static void cl_blkdev_proc_create_file(struct cl_blkdev *dev) +{ + struct proc_dir_entry *pde; + pde = create_proc_entry(proc_filename, 0666, NULL); + if (pde == NULL) + return; + + pde->proc_fops = &proc_ops; + pde->data = dev; + dev->pde = pde; +} + +static void cl_blkdev_remove_proc_file(struct cl_blkdev *dev) +{ + if (dev->pde) + remove_proc_entry(proc_filename, NULL); +} + +#else + +#define cl_blkdev_create_proc_file(x) do {} while(0) +#define cl_blkdev_remove_proc_file(x) do {} while(0) + +#endif + +/*******************************************************************/ +/* NAND device initialization and cleanup */ +/*******************************************************************/ +/* + cl_nand_flash_init: + - initialize the CL_Logic + - register the block device and gendisk + + dev - preallocated cl_nand_dev object + cl_nand_linux - HW interface +*/ +int cl_nand_flash_init(struct cl_nand_dev *dev, cl_nand_map_if *cl_nand_linux) +{ + const char *name = "nand"; + int ret = 0; + printk ("Nand Flash disk driver, CompuLab"); + + if( wpend ) + printk("NAND Write Protection activated from %ld to %ld.\n", + wpstart, wpend); + + if (format) + printk ("Formatting Nand flash . . .\n"); + dev->logic = dev->logic_create(cl_nand_linux, CACHE_SIZE, format, FLASH_SECTOR); + if (!dev->logic) { + printk ("Flash logic couldn't be created.\n"); + return -1; + } + + dev->blkdev = kmalloc(sizeof(*dev->blkdev), GFP_KERNEL); + if ( !dev->blkdev ) { + return -ENOMEM; + } + + dev->blkdev->hw_private = dev; + if ( (ret = cl_blkdev_init(dev->blkdev, &nand_blkdev_ops, name)) ) { + printk(KERN_ERR "%s: cl_blkdev initialization failed: %d\n", + __FUNCTION__, ret); + dev->logic_free(dev->logic); + return ret; + } + + ret = cl_blkdev_register_disk(dev->blkdev, name, + dev->logic_get_param(dev->logic, + CL_FLASH_TOTAL_SIZE, + 0) / 512); + if ( ret ) { + printk(KERN_ERR "%s: NAND disk registration failed: %d\n", + __FUNCTION__, ret); + cl_blkdev_unregister(dev->blkdev); + dev->logic_free(dev->logic); + return ret; + } + + cl_blkdev_proc_create_file(dev->blkdev); + + return 0; +} + +/* + cl_nand_flash_cleanup: performs cleanup when driver is no longer used +*/ +void cl_nand_flash_cleanup(struct cl_nand_dev * dev) +{ + cl_blkdev_unregister(dev->blkdev); + if ( dev->logic ) + dev->logic_free(dev->logic); + + cl_blkdev_remove_proc_file(dev->blkdev); + + if ( dev->blkdev ) + kfree(dev->blkdev); +} diff --git a/drivers/block/cl_flash/cl_blkdev.h b/drivers/block/cl_flash/cl_blkdev.h new file mode 100644 index 0000000..bca1944 --- /dev/null +++ b/drivers/block/cl_flash/cl_blkdev.h @@ -0,0 +1,43 @@ +#ifndef __CL_BLKDEV_H__ +#define __CL_BLKDEV_H__ + +struct cl_blkdev; + +struct cl_nand_dev { + struct cl_blkdev *blkdev; + cl_logic logic; + unsigned long last_end_write_cmd; + + /* CL logic access layer */ + cl_logic (*logic_create)(cl_nand_map_if*, long, + int, unsigned short); + void (*logic_free)(cl_logic); + long (*logic_get_param)(cl_logic, cl_logic_param, long); + int (*logic_read_page)(cl_logic, long, CLBYTEPTR); + int (*logic_write_page)(cl_logic, long, CLBYTEPTR); + void (*logic_on_idle)(cl_logic, int); + void (*logic_sync)(cl_logic); + int (*logic_direct_access)(cl_logic,cl_nand_direct_access_type, + unsigned short, unsigned char, CLBYTEPTR); +}; + +extern int cl_nand_flash_init(struct cl_nand_dev *dev, cl_nand_map_if *cl_nand_linux); +extern void cl_nand_flash_cleanup(struct cl_nand_dev * dev); + +#define INIT_NAND_DEV(dev) \ + do { \ + dev->logic = 0; \ + dev->blkdev = 0; \ + dev->last_end_write_cmd = 0; \ + dev->logic_create = cl_logic_create; \ + dev->logic_free = cl_logic_free; \ + dev->logic_get_param = cl_logic_get_param; \ + dev->logic_read_page = cl_logic_read_page; \ + dev->logic_write_page = cl_logic_write_page; \ + dev->logic_on_idle = cl_logic_on_idle; \ + dev->logic_sync = cl_logic_sync; \ + dev->logic_direct_access = cl_logic_direct_access; \ + } while(0) + + +#endif /* __CL_BLKDEV_H__ */ diff --git a/drivers/block/cl_flash/cl_common.c b/drivers/block/cl_flash/cl_common.c new file mode 100644 index 0000000..a0d2a9c --- /dev/null +++ b/drivers/block/cl_flash/cl_common.c @@ -0,0 +1,52 @@ +void cl_zero_mem (void* ptr, long size) +{ + memset (ptr, 0, size); +} + +void cl_ff_mem (void* ptr, long size) +{ + memset (ptr, 0xff, size); +} +void cl_mem_copy (void* dest, void* src, long size) +{ + memcpy (dest, src, size); +} + +int cl_mem_compare (void* mem1, void* mem2, long size) +{ + return memcmp (mem1, mem2, size); +} + +unsigned long cl_get_jiffies (void) +{ + return jiffies; +} + +unsigned long cl_nand_get_max_cache_time (void) +{ + return HZ * 30; /* 30 seconds in cache maximum */ +} + +void cl_trace_log ( char* format, ...) +{ +#ifdef DO_CL_TRACE_LOG + char full_msg[300]; + va_list marker; + + va_start(marker, format); + vsprintf(full_msg, format, marker); + printk(full_msg); + va_end(marker); +#endif +} + +void cl_error_log ( char* format, ...) +{ + char full_msg[300]; + va_list marker; + + va_start(marker, format); + vsprintf(full_msg, format, marker); + printk(full_msg); + va_end(marker); +} diff --git a/drivers/block/cl_flash/cl_nanddev_x270.c b/drivers/block/cl_flash/cl_nanddev_x270.c new file mode 100644 index 0000000..71f05f8 --- /dev/null +++ b/drivers/block/cl_flash/cl_nanddev_x270.c @@ -0,0 +1,233 @@ +/* + * drivers/block/cl_flash/cl_nandded_x270.c + * + * Flash Disk Driver for CM-X270 platform. + * Low level device interface implementation + * + * Copyright Compulab 2003-2006 (c). + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "CL_Logic.h" +#include "cl_blkdev.h" + +/* The following macro enables flash activity indication by LEDs */ +#undef USE_LEDS + +#define NAND_RB (GPLR2 & (1<<25)) + +#define NandCLE (1<<0) +#define NandALE (1<<1) + +/* + * Values specific to the ARMCore + */ +volatile unsigned long * FLASH_DATA; +volatile unsigned long * FLASH_DATA_ALE; +volatile unsigned long * FLASH_DATA_CLE; + +/* asm-arm/arch-pxa/hardware.h defines UNCACHED_ADDR */ +volatile unsigned char * UNC = (volatile unsigned char *)UNCACHED_ADDR; + +/*******************************************************************/ +/* CM-X270 NAND HW access layer */ +/*******************************************************************/ +static inline void nand_cs_on(void) +{ + GPCR0 = 1<<11; + while( (GPLR0 & (1<<11)) ); +} + +static inline void nand_cs_off(void) +{ + unsigned char dummy; + asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); + dummy=*UNC; + + GPSR0 = 1<<11; + while( !(GPLR0 & (1<<11)) ); +} + +static void FlashInitial(void) +{ +} + +static void FlashChipSelect (int on, int need_auto_operation) +{ + static int cs_state = -1; + + if (need_auto_operation) + on = 1; + + if (cs_state == on) + return; + + cs_state = on; + + if (on) { + nand_cs_on(); + } + else { + nand_cs_off(); + } +} + +static unsigned char FlashReadByte (unsigned char offset) +{ + return (unsigned char)(*FLASH_DATA >> 16); +} + +static void FlashWriteByte (unsigned char offset, unsigned char data) +{ + if(offset & NandALE) *FLASH_DATA_ALE = (data << 16); + else if(offset & NandCLE) *FLASH_DATA_CLE = (data << 16); + else *FLASH_DATA = (data << 16); +} + +static void FlashBlockRead (unsigned char* data, int count) +{ + while (count--) + *data++ = (unsigned char)(*FLASH_DATA >> 16); +} + +static void FlashBlockWrite ( unsigned char* data, int count) +{ + while (count--) + *FLASH_DATA = (*data++ << 16); +} + +/* Orange LED used by Linux kernel activity */ +static void FlashCoreLeds (short operation, short reclaim) +{ +#ifdef USE_LEDS + +#endif +} + +static void do_nothing (void) +{ +} + +int nand_delay(unsigned long microseconds) +{ + if ( microseconds < 1000 ) { + udelay(microseconds); + return 0; + } + udelay(1000); + udelay(1000); + udelay(1000); + return 0; +} + +/* Wait on Ready/Busy signal */ +static int RBWait(unsigned long microseconds) +{ + unsigned char dummy; + int i=0; + + /* ensure there's no outstanding bus transaction */ + asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); + dummy=*UNC; + + /* protect from big delays in R/B GPIO falling edge (or no R/B + falling edge activity) */ + while((NAND_RB == 1) && (i < 3000)){ + udelay(1); + i++; + }; + + if ( i > 0 ) + printk(KERN_DEBUG "%s: No immediate R/B activity\n", __FILE__); + + if (i == 3000){ + printk(KERN_DEBUG "%s: No R/B activity for 3 ms\n", __FILE__); + return (0); + } + + i=0; + + /* protect from big delays in R/B GPIO rising edge */ + while((NAND_RB == 0) && (i < 3000)){ + udelay(1); + i++; + }; + + if (i == 3000){ + printk(KERN_DEBUG "%s: R/B timed out\n", __FILE__); + return (0); + } + + /* ensure there's no outstanding bus transaction */ + asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); + dummy=*UNC; + + return(1); +} + +static cl_nand_map_if cl_nand_linux = { + .init = FlashInitial, + .destroy = do_nothing, + .chip_select = FlashChipSelect, + .readb = FlashReadByte, + .writeb = FlashWriteByte, + .blockread = FlashBlockRead, + .blockwrite = FlashBlockWrite, + .activity_leds = FlashCoreLeds, + .sleep = nand_delay, + .rbwait = RBWait +}; + +static struct cl_nand_dev nand_dev; + +/* + nand_flash_init: + - perform board specific initialization + - initialize NAND device data structure + - initialize block device layer +*/ +static int nand_flash_init (void) +{ + struct cl_nand_dev *dev = &nand_dev; + + FLASH_DATA = (volatile unsigned long*)ioremap(PXA_CS1_PHYS, 12); + if (FLASH_DATA == NULL) { + printk("Bad NAND flash window at %X (already in use)\n", 0x04000000); + return -1; + } + FLASH_DATA_CLE = FLASH_DATA + 1; + FLASH_DATA_ALE = FLASH_DATA + 2; + + INIT_NAND_DEV(dev); + return cl_nand_flash_init(dev, &cl_nand_linux); +} + +#ifdef CONFIG_ARMCORE_NAND +int cl_nand_init_module(void) +{ + return nand_flash_init(); +} + +void cl_nand_cleanup_module(void) +{ + struct cl_nand_dev *dev = &nand_dev; + cl_nand_flash_cleanup(dev); +} +#else +int cl_nand_init_module(void) +{ + return 0; +} + +void cl_nand_cleanup_module(void) +{ +} +#endif diff --git a/drivers/block/cl_flash/cl_nordev.c b/drivers/block/cl_flash/cl_nordev.c new file mode 100644 index 0000000..85ae58a --- /dev/null +++ b/drivers/block/cl_flash/cl_nordev.c @@ -0,0 +1,594 @@ +/* + Flash Disk Driver Interface for Linux 2.4.x + Written by Vova Lifliand +*/ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Macros for correct linux/blk.h inclusion */ + +#define DEVICE_NAME "nor" + +static int major = 0; + +#define FLASH_SECTOR 512 + +#include +#include + +extern void cl_error_log ( char* format, ...); +extern void cl_trace_log ( char* format, ...); +extern void cl_mem_copy (void* dest, void* src, long size); + + +/* Undefine for custom LEDs usage */ +#undef USE_LEDS + +/* CrFlash driver interface */ +#ifndef FLASH_PLATFORM_LINUX +#define FLASH_PLATFORM_LINUX +#endif +#include "CL_Logic.h" + +typedef unsigned long ULONG; + +/* Forward functions declaration */ +static int flash_open (struct inode *inode,struct file *file); +static void do_flash_request (request_queue_t * q); +static int flash_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg); +static int flash_release (struct inode *inode, struct file *file); + +static DECLARE_MUTEX (nor_flash_sem); +static int nor_flash_sem_catched = 0; + + +volatile unsigned short * NorFlashMem; + +static int flash_check_media_change (struct gendisk* dev) +{ +/* printk ("flash_check_media_change called.\r\n");*/ + return 0; /* Disk not changed */ +} + +static int flash_revalidate (struct gendisk* dev) +{ +/* printk ("flash_revalidate called.\r\n");*/ + return 0; +} + +static struct block_device_operations flash_fops = +{ + .owner = THIS_MODULE, + .open = flash_open, + .release = flash_release, + .ioctl = flash_ioctl, + .media_changed = flash_check_media_change, + .revalidate_disk = flash_revalidate +}; + +static struct gendisk *flash_gendisk; +static spinlock_t flash_lock; +static struct request_queue *flash_queue; + + +#ifdef CONFIG_ARMCORE_NOR +/* nor_flash_init: register the block device number and set up pointer tables */ +int __init nor_flash_init (void) +{ + ULONG trash1, trash2, trash3, trash4, TotalSect; + + /* Request memory for NOR Flash */ + NorFlashMem = (volatile unsigned short*)ioremap (0x00000000, 0x800000); + if (NorFlashMem == NULL) { + printk("Bad NOR flash window at %X (already in use)\n", 0x00000000); + return -1; + } + + /* Do flash initialization */ + if (!cl_nor_init_flash()) { + printk("NOR: Flash initialization failed\n"); + iounmap((void __iomem *)NorFlashMem); + return -1; + } + + spin_lock_init(&flash_lock); + flash_queue = blk_init_queue(do_flash_request, &flash_lock); + if(flash_queue == NULL) + { + printk ("Could not initialize queue.\r\n"); + iounmap((void __iomem *)NorFlashMem); + return -1; + } + blk_queue_hardsect_size(flash_queue, FLASH_SECTOR); + + if ((major=register_blkdev (0, DEVICE_NAME)) <= 0) + { + printk("flash: Unable to get major number \n"); + iounmap((void __iomem *)NorFlashMem); + return -1; + } else printk("Major number received: %d\n", major); + + /* Insert this disk into linked list of disks */ + + flash_gendisk = alloc_disk(16); + if (! flash_gendisk) return -ENOMEM; + flash_gendisk->major = major; + flash_gendisk->first_minor = 0; + flash_gendisk->fops = &flash_fops; + flash_gendisk->private_data=NULL; + flash_gendisk->queue = flash_queue; + strcpy(flash_gendisk->disk_name, "nor"); + cl_nor_get_disk_param( &TotalSect, &trash1, &trash2, &trash3, &trash4); + set_capacity(flash_gendisk, TotalSect); + add_disk(flash_gendisk); + + /* Starting flush timer: the cl_timer_proc will be executed on each timer interrupt */ + + return 0; +} +#else +int __init nor_flash_init (void) +{ + return 0; +} +#endif + +/* flash_open: open a device */ +static int flash_open (struct inode *inode, struct file *file) +{ + + return 0; + +} + +/* do_flash_request: handle an incoming request */ +static void do_flash_request (request_queue_t * q) +{ + u_int block, count; + int code=1, i; + struct request* req=NULL; + + while ((code == 1) && ((req = elv_next_request(q)) != NULL)) + { + block = req->sector; + // printk ("req->nr_sectors = %d.\r\n", req->nr_sectors); + // printk ("req->current_nr_sectors = %d.\r\n", req->current_nr_sectors); + count = req->current_nr_sectors; + + nor_flash_sem_catched++; + down (&nor_flash_sem); + + switch (rq_data_dir(req)) { + case 0: // READ + for (i = 0, code = 1; i < count; i++) + // printk ("Reading sector %d (of %d).\r\n", block + i, count); + if (!cl_nor_read_page ( block + i, + (void *)((char*)req->buffer + i * 512))) { + // printk ("Reading failed.\r\n"); + code = 0; /* failure */ + break; + } + // printk ("Reading completed successfully.\r\n"); + break; + case 1: // WRITE + for (i = 0, code = 1; i < count; i++) { + // printk ("Writing sector %d.\r\n", block + i); + if (!cl_nor_write_page ( block + i, + (void *)((char*)req->buffer + i * 512))) { + // printk ("Writing failed.\r\n"); + code = 0; /* failure */ + break; + } + // printk ("Writing completed successfully.\r\n"); + } + break; + default: + printk("do_flash_request: unknown request\n"); + break; + } + up (&nor_flash_sem); + nor_flash_sem_catched--; + end_request (req, code); /* wrap up, 0 = fail, 1 = success */ + } +} + +/* flash_ioctl: handle device ioctl's */ +static int flash_ioctl (struct inode *inode, struct file *file, u_int cmd, u_long arg) +{ + ULONG trash1, trash2, trash3, trash4, TotalSect; + + // printk ("flash_ioctl called.\r\n"); + + if ((!inode) || !(inode->i_rdev)) + return -EINVAL; + + cl_nor_get_disk_param( &TotalSect, &trash1, &trash2, &trash3, &trash4); + // printk ("flash_ioctl in switch.\r\n"); + switch (cmd) + { + case HDIO_GETGEO: + { + struct hd_geometry *geometry = (struct hd_geometry*)arg; + if (!geometry) + return -EINVAL; /* Bad arguments to ioctl */ + put_user(TotalSect / 32 , &geometry->cylinders); + put_user(1, &geometry->heads); + put_user(32, &geometry->sectors); + put_user(2, &geometry->start); + } + case BLKGETSIZE: + if (!arg) + return -EINVAL; + return put_user (TotalSect, (long *) arg); + case HDIO_SET_DMA: /* We don't use DMA for flash. This has no meaning */ + if (!capable (CAP_SYS_ADMIN)) + return -EACCES; + return 0; + case HDIO_GET_DMA: + return put_user( 0, (long *) arg); /* No DMA */ + case HDIO_GET_MULTCOUNT: /* We don't have a limitation of number of sectors in op. */ + return put_user (128, (long *) arg); + case BLKFLSBUF: + case BLKROSET: + case BLKROGET: + case BLKRASET: + case BLKRAGET: + case BLKPG: + + default: + return -EINVAL; + } +} + +/* flash_release: release the device */ +static int flash_release (struct inode *inode, struct file *file) +{ + + return 0; +} + +#ifdef CONFIG_ARMCORE_NOR +static void flash_done (void) +{ + del_gendisk(flash_gendisk); + put_disk(flash_gendisk); + blk_cleanup_queue(flash_queue); + + /* Free memory allocated by flash module */ + cl_nor_free_mem (); + + unregister_blkdev (major, DEVICE_NAME); +} +#else +static void flash_done (void) +{ +} +#endif + +extern int cl_nand_init_module(void); +extern void cl_nand_cleanup_module(void); + +int flash_init_module(void) +{ + int error; + + error = cl_nand_init_module(); + if (error) return error; + + error = nor_flash_init(); + if (error) return error; + + return 0; +} + +void flash_cleanup_module(void) +{ + flash_done(); + cl_nand_cleanup_module(); +} + +module_init (flash_init_module); +module_exit (flash_cleanup_module); + +//-------------------- CMNLIN.C --------- + +#define TRUE 1 +#define FALSE 0 + +#define FL_CLKS_PER_SEC 182 + +#define NAND_HEAP_SIZE 64000 /* bytes */ +#define NOR_HEAP_SIZE 50000 /* bytes */ + +/* NOR Flash constants */ +#define NorFlashBlockSize 0x10000L /* 64 KB */ +#define NorFlashDiskPagesPerBlock 127 + +#define NOR_DRIVE_STARTING_BLOCK 28 + +/* NOR Flash Functions Support */ + +/* Constructor / destructor */ +static void Nor_Create(void); +/* Basic operations */ +static void Nor_EnableFlashMap(int EnableFlag); +static unsigned long Nor_GetSize(void); +static int Nor_GetPagesPerBlock(void); +static int Nor_ReadHeader (unsigned short BlockN, cl_nor_block_header* Header); +static int Nor_ReadPage (unsigned short BlockN, unsigned char PageNum, CLBYTEPTR DestBuff); +static int Nor_SetBlockState(unsigned short BlockN, unsigned short Signature, + unsigned short State, unsigned short Reserved); +static int Nor_InvalidatePage(unsigned short BlockN, unsigned char PageN); +static int Nor_WritePage(unsigned short BlockN, unsigned char PageN, + CLBYTEPTR PageData, unsigned short PageIndex); +static int Nor_EraseBlock(unsigned short BlockN); + +extern volatile unsigned short * NorFlashMem; +unsigned char Nor_IntelFlash; + +void Nor_EmptyFunc(void){}; + +cl_nor_flash_access NorFlashAccess = + { + Nor_Create, + Nor_EmptyFunc, /*NULL,*/ /* Destructor not needed */ + Nor_GetSize, + Nor_EnableFlashMap, + Nor_GetPagesPerBlock, + Nor_ReadHeader, + Nor_ReadPage, + Nor_SetBlockState, + Nor_InvalidatePage, + Nor_WritePage, + Nor_EraseBlock, + }; + +/* Driver see NOR Flash Blocks as linear, while there are BIOS holes */ +static int Nor_GetPhysBlockIndex (int BlockN) +{ + return (BlockN + NOR_DRIVE_STARTING_BLOCK); +} + +static void NorWrWord(unsigned long index, unsigned short data) +{ + *(NorFlashMem+index)=data; +} +extern void NorWrWord(unsigned long index, unsigned short data); + +static unsigned short NorRdWord(unsigned long index) +{ + return *(NorFlashMem+index); +} + +static unsigned char Nor_OutAMDCommand(unsigned short command) +{ + NorWrWord(0x555, 0xAAAA); + NorWrWord(0x2AA, 0x5555); + NorWrWord(0x555, command); + return TRUE; +} + + +static void Nor_Create(void) +{ + /* Nothing should be done here - all services are provided by BIOS */ +} + +static unsigned long Nor_GetSize(void) +{ + unsigned long NorFlashSize = 0x100000; + unsigned short n; +/* unsigned long i; */ + + /* Determine flash type */ + NorWrWord(0, 0xFFFF); + NorWrWord(0, 0x9090); + if(NorRdWord(0) == 0x89) + Nor_IntelFlash = TRUE; + else Nor_IntelFlash = FALSE; + NorWrWord(0, 0xFFFF); + + /* Query flash size */ + /* 1. Do reset command */ + NorWrWord(0, 0xF0F0); /* was 0f0f */ + NorWrWord(0, 0xFFFF); /* Will also reset intel flash */ + /* 2. Enter CFI mode */ + NorWrWord(0x55, 0x9898); + /* 3. Read flash size */ +/* READ WHOLE CFI for (i=10; i<0x3D; i++){ + n = NorRdWord(i); + printk("CFI n=%x\n", n);} */ + n = NorRdWord(0x27); + /* 4. Do reset again - exit CFI mode */ + NorWrWord(0, 0xF0F0); /* was 0f0f */ + NorWrWord(0, 0xFFFF); /* Will also reset intel flash */ + /* Exclude BIOS area */ + if((n>0x17) | (n<0x14)) n=0x14; // if detection is unsuccessfull (no CFI) default to 1MB + NorFlashSize = (1 << n); /* 2 ^ n */ + + cl_error_log("NOR Flash (%s) size: %d MB total\n",(Nor_IntelFlash ? "Intel" : "AMD"),NorFlashSize / (1024 * 1024)); + + if(NorFlashSize == (1024 * 1024)) { + cl_error_log("1Mb flash not supported!\n"); + return 0; + } + + return NorFlashSize -= NOR_DRIVE_STARTING_BLOCK * 64L * 1024L; /*exclude BIOS and jump areas, spareblocks etc.*/ +} + +/* Remaps or unmaps MMS windows, allocated by flash */ +static void Nor_EnableFlashMap (int EnableFlag) +{ + /* Just to prevent warning */ + int x = EnableFlag; + EnableFlag = x; + /* Nothing should be done here - all services are provided by BIOS */ +} + +static int Nor_GetPagesPerBlock(void) +{ + return NorFlashDiskPagesPerBlock; +} + +static int Nor_ReadHeader (unsigned short BlockN, cl_nor_block_header* Header) +{ + + cl_mem_copy (Header, + (char*)(NorFlashMem + (0x8000 * Nor_GetPhysBlockIndex(BlockN))), + (sizeof (cl_nor_block_header) + 1) & 0xFFFE); + return 1; +} + +static int Nor_ReadPage (unsigned short BlockN, unsigned char PageNum, CLBYTEPTR DestBuff) +{ + cl_mem_copy (DestBuff, + (char*)(NorFlashMem + (0x8000 * Nor_GetPhysBlockIndex(BlockN)) + + ((PageNum + 1) * (CL_NOR_FLASH_PAGE_SIZE / 2))), + CL_NOR_FLASH_PAGE_SIZE); + return 1; +} + +static int Nor_EraseBlock(unsigned short BlockN) +{ + unsigned long addr; + unsigned short dummy; + + addr=(Nor_GetPhysBlockIndex(BlockN)*NorFlashBlockSize)/2; + if(Nor_IntelFlash) + { /* Erase block sequence from Intel flash */ + NorWrWord(addr, 0xFFFF); + NorWrWord(addr, 0x7070); + NorWrWord(addr, 0x2020); + NorWrWord(addr, 0xD0D0); + NorWrWord(addr, 0xD0D0); + while(!(NorRdWord(addr) & 128)) + ; + NorWrWord(0, 0xFFFF); + return TRUE; + } + else + { + /* Do "erase block" commands sequence */ + if(!Nor_OutAMDCommand(0xF0F0)) return FALSE; + dummy = NorRdWord(addr); /* read and discard */ + if(!Nor_OutAMDCommand(0x8080)) return FALSE; + NorWrWord(0x555, 0xAAAA); + NorWrWord(0x2AA, 0x5555); + NorWrWord(addr, 0x3030); + + /* Waiting block is erased - no timeout here */ + while(TRUE) + { + /* Stall processor execution for about 20 microseconds <--- it is much less */ + for(dummy = 0; dummy < 20; dummy++) + ; + /* Check if ready */ + if(NorRdWord(addr) == 0xFFFF) + return TRUE; + } + } +} + +static int Nor_SetWord (unsigned long ofs, unsigned short word) +{ + unsigned short timeout = 0xFFF; + unsigned long addr; + addr = ((Nor_GetPhysBlockIndex (ofs >> 15))<<15)+(ofs&0x7FFF);// 15 because address is given for word argument + /* The address should be word aligned since accessing by word and not by byte */ + + if(Nor_IntelFlash) + { /* Write sequence from Intel flash */ + NorWrWord(addr, 0x4040); + NorWrWord(addr, word); + while(timeout--) + udelay(1); + if(NorRdWord(addr) & 128) + { + unsigned char res = !(NorRdWord(addr) & 16); + NorWrWord(addr, 0x5050); + NorWrWord(addr, 0xFFFF); + return res; + } + NorWrWord(0, 0x5050); + } + else + { /* Write sequence from AMD flash */ + /* Output command is a necessary sequence to write word */ + if(!Nor_OutAMDCommand(0xA0A0)) + return FALSE; + + /* Write data */ + NorWrWord(addr, word); + /* Wait data written */ + while(timeout--) { + udelay(1); + if(NorRdWord(addr) == word) + return TRUE; + } + } + /* Failure */ + cl_error_log("ERROR: SetWord timeout."); + + return FALSE; +} + +static int Nor_SetBlockState(unsigned short BlockN, unsigned short Signature, + unsigned short State, unsigned short Reserved) +{ + return Nor_SetWord ((BlockN * NorFlashBlockSize + 0)/2, Signature) && + Nor_SetWord ((BlockN * NorFlashBlockSize + 2)/2, State) && + Nor_SetWord ((BlockN * NorFlashBlockSize + 26 + 127 * 2)/2, Reserved); +} + +static int Nor_InvalidatePage (unsigned short BlockN, unsigned char PageN) +{ + return Nor_SetWord ((BlockN * NorFlashBlockSize + 6 + 2 * PageN)/2, 0); +} + +static int Nor_WritePage (unsigned short BlockN, unsigned char PageN, + CLBYTEPTR PageData, unsigned short PageIndex) +{ + int words_left, dest_addr; + unsigned short* ptr; + + /* Write index to first page - header information */ + if(!Nor_SetWord((BlockN * NorFlashBlockSize + 6 + 2 * PageN)/2, PageIndex)) + { + cl_error_log("A"); + return FALSE; /* Couldn't write page index */ + } + + /* Write page data */ + words_left = (512 >> 1); /* Write by word */ + dest_addr = BlockN * NorFlashBlockSize + (PageN + 1) * 512; + ptr = (unsigned short*)PageData; + while(words_left--) + { + if(!Nor_SetWord(dest_addr/2, *ptr++)) + { + cl_error_log("B"); + return FALSE; /* Page data writing failure */ + } + dest_addr += 2; /* Write by word (2 bytes each write command) */ + } + + return TRUE; +} + diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 05ba410..a820db0 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -1020,5 +1020,11 @@ config TELCLOCK sysfs directory, /sys/devices/platform/telco_clock, with a number of files for controlling the behavior of this hardware. + +config EMV3020_RTC + tristate "EM-V3020 RTC" + ---help--- + Support for EM Microelectronics V3020 RTC + endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 503dd90..625bfd9 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_SGI_MBCS) += mbcs.o +obj-$(CONFIG_EMV3020_RTC) += emv3020.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o diff --git a/drivers/char/emv3020.c b/drivers/char/emv3020.c new file mode 100644 index 0000000..df7f1a4 --- /dev/null +++ b/drivers/char/emv3020.c @@ -0,0 +1,365 @@ +/* + * emv3020.c + * + * Driver for EMV3020 RTC + * + * Copyright (C) 2006 Compulab Ltd. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define EMV3020_VA_RTC emv3020_rtc_base + +static struct resource *emv3020_rtc_mem; +static void __iomem *emv3020_rtc_base; + +#define DEBUG 0 +#if DEBUG +static unsigned int rtc_debug = DEBUG; +#else +#define rtc_debug 0 /* gcc will remove all the debug code for us */ +#endif + +static void emv3020_set_reg(unsigned char address, unsigned char data) +{ + int i; + + for ( i = 0; i < 4; i++ ) + writel((address << (16-i)), EMV3020_VA_RTC); + + if ( address < 0xe) + for ( i = 0; i < 8; i++) + writel((data << (16-i)), EMV3020_VA_RTC); +} + +static unsigned char emv3020_get_reg(unsigned char address) +{ + unsigned int data=0; + int i, tmp; + + for ( i = 0; i < 4; i++ ) + writel((address << (16-i)), EMV3020_VA_RTC); + + for ( i = 0; i < 8; i++ ) { + tmp = readl(EMV3020_VA_RTC); + data |= ((tmp & 0x10000) >> (16 - i)); + } + + return data; +} + +static int emv3020_detect(struct device *dev) +{ + int i; + int temp; + + for ( i=0; i<8; i++) + temp = readl(EMV3020_VA_RTC); + + emv3020_set_reg(0x2, 0x33); + + if ( emv3020_get_reg(0x2) == 0x33 ) { + emv3020_set_reg(0x0, 0x0); + return 0; + } + + return -ENODEV; +} + +static int emv3020_rtc_gettime(struct rtc_time *dt) +{ + int ret=0; + + emv3020_set_reg(0x0F, 0); + + dt->tm_sec = emv3020_get_reg(0x02); + dt->tm_min = emv3020_get_reg(0x03); + dt->tm_hour = emv3020_get_reg(0x04); + dt->tm_mday = emv3020_get_reg(0x05); + dt->tm_mon = emv3020_get_reg(0x06); + dt->tm_wday = emv3020_get_reg(0x08); + dt->tm_year = emv3020_get_reg(0x07); + + BCD_TO_BIN(dt->tm_sec); + BCD_TO_BIN(dt->tm_min); + BCD_TO_BIN(dt->tm_hour); + BCD_TO_BIN(dt->tm_mday); + BCD_TO_BIN(dt->tm_mon); + BCD_TO_BIN(dt->tm_wday); + BCD_TO_BIN(dt->tm_year); + dt->tm_year += 100; + + if(rtc_debug)printk("\n%s : Read RTC values\n",__FUNCTION__); + if(rtc_debug)printk("tm_hour: %i\n",dt->tm_hour); + if(rtc_debug)printk("tm_min : %i\n",dt->tm_min); + if(rtc_debug)printk("tm_sec : %i\n",dt->tm_sec); + if(rtc_debug)printk("tm_year: %i\n",dt->tm_year); + if(rtc_debug)printk("tm_mon : %i\n",dt->tm_mon); + if(rtc_debug)printk("tm_mday: %i\n",dt->tm_mday); + if(rtc_debug)printk("tm_wday: %i\n",dt->tm_wday); + + return ret; +} + +static int emv3020_rtc_settime(struct rtc_time *dt) +{ + if(rtc_debug)printk("\n%s : Setting RTC values\n",__FUNCTION__); + if(rtc_debug)printk("tm_sec : %i\n",dt->tm_sec); + if(rtc_debug)printk("tm_min : %i\n",dt->tm_min); + if(rtc_debug)printk("tm_hour: %i\n",dt->tm_hour); + if(rtc_debug)printk("tm_mday: %i\n",dt->tm_mday); + if(rtc_debug)printk("tm_wday: %i\n",dt->tm_wday); + if(rtc_debug)printk("tm_year: %i\n",dt->tm_year); + + dt->tm_year %= 100; + BIN_TO_BCD(dt->tm_sec); + BIN_TO_BCD(dt->tm_min); + BIN_TO_BCD(dt->tm_hour); + BIN_TO_BCD(dt->tm_mday); + BIN_TO_BCD(dt->tm_mon); + BIN_TO_BCD(dt->tm_wday); + BIN_TO_BCD(dt->tm_year); + + emv3020_set_reg(0x02, dt->tm_sec); + emv3020_set_reg(0x03, dt->tm_min); + emv3020_set_reg(0x04, dt->tm_hour); + emv3020_set_reg(0x05, dt->tm_mday); + emv3020_set_reg(0x06, dt->tm_mon); + emv3020_set_reg(0x08, dt->tm_wday); + emv3020_set_reg(0x07, dt->tm_year); + + emv3020_set_reg(0x0E, 0); + + return 0; +} + +static int emv3020_rtc_open(void) +{ + return 0; +} + +static void emv3020_rtc_release(void) +{ +} + +static int emv3020_rtc_ioctl(unsigned int cmd, unsigned long arg) +{ + struct rtc_time wtime; + int status = 0; + + switch (cmd) { + default: + case RTC_UIE_ON: + case RTC_UIE_OFF: + case RTC_PIE_ON: + case RTC_PIE_OFF: + case RTC_AIE_ON: + case RTC_AIE_OFF: + case RTC_ALM_SET: + case RTC_ALM_READ: + case RTC_IRQP_READ: + case RTC_IRQP_SET: + case RTC_EPOCH_READ: + case RTC_EPOCH_SET: + case RTC_WKALM_SET: + case RTC_WKALM_RD: + status = -EINVAL; + break; + + case RTC_RD_TIME: + emv3020_rtc_gettime(&wtime); + if( copy_to_user((void *)arg, &wtime, + sizeof (struct rtc_time))) + status = -EFAULT; + break; + + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) { + status = -EACCES; + break; + } + + if (copy_from_user(&wtime, (struct rtc_time *)arg, + sizeof(struct rtc_time)) ) { + status = -EFAULT; + break; + } + + emv3020_rtc_settime(&wtime); + break; + } + + return status; +} + +static char *emv3020_mon2str(unsigned int mon) +{ + char *mon2str[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + if( mon > 11) return "error"; + else return mon2str[ mon]; +} + +static int emv3020_rtc_proc( char *buf) +{ + char *p = buf; + struct rtc_time dt; + + emv3020_rtc_gettime(&dt); + + p += sprintf(p, "\nEMV3020 (Real Time Clock)\n"); + p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n", + dt.tm_mday, + emv3020_mon2str(dt.tm_mon), + dt.tm_year+1900, + dt.tm_hour, + dt.tm_min, + dt.tm_sec); + return p - buf; +} + +static struct rtc_ops emv3020_rtcops = { + .owner = THIS_MODULE, + .open = emv3020_rtc_open, + .release = emv3020_rtc_release, + .ioctl = emv3020_rtc_ioctl, + .read_time = emv3020_rtc_gettime, + .set_time = emv3020_rtc_settime, + .read_alarm = 0, + .set_alarm = 0, + .proc = emv3020_rtc_proc, +}; + +static int emv3020_rtc_remove(struct device *dev) +{ + unregister_rtc(&emv3020_rtcops); + + if (emv3020_rtc_mem != NULL) { + pr_debug("emv3020_rtc: releasing emv3020_rtc_mem\n"); + iounmap(emv3020_rtc_base); + release_resource(emv3020_rtc_mem); + } + + return 0; +} + +static int emv3020_rtc_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct resource *res; + int ret; + + pr_debug("%s: probe=%p, device=%p\n", __FUNCTION__, pdev, dev); + + /* get the memory region */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(dev, "failed to get memory region resource\n"); + return -ENOENT; + } + + emv3020_rtc_mem = request_mem_region(res->start, + res->end - res->start + 1, + pdev->name); + + if (emv3020_rtc_mem == NULL) { + dev_err(dev, "failed to reserve memory region\n"); + ret = -ENOENT; + goto exit_err; + } + + emv3020_rtc_base = ioremap(res->start, res->end - res->start + 1); + if (emv3020_rtc_base == NULL) { + dev_err(dev, "failed ioremap()\n"); + ret = -EINVAL; + goto exit_err; + } + + emv3020_rtc_mem = res; + pr_debug("emv3020_rtc_base=%p\n", emv3020_rtc_base); + + /* check to see if everything is setup correctly */ + if ( (ret = emv3020_detect(dev)) != 0 ) { + iounmap(emv3020_rtc_base); + release_resource(emv3020_rtc_mem); + goto exit_err; + } + + /* register RTC and exit */ + register_rtc(&emv3020_rtcops); + + return 0; + + exit_err: + dev_err(dev, "error %d during initialisation\n", ret); + + return ret; +} + +#ifdef CONFIG_PM +/* EMV3020 RTC Power management control */ +static int emv3020_rtc_suspend(struct device *dev, pm_message_t state) +{ + return 0; +} + +static int emv3020_rtc_resume(struct device *dev) +{ + return 0; +} +#else +#define emv3020_rtc_suspend NULL +#define emv3020_rtc_resume NULL +#endif + +static struct device_driver emv3020_rtcdrv = { + .name = "emv3020-rtc", + .bus = &platform_bus_type, + .probe = emv3020_rtc_probe, + .remove = emv3020_rtc_remove, + .suspend = emv3020_rtc_suspend, + .resume = emv3020_rtc_resume, +}; + +static __init int emv3020_init(void) +{ + return driver_register(&emv3020_rtcdrv); +} + +static __exit void emv3020_exit(void) +{ + driver_unregister(&emv3020_rtcdrv); +} + +module_init(emv3020_init); +module_exit(emv3020_exit); + + +MODULE_AUTHOR ("Compulab Ltd."); +MODULE_LICENSE ("GPL"); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index d633081..5e7f6ee 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -850,6 +850,13 @@ config BLK_DEV_IDE_BAST Say Y here if you want to support the onboard IDE channels on the Simtec BAST or the Thorcom VR1000 +config BLK_DEV_IDE_CM_X270 + tristate "CompuLab CM-X270 IDE support" + depends on ARM && (MACH_ARMCORE) + help + Say Y here if you want to support the onboard IDE channels on the + CompuLab CM-X270 module + config BLK_DEV_GAYLE bool "Amiga Gayle IDE interface support" depends on AMIGA diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile index 6a78f07..e5cadb7 100644 --- a/drivers/ide/arm/Makefile +++ b/drivers/ide/arm/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o +obj-$(CONFIG_BLK_DEV_IDE_CM_X270) += cm-x270-ide.o EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/arm/cm-x270-ide.c b/drivers/ide/arm/cm-x270-ide.c new file mode 100644 index 0000000..d0e9b8a --- /dev/null +++ b/drivers/ide/arm/cm-x270-ide.c @@ -0,0 +1,135 @@ +/* linux/drivers/ide/arm/cm-x270-ide.c + * + * Copyright (c) 2006 CompuLab, Ltd + * Mike Rapoport + * + * Based on linux/drivers/ide/arm/bast-ide.c + * Copyright (c) 2003-2004 Simtec Electronics + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define CMX270_SB270_IDECS0_VIRT (CMX270_IDE104_VIRT + (1<<24) + (1<<25)) +#define CMX270_SB270_IDECS1_VIRT (CMX270_IDE104_VIRT + (1<<25)) +#define CMX270_ATX_IDECS0_VIRT (CMX270_IDE104_VIRT + (1<<25)) +#define CMX270_ATX_IDECS1_VIRT (CMX270_IDE104_VIRT + (1<<25) + (1<<22)) + +/* list of registered interfaces */ +static ide_hwif_t *ifs[1]; + +static int __init +cmx270_ide_register(unsigned int base, unsigned int aux, int irq, + ide_hwif_t **hwif) +{ + hw_regs_t hw; + + memset(&hw, 0, sizeof(hw)); + + if(!base || !aux) return -EINVAL; + + printk(KERN_DEBUG "%s: base = %08x, aux = %08x\n", __FUNCTION__, + base, aux); + + /* Different mappings for local bus IDE and PCMCIA IDE */ + if(base == CMX270_SB270_IDECS0_VIRT) { + hw.io_ports[IDE_DATA_OFFSET] = base + 0; + hw.io_ports[IDE_ERROR_OFFSET] = base + (0x1<<3); + hw.io_ports[IDE_NSECTOR_OFFSET]= base + (0x2<<3); + hw.io_ports[IDE_SECTOR_OFFSET]= base + (0x3<<3); + hw.io_ports[IDE_LCYL_OFFSET]= base + (0x4<<3); + hw.io_ports[IDE_HCYL_OFFSET]= base + (0x5<<3); + hw.io_ports[IDE_SELECT_OFFSET]= base + (0x6<<3); + hw.io_ports[IDE_STATUS_OFFSET]= base + (0x7<<3); + hw.io_ports[IDE_CONTROL_OFFSET] = aux+(0x6<<3); + } + else if (base == CMX270_ATX_IDECS0_VIRT) { /* atx base */ + hw.io_ports[IDE_DATA_OFFSET] = base + 0; + hw.io_ports[IDE_ERROR_OFFSET] = base + 8; + hw.io_ports[IDE_NSECTOR_OFFSET]= base + 2; + hw.io_ports[IDE_SECTOR_OFFSET]= base + 10; + hw.io_ports[IDE_LCYL_OFFSET]= base + 4; + hw.io_ports[IDE_HCYL_OFFSET]= base + 12; + hw.io_ports[IDE_SELECT_OFFSET]= base + 6; //6; + hw.io_ports[IDE_STATUS_OFFSET]= base + 14; + hw.io_ports[IDE_CONTROL_OFFSET] = (aux+0x6); + } else { + printk(KERN_DEBUG "%s: registering wrong IDE i/f\n", __FUNCTION__); + hw.io_ports[IDE_DATA_OFFSET] = base + 8; + hw.io_ports[IDE_ERROR_OFFSET] = base + 13; + hw.io_ports[IDE_NSECTOR_OFFSET] = base + 2; + hw.io_ports[IDE_SECTOR_OFFSET] = base + 3; + hw.io_ports[IDE_LCYL_OFFSET] = base + 4; + hw.io_ports[IDE_HCYL_OFFSET] = base + 5; + hw.io_ports[IDE_SELECT_OFFSET] = base + 6; + hw.io_ports[IDE_STATUS_OFFSET] = base + 7; + hw.io_ports[IDE_CONTROL_OFFSET] = aux; + } + + hw.irq = irq; + + return ide_register_hw(&hw, hwif); +} + +static int __init cmx270_ide_init(void) +{ + int retval = 0; + + if (!(machine_is_armcore())) + goto out; + + printk("CM-X270: initializing IDE interface\n"); + + MSC1 = 0x7ffc7ff4; + + /* Interrupts on rising edge: lines are inverted before they get to + the PXA */ + pxa_gpio_mode(IRQ_TO_GPIO(CMX270_IDE_IRQ)); + + /* try SB-X270 */ + set_irq_type(CMX270_IDE_IRQ, IRQT_RISING); + retval = cmx270_ide_register(CMX270_SB270_IDECS0_VIRT, + CMX270_SB270_IDECS1_VIRT, + CMX270_IDE_IRQ, &ifs[0]); + if (retval >= 0) { + printk(KERN_DEBUG "%s: found IDE interface on SB-X270\n", + __FUNCTION__); + goto out; + } + + /* SB-X270 detection failed, try ATX */ + set_irq_type(CMX270_IDE_IRQ, IRQT_FALLING); + retval = cmx270_ide_register(CMX270_ATX_IDECS0_VIRT, + CMX270_ATX_IDECS1_VIRT, + CMX270_IDE_IRQ, &ifs[0]); + + if ( retval >= 0 ) { + printk(KERN_DEBUG "%s: found IDE interface on ATX\n", + __FUNCTION__); + goto out; + } + + out: + return retval; +} + +module_init(cmx270_ide_init); + +MODULE_AUTHOR("CompuLab"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CompuLab CM-X270 IDE driver"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 550f297..ed5bb70 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -23,3 +23,13 @@ config MCP_UCB1200_TS depends on MCP_UCB1200 && INPUT endmenu + +config UCB1400 + tristate + +config UCB1400_TS + tristate "UCB1400 Touchscreen support" + depends on ARCH_LUBBOCK || MACH_MAINSTONE || MACH_ARMCORE + select UCB1400 + select SND_AC97_BUS + diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index adb29b5..24429d1 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -10,3 +10,10 @@ obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00- ifeq ($(CONFIG_SA1100_ASSABET),y) obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o endif + +ucb1400-core-y := ucb1x00-core.o mcp-ac97.o +obj-$(CONFIG_UCB1400_TS) += ucb1400-core.o ucb1x00-ts.o + +ucb1400-core-$(CONFIG_UCB1400) := ucb1x00-core.o mcp-ac97.o +obj-$(CONFIG_UCB1400_TS) += ucb1400-core.o ucb1x00-ts.o + diff --git a/drivers/mfd/mcp-ac97.c b/drivers/mfd/mcp-ac97.c new file mode 100644 index 0000000..223f8c2 --- /dev/null +++ b/drivers/mfd/mcp-ac97.c @@ -0,0 +1,151 @@ +/* + * linux/drivers/misc/mcp-ac97.c + * + * Author: Nicolas Pitre + * Created: Jan 14, 2005 + * Copyright: (C) MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This module provides the minimum replacement for mcp-core.c allowing for + * the UCB1400 chip to be driven by the ucb1x00 driver over an AC97 link. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "mcp.h" + +/* ucb1x00 SIB register to ucb1400 AC-link register mapping */ + +static const unsigned char regmap[] = { + 0x5a, /* UCB_IO_DATA */ + 0X5C, /* UCB_IO_DIR */ + 0X5E, /* UCB_IE_RIS */ + 0x60, /* UCB_IE_FAL */ + 0x62, /* UCB_IE_STATUS */ + 0, /* UCB_TC_A */ + 0, /* UCB_TC_B */ + 0, /* UCB_AC_A */ + 0, /* UCB_AC_B */ + 0x64, /* UCB_TS_CR */ + 0x66, /* UCB_ADC_CR */ + 0x68, /* UCB_ADC_DATA */ + 0x7e, /* UCB_ID */ + 0, /* UCB_MODE */ +}; + +unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) +{ + ac97_t *ac97 = to_ac97_t(mcp->dev); + if (reg < ARRAY_SIZE(regmap)) { + reg = regmap[reg]; + if (reg) + return ac97->bus->ops->read(ac97, reg); + } + return -1; +} +EXPORT_SYMBOL(mcp_reg_read); + +void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) +{ + ac97_t *ac97 = to_ac97_t(mcp->dev); + if (reg < ARRAY_SIZE(regmap)) { + reg = regmap[reg]; + if (reg) + ac97->bus->ops->write(ac97, reg, val); + } +} +EXPORT_SYMBOL(mcp_reg_write); + +void mcp_enable(struct mcp *mcp) +{ +} +EXPORT_SYMBOL(mcp_enable); + +void mcp_disable(struct mcp *mcp) +{ +} +EXPORT_SYMBOL(mcp_disable); + +#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) + +static int mcp_probe(struct device *dev) +{ + struct mcp_driver *drv = to_mcp_driver(dev->driver); + struct mcp *mcp; + int ret; + + ret = -ENOMEM; + mcp = kmalloc(sizeof(*mcp), GFP_KERNEL); + if (mcp) { + memset(mcp, 0, sizeof(*mcp)); + mcp->owner = THIS_MODULE; + mcp->dev = dev; + ret = drv->probe(mcp); + if (ret) + kfree(mcp); + } + if (!ret) + dev_set_drvdata(dev, mcp); + return ret; +} + +static int mcp_remove(struct device *dev) +{ + struct mcp_driver *drv = to_mcp_driver(dev->driver); + struct mcp *mcp = dev_get_drvdata(dev); + + drv->remove(mcp); + dev_set_drvdata(dev, NULL); + kfree(mcp); + return 0; +} + +static int mcp_suspend(struct device *dev, pm_message_t state) +{ + struct mcp_driver *drv = to_mcp_driver(dev->driver); + struct mcp *mcp = dev_get_drvdata(dev); + int ret = 0; + + if (drv->suspend) + ret = drv->suspend(mcp, state); + return ret; +} + +static int mcp_resume(struct device *dev) +{ + struct mcp_driver *drv = to_mcp_driver(dev->driver); + struct mcp *mcp = dev_get_drvdata(dev); + int ret = 0; + + if (drv->resume) + ret = drv->resume(mcp); + return ret; +} + +int mcp_driver_register(struct mcp_driver *mcpdrv) +{ + mcpdrv->drv.owner = THIS_MODULE; + mcpdrv->drv.bus = &ac97_bus_type; + mcpdrv->drv.probe = mcp_probe; + mcpdrv->drv.remove = mcp_remove; + mcpdrv->drv.suspend = mcp_suspend; + mcpdrv->drv.resume = mcp_resume; + return driver_register(&mcpdrv->drv); +} + +void mcp_driver_unregister(struct mcp_driver *mcpdrv) +{ + driver_unregister(&mcpdrv->drv); +} + +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 75f401d..2a7c176 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -208,6 +208,7 @@ struct mcp *mcp_host_alloc(struct device mcp->attached_device.bus = &mcp_bus_type; mcp->attached_device.dma_mask = parent->dma_mask; mcp->attached_device.release = mcp_release; + mcp->dev = &mcp->attached_device; } return mcp; } diff --git a/drivers/mfd/mcp.h b/drivers/mfd/mcp.h index c093a93..2897d8c 100644 --- a/drivers/mfd/mcp.h +++ b/drivers/mfd/mcp.h @@ -19,11 +19,12 @@ struct mcp { int use_count; unsigned int sclk_rate; unsigned int rw_timeout; - dma_device_t dma_audio_rd; - dma_device_t dma_audio_wr; - dma_device_t dma_telco_rd; - dma_device_t dma_telco_wr; +/* dma_device_t dma_audio_rd; */ +/* dma_device_t dma_audio_wr; */ +/* dma_device_t dma_telco_rd; */ +/* dma_device_t dma_telco_wr; */ struct device attached_device; + struct device *dev; }; struct mcp_ops { diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index aff83f9..f9a532b 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -23,6 +23,7 @@ #include #include #include #include +#include #include #include @@ -31,6 +32,12 @@ #include #include "ucb1x00.h" +#if defined(CONFIG_UCB1400) || defined(CONFIG_UCB1400_MODULE) +#define UCB_IS_1400(id) ((id) == UCB_ID_1400) +#else +#define UCB_IS_1400(id) (0) +#endif + static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); static LIST_HEAD(ucb1x00_devices); @@ -58,9 +65,9 @@ void ucb1x00_io_set_dir(struct ucb1x00 * spin_lock_irqsave(&ucb->io_lock, flags); ucb->io_dir |= out; ucb->io_dir &= ~in; + spin_unlock_irqrestore(&ucb->io_lock, flags); ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); - spin_unlock_irqrestore(&ucb->io_lock, flags); } /** @@ -86,9 +93,9 @@ void ucb1x00_io_write(struct ucb1x00 *uc spin_lock_irqsave(&ucb->io_lock, flags); ucb->io_out |= set; ucb->io_out &= ~clear; + spin_unlock_irqrestore(&ucb->io_lock, flags); ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); - spin_unlock_irqrestore(&ucb->io_lock, flags); } /** @@ -178,7 +185,7 @@ unsigned int ucb1x00_adc_read(struct ucb schedule_timeout(1); } - return UCB_ADC_DAT(val); + return UCB_IS_1400(ucb->id) ? (val & 0x3ff) : ((val & 0x7fe0) >> 5); } /** @@ -223,6 +230,47 @@ static irqreturn_t ucb1x00_irq(int irqnr return IRQ_HANDLED; } +/* + * A restriction with interrupts exists when using the ucb1400, as + * the codec read/write routines may sleep while waiting for codec + * access completion and uses semaphores for access control to the + * AC97 bus. A complete codec read cycle could take anywhere from + * 60 to 100uSec so we *definitely* don't want to spin inside the + * interrupt handler waiting for codec access. So, we handle the + * interrupt by scheduling a RT kernel thread to run in process + * context instead of interrupt context. + */ +static int ucb1x00_thread(void *_ucb) +{ + struct task_struct *tsk = current; + struct ucb1x00 *ucb = _ucb; + + tsk->policy = SCHED_FIFO; + tsk->rt_priority = 1; + + while (!kthread_should_stop()) { + wait_for_completion_interruptible(&ucb->irq_wait); + if (try_to_freeze()) + continue; + ucb1x00_irq(ucb->irq, ucb, NULL); + enable_irq(ucb->irq); + } + + ucb->irq_task = NULL; + return 0; +} + +static irqreturn_t ucb1x00_threaded_irq(int irqnr, void *devid, struct pt_regs *regs) +{ + struct ucb1x00 *ucb = devid; + if (irqnr == ucb->irq) { + disable_irq(ucb->irq); + complete(&ucb->irq_wait); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + /** * ucb1x00_hook_irq - hook a UCB1x00 interrupt * @ucb: UCB1x00 structure describing chip @@ -276,18 +324,22 @@ void ucb1x00_enable_irq(struct ucb1x00 * if (idx < 16) { spin_lock_irqsave(&ucb->lock, flags); - - ucb1x00_enable(ucb); - if (edges & UCB_RISING) { + if (edges & UCB_RISING) ucb->irq_ris_enbl |= 1 << idx; - ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); - } - if (edges & UCB_FALLING) { + if (edges & UCB_FALLING) ucb->irq_fal_enbl |= 1 << idx; - ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); - } - ucb1x00_disable(ucb); spin_unlock_irqrestore(&ucb->lock, flags); + + ucb1x00_enable(ucb); + + /* This prevents spurious interrupts on the UCB1400 */ + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); + + ucb1x00_disable(ucb); } } @@ -305,18 +357,16 @@ void ucb1x00_disable_irq(struct ucb1x00 if (idx < 16) { spin_lock_irqsave(&ucb->lock, flags); - - ucb1x00_enable(ucb); - if (edges & UCB_RISING) { + if (edges & UCB_RISING) ucb->irq_ris_enbl &= ~(1 << idx); - ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); - } - if (edges & UCB_FALLING) { + if (edges & UCB_FALLING) ucb->irq_fal_enbl &= ~(1 << idx); - ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); - } - ucb1x00_disable(ucb); spin_unlock_irqrestore(&ucb->lock, flags); + + ucb1x00_enable(ucb); + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); + ucb1x00_disable(ucb); } } @@ -349,16 +399,17 @@ int ucb1x00_free_irq(struct ucb1x00 *ucb ucb->irq_ris_enbl &= ~(1 << idx); ucb->irq_fal_enbl &= ~(1 << idx); - ucb1x00_enable(ucb); - ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); - ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); - ucb1x00_disable(ucb); - irq->fn = NULL; irq->devid = NULL; ret = 0; } spin_unlock_irq(&ucb->lock); + + ucb1x00_enable(ucb); + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); + ucb1x00_disable(ucb); + return ret; bad: @@ -478,7 +529,7 @@ static int ucb1x00_probe(struct mcp *mcp mcp_enable(mcp); id = mcp_reg_read(mcp, UCB_ID); - if (id != UCB_ID_1200 && id != UCB_ID_1300) { + if (id != UCB_ID_1200 && id != UCB_ID_1300 && !UCB_IS_1400(id)) { printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); goto err_disable; } @@ -491,12 +542,13 @@ static int ucb1x00_probe(struct mcp *mcp memset(ucb, 0, sizeof(struct ucb1x00)); ucb->cdev.class = &ucb1x00_class; - ucb->cdev.dev = &mcp->attached_device; + ucb->cdev.dev = mcp->dev; strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id)); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); sema_init(&ucb->adc_sem, 1); + init_completion(&ucb->irq_wait); ucb->id = id; ucb->mcp = mcp; @@ -507,13 +559,22 @@ static int ucb1x00_probe(struct mcp *mcp goto err_free; } - ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING, - "UCB1x00", ucb); + ret = request_irq(ucb->irq, + UCB_IS_1400(id) ? ucb1x00_threaded_irq : ucb1x00_irq, + SA_TRIGGER_RISING, "UCB1x00", ucb); if (ret) { printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", ucb->irq, ret); goto err_free; } + if (UCB_IS_1400(id)) { + ucb->irq_task = kthread_run(ucb1x00_thread, ucb, "kUCB1x00d"); + if (IS_ERR(ucb->irq_task)) { + ret = PTR_ERR(ucb->irq_task); + ucb->irq_task = NULL; + goto err_irq; + } + } mcp_set_drvdata(mcp, ucb); @@ -531,6 +592,8 @@ static int ucb1x00_probe(struct mcp *mcp goto out; err_irq: + if (UCB_IS_1400(id) && ucb->irq_task) + kthread_stop(ucb->irq_task); free_irq(ucb->irq, ucb); err_free: kfree(ucb); @@ -553,6 +616,10 @@ static void ucb1x00_remove(struct mcp *m } mutex_unlock(&ucb1x00_mutex); + if (UCB_IS_1400(ucb->id) && ucb->irq_task) { + complete(&ucb->irq_wait); + kthread_stop(ucb->irq_task); + } free_irq(ucb->irq, ucb); class_device_unregister(&ucb->cdev); } diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 79fd062..e68132d 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -35,7 +35,15 @@ #include #include #include + +/* FIXME: proper machine detection should be implemented */ +#ifdef CONFIG_SA1100_COLLIE #include +#else +#define machine_is_collie() (0) +#define COLLIE_TC35143_GPIO_TBL_CHK (0) +#endif + #include #include "ucb1x00.h" @@ -45,7 +53,7 @@ struct ucb1x00_ts { struct input_dev *idev; struct ucb1x00 *ucb; - wait_queue_head_t irq_wait; + struct completion irq_wait; struct task_struct *rtask; u16 x_res; u16 y_res; @@ -98,7 +106,8 @@ static inline unsigned int ucb1x00_ts_re udelay(55); return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync); - } else { + } + else { ucb1x00_reg_write(ts->ucb, UCB_TS_CR, UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | @@ -205,7 +214,6 @@ static int ucb1x00_thread(void *_ts) { struct ucb1x00_ts *ts = _ts; struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); int valid; /* @@ -217,10 +225,8 @@ static int ucb1x00_thread(void *_ts) valid = 0; - add_wait_queue(&ts->irq_wait, &wait); while (!kthread_should_stop()) { unsigned int x, y, p; - signed long timeout; ts->restart = 0; @@ -242,8 +248,6 @@ static int ucb1x00_thread(void *_ts) if (ucb1x00_ts_pen_down(ts)) { - set_task_state(tsk, TASK_INTERRUPTIBLE); - ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); ucb1x00_disable(ts->ucb); @@ -256,7 +260,15 @@ static int ucb1x00_thread(void *_ts) valid = 0; } - timeout = MAX_SCHEDULE_TIMEOUT; + /* + * Since ucb1x00_enable_irq() might sleep due + * to the way the UCB1400 regs are accessed, we + * can't use set_task_state() before that call, + * and not changing state before enabling the + * interrupt is racy. A completion handler avoids + * the issue. + */ + wait_for_completion_interruptible(&ts->irq_wait); } else { ucb1x00_disable(ts->ucb); @@ -271,16 +283,12 @@ static int ucb1x00_thread(void *_ts) } set_task_state(tsk, TASK_INTERRUPTIBLE); - timeout = HZ / 100; + schedule_timeout(HZ/100); } try_to_freeze(); - - schedule_timeout(timeout); } - remove_wait_queue(&ts->irq_wait, &wait); - ts->rtask = NULL; return 0; } @@ -293,7 +301,7 @@ static void ucb1x00_ts_irq(int idx, void { struct ucb1x00_ts *ts = id; ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); - wake_up(&ts->irq_wait); + complete(&ts->irq_wait); } static int ucb1x00_ts_open(struct input_dev *idev) @@ -303,7 +311,7 @@ static int ucb1x00_ts_open(struct input_ BUG_ON(ts->rtask); - init_waitqueue_head(&ts->irq_wait); + init_completion(&ts->irq_wait); ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); if (ret < 0) goto out; @@ -337,8 +345,10 @@ static void ucb1x00_ts_close(struct inpu { struct ucb1x00_ts *ts = idev->private; - if (ts->rtask) + if (ts->rtask) { + complete(&ts->irq_wait); kthread_stop(ts->rtask); + } ucb1x00_enable(ts->ucb); ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); @@ -358,7 +368,7 @@ static int ucb1x00_ts_resume(struct ucb1 * after sleep. */ ts->restart = 1; - wake_up(&ts->irq_wait); + complete(&ts->irq_wait); } return 0; } diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h index 9c9a647..ff04dc9 100644 --- a/drivers/mfd/ucb1x00.h +++ b/drivers/mfd/ucb1x00.h @@ -94,6 +94,7 @@ #define UCB_ADC_DAT(x) (((x) & 0x7fe0) #define UCB_ID 0x0c #define UCB_ID_1200 0x1004 #define UCB_ID_1300 0x1005 +#define UCB_ID_1400 0x4304 #define UCB_MODE 0x0d #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) @@ -110,6 +111,8 @@ struct ucb1x00 { spinlock_t lock; struct mcp *mcp; unsigned int irq; + struct task_struct *irq_task; + struct completion irq_wait; struct semaphore adc_sem; spinlock_t io_lock; u16 id; @@ -122,6 +125,7 @@ struct ucb1x00 { struct class_device cdev; struct list_head node; struct list_head devs; + }; struct ucb1x00_driver; diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1fc4c13..c238ede 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -182,6 +182,10 @@ config MTD_NAND_DISKONCHIP_BBTWRITE config MTD_NAND_SHARPSL bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" depends on MTD_NAND && ARCH_PXA + + config MTD_NAND_CM_X270 + tristate "Support for NAND Flash on CompuLab CM-X270" + depends on MTD_NAND && ARCH_PXA config MTD_NAND_NANDSIM bool "Support for NAND Flash Simulator" diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 4174202..9a9e0c9 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_NAND_DISKONCHIP) += dis obj-$(CONFIG_MTD_NAND_H1900) += h1910.o obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o +obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270-nand.o obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o nand-objs = nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/cmx270-nand.c b/drivers/mtd/nand/cmx270-nand.c new file mode 100644 index 0000000..32b6288 --- /dev/null +++ b/drivers/mtd/nand/cmx270-nand.c @@ -0,0 +1,281 @@ +/* + * drivers/mtd/nand/cmx270-nand.c + * + * Copyright (C) 2005 Compulab, Ltd. (mike@compulab.co.il) + * + * Derived from drivers/mtd/nand/h1910.c + * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * CM-X270 board. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define GPIO_NAND_CS (11) +#define GPIO_NAND_RB (89) + +#define DRAIN_WB() \ + do { \ + unsigned char dummy; \ + asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \ + dummy=*((volatile unsigned char*)UNCACHED_ADDR); \ + } while(0); + +/* + * MTD structure for CM-X270 board + */ +static struct mtd_info *cmx270_nand_mtd = NULL; + +/* + * Module stuff + */ + +#ifdef CONFIG_MTD_PARTITIONS +/* + * Define static partitions for flash device + */ +static struct mtd_partition partition_info[] = { + [0] = { + .name = "cmx270-0", + .offset = 0, + .size = MTDPART_SIZ_FULL + } +}; +#define NUM_PARTITIONS ARRAY_SIZE(partition_info) + +#endif + + +static u_char cmx270_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return (readl(this->IO_ADDR_R) >> 16); +} + +static void cmx270_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + writel((byte << 16), this->IO_ADDR_W); +} + +static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_W); + } +} + +static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_R) >> 16; + } +} + +static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_R) >> 16) ) + return -EFAULT; + } + + return 0; +} + +static inline void nand_cs_on(void) +{ + GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); +} + +static void nand_cs_off(void) +{ + DRAIN_WB(); + + GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); +} + +/* + * hardware specific access to control-lines + */ +static void cmx270_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip* this = (struct nand_chip *) (mtd->priv); + unsigned int nandaddr = (unsigned int)this->IO_ADDR_R; + + DRAIN_WB(); + + switch(cmd) { + + case NAND_CTL_SETCLE: + nandaddr |= (1 << 2); + this->IO_ADDR_R = (void __iomem*)nandaddr; + this->IO_ADDR_W = (void __iomem*)nandaddr; + break; + case NAND_CTL_CLRCLE: + nandaddr &= ~(1 << 2); + this->IO_ADDR_R = (void __iomem*)nandaddr; + this->IO_ADDR_W = (void __iomem*)nandaddr; + break; + + case NAND_CTL_SETALE: + nandaddr |= (1 << 3); + this->IO_ADDR_R = (void __iomem*)nandaddr; + this->IO_ADDR_W = (void __iomem*)nandaddr; + break; + case NAND_CTL_CLRALE: + nandaddr &= ~(1 << 3); + this->IO_ADDR_R = (void __iomem*)nandaddr; + this->IO_ADDR_W = (void __iomem*)nandaddr; + break; + + case NAND_CTL_SETNCE: + nand_cs_on(); + break; + case NAND_CTL_CLRNCE: + nand_cs_off(); + break; + } + + DRAIN_WB(); +} + +/* + * read device ready pin + */ +static int cmx270_device_ready(struct mtd_info *mtd) +{ + DRAIN_WB(); + return ( GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB) ); +} + +/* + * Main initialization routine + */ +static int __init cmx270_init (void) +{ + struct nand_chip *this; + const char *part_type = 0; + int mtd_parts_nb = 0; + struct mtd_partition *mtd_parts = 0; + static unsigned int nandaddr = 0; + + + /* Allocate memory for MTD device structure and private data */ + cmx270_nand_mtd = kmalloc(sizeof(struct mtd_info) + + sizeof(struct nand_chip), + GFP_KERNEL); + if (!cmx270_nand_mtd) { + printk("Unable to allocate CM-X270 NAND MTD device structure.\n"); + return -ENOMEM; + } + + nandaddr = (volatile unsigned int)ioremap(PXA_CS1_PHYS, 100); + + /* Get pointer to private data */ + this = (struct nand_chip *) (&cmx270_nand_mtd[1]); + + /* Initialize structures */ + memset((char *) cmx270_nand_mtd, 0, sizeof(struct mtd_info)); + memset((char *) this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + cmx270_nand_mtd->priv = this; + + /* insert callbacks */ + this->IO_ADDR_R = (void __iomem *)nandaddr; + this->IO_ADDR_W = (void __iomem *)nandaddr; + this->hwcontrol = cmx270_hwcontrol; +/* this->dev_ready = cmx270_device_ready; /\* unknown whether that was correct or not so we will just do it like this *\/ */ + + /* 15 us command delay time */ + this->chip_delay = 50; + this->eccmode = NAND_ECC_SOFT; + + /* read/write functions */ + this->read_byte = cmx270_read_byte; + this->write_byte = cmx270_write_byte; + this->read_buf = cmx270_read_buf; + this->write_buf = cmx270_write_buf; + this->verify_buf = cmx270_verify_buf; + + /* Scan to find existence of the device */ + if (nand_scan (cmx270_nand_mtd, 1)) { + printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); + iounmap((void*)nandaddr); + kfree (cmx270_nand_mtd); + return -ENXIO; + } + +#ifdef CONFIG_MTD_CMDLINE_PARTS + mtd_parts_nb = parse_cmdline_partitions(cmx270_nand_mtd, &mtd_parts, + "cmx270"); + if (mtd_parts_nb > 0) + part_type = "command line"; + else + mtd_parts_nb = 0; +#endif + if (mtd_parts_nb == 0) + { + mtd_parts = partition_info; + mtd_parts_nb = NUM_PARTITIONS; + part_type = "static"; + } + + /* Register the partitions */ + printk(KERN_NOTICE "Using %s partition definition\n", part_type); + add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); + + /* Return happy */ + return 0; +} +module_init(cmx270_init); + +/* + * Clean up routine + */ +static void __exit cmx270_cleanup (void) +{ + struct nand_chip *this; + + this = (struct nand_chip *) (&cmx270_nand_mtd[1]); + iounmap(this->IO_ADDR_R); + + /* Release resources, unregister device */ + nand_release (cmx270_nand_mtd); + + /* Free the MTD device structure */ + kfree (cmx270_nand_mtd); +} +module_exit(cmx270_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mike Rapoport "); +MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Core"); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index aa633fa..505f92b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -865,6 +865,14 @@ config DM9000 . The module will be called dm9000. +config DM9000_NOEPROM + bool "DM9000 without EEPROM attached" + depends on DM9000 + ---help--- + Select this option if you have DM9000 chipset without EEPROM + containing the MAC address. In this case MAC address should + be set either by the bootloader or using ifconfig + config NET_VENDOR_RACAL bool "Racal-Interlan (Micom) NI cards" depends on NET_ETHERNET && ISA diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 24996da..7e45756 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -561,8 +561,14 @@ #endif ((u16 *) db->srom)[i] = read_srom_word(db, i); /* Set Node Address */ +#ifndef CONFIG_DM9000_NOEPROM for (i = 0; i < 6; i++) ndev->dev_addr[i] = db->srom[i]; +#else + /* The Node Address was set by bootloader */ + for (i=0; i<6; i++) + ndev->dev_addr[i] = ior(db, 0x10+i); +#endif if (!is_valid_ether_addr(ndev->dev_addr)) printk("%s: Invalid ethernet MAC address. Please " @@ -1098,6 +1104,10 @@ dm9000_phy_read(struct net_device *dev, /* The read data keeps on REG_0D & REG_0E */ ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); +/* if ( reg == MII_BMSR ) { */ +/* printk(KERN_WARNING "===> %s: ret = %x\n", __FUNCTION__, ret); */ +/* } */ + /* restore the previous address */ writeb(reg_save, db->io_addr); @@ -1163,7 +1173,6 @@ dm9000_drv_resume(struct platform_device if (netif_running(ndev)) { dm9000_reset(db); dm9000_init_dm9000(ndev); - netif_device_attach(ndev); } } diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index bcecf51..b6a4173 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -68,4 +68,4 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o - +pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c new file mode 100644 index 0000000..eb4df11 --- /dev/null +++ b/drivers/pcmcia/pxa2xx_cm_x270.c @@ -0,0 +1,198 @@ +/* + * linux/drivers/pcmcia/pxa/pxa_armcore.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Compulab Ltd., 2003 + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "soc_common.h" + + +static struct pcmcia_irqs irqs[] = { + { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" }, + { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" }, +}; + + +static int +cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + int return_val=0; + + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | + GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | + GPIO_bit(GPIO85_nPCE_1) | + GPIO_bit(GPIO54_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO85_nPCE_1_MD); + pxa_gpio_mode(GPIO54_nPCE_2_MD); + //pxa_gpio_mode(GPIO79_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets (on ATX base not routed)*/ + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + + // Reset signal + GPDR(GPIO53_nPCE_2) |= GPIO_bit(GPIO53_nPCE_2); + GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); + + GPDR(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID)); + GPDR(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID)); + + set_irq_type(PCMCIA_S0_CD_VALID, IRQT_BOTHEDGE); + set_irq_type(PCMCIA_S1_CD_VALID, IRQT_BOTHEDGE); + + //irq's for slots: + GPDR(IRQ_TO_GPIO(PCMCIA_S0_RDYINT)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S0_RDYINT)); + GPDR(IRQ_TO_GPIO(PCMCIA_S1_RDYINT)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S1_RDYINT)); + + set_irq_type(PCMCIA_S0_RDYINT, IRQT_FALLING); + set_irq_type(PCMCIA_S1_RDYINT, IRQT_FALLING); + + skt->irq = (skt->nr == 0) ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT; + return_val = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); + + return return_val; +} + + +static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt) +{ + soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + + set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID), IRQT_NOEDGE); + set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID), IRQT_NOEDGE); + + set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_RDYINT), IRQT_NOEDGE); + set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_RDYINT), IRQT_NOEDGE); +} + + +static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, + struct pcmcia_state *state) +{ + + state->detect = (PCC_DETECT(skt->nr) == 0) ? 1 : 0; + state->ready = (PCC_READY(skt->nr) == 0) ? 0 : 1; + state->bvd1 = 1; + state->bvd2 = 1; + state->vs_3v = 0; + state->vs_Xv = 0; + state->wrprot = 0; /* not available */ + +} + + +static int +cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, + const socket_state_t *state) +{ + + GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); + pxa_gpio_mode(GPIO49_nPWE | GPIO_OUT); + //pxa_gpio_mode(GPIO79_pSKTSEL_MD | GPIO_OUT); /* For 2-socket mode */ + + switch(skt->nr){ + case 0: + if(state->flags & SS_RESET) { + //GPCR(GPIO79_pSKTSEL) = GPIO_bit(GPIO79_pSKTSEL); /* For 2-socket mode */ + //udelay(1); + GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); + GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); + udelay(10); + GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); + GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); + } + break; + case 1: + if(state->flags & SS_RESET) { + //GPCR(GPIO79_pSKTSEL) = GPIO_bit(GPIO79_pSKTSEL); /* For 2-socket mode */ + //udelay(1); + GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); + GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); + udelay(10); + GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); + GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); + } + break; + } + + pxa_gpio_mode(GPIO49_nPWE_MD); + //pxa_gpio_mode(GPIO79_pSKTSEL_MD); /* For 2-socket mode */ + + + return 0; +} + +static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt) +{ +} + +static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) +{ +} + + +static struct pcmcia_low_level cmx270_pcmcia_ops = { + .owner = THIS_MODULE, + .hw_init = cmx270_pcmcia_hw_init, + .hw_shutdown = cmx270_pcmcia_shutdown, + .socket_state = cmx270_pcmcia_socket_state, + .configure_socket = cmx270_pcmcia_configure_socket, + .socket_init = cmx270_pcmcia_socket_init, + .socket_suspend = cmx270_pcmcia_socket_suspend, + .nr = 2, +}; + +static struct platform_device *cmx270_pcmcia_device; + +static int __init cmx270_pcmcia_init(void) +{ + int ret; + + cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); + + if (!cmx270_pcmcia_device) + return -ENOMEM; + + cmx270_pcmcia_device->dev.platform_data = &cmx270_pcmcia_ops; + + printk ("Registering cm-x270 PCMCIA interface.\n"); + ret = platform_device_add(cmx270_pcmcia_device); + + if (ret) + platform_device_put(cmx270_pcmcia_device); + + return ret; +} + +static void __exit cmx270_pcmcia_exit(void) +{ + platform_device_unregister(cmx270_pcmcia_device); +} + +module_init(cmx270_pcmcia_init); +module_exit(cmx270_pcmcia_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 10535f0..7f7fd02 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -49,6 +49,21 @@ #include #include #include +#define SERIAL_SA1100_MAJOR 204 +#define MINOR_START 5 + +#ifdef CONFIG_MACH_ARMCORE +extern int machine_is_cmx270l(void); +#define SWITCH_CONSOLE() \ + do { \ + if ( machine_is_cmx270l() ) { \ + serial_pxa_switch_ports(&serial_pxa_ports[0], \ + &serial_pxa_ports[1]); \ + } \ + } while (0) +#else +#define SWITCH_CONSOLE() do {} while (0) +#endif struct uart_pxa_port { struct uart_port port; @@ -584,6 +599,23 @@ serial_pxa_type(struct uart_port *port) return up->name; } +static void +serial_pxa_switch_ports(struct uart_pxa_port* port1, + struct uart_pxa_port* port2) +{ + int tmp_line; + static struct uart_pxa_port tmp_port; + + tmp_line = port1->port.line; + port1->port.line = port2->port.line; + port2->port.line = tmp_line; + + memcpy(&tmp_port, port1, sizeof(struct uart_pxa_port)); + memcpy(port1, port2, sizeof(struct uart_pxa_port)); + memcpy(port2, &tmp_port, sizeof(struct uart_pxa_port)); +} + + #ifdef CONFIG_SERIAL_PXA_CONSOLE static struct uart_pxa_port serial_pxa_ports[]; @@ -683,7 +715,7 @@ serial_pxa_console_setup(struct console } static struct console serial_pxa_console = { - .name = "ttyS", + .name = "ttySA", .write = serial_pxa_console_write, .device = uart_console_device, .setup = serial_pxa_console_setup, @@ -695,6 +727,8 @@ static struct console serial_pxa_console static int __init serial_pxa_console_init(void) { + SWITCH_CONSOLE(); + register_console(&serial_pxa_console); return 0; } @@ -788,11 +822,16 @@ static struct uart_pxa_port serial_pxa_p static struct uart_driver serial_pxa_reg = { .owner = THIS_MODULE, - .driver_name = "PXA serial", - .devfs_name = "tts/", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, +/* .driver_name = "PXA serial", */ +/* .devfs_name = "tts/", */ +/* .dev_name = "ttyS", */ +/* .major = TTY_MAJOR, */ +/* .minor = 64, */ + .driver_name = "ttySA", + .dev_name = "ttySA", + .devfs_name = "ttySA", + .major = SERIAL_SA1100_MAJOR, + .minor = MINOR_START, .nr = ARRAY_SIZE(serial_pxa_ports), .cons = PXA_CONSOLE, }; @@ -852,6 +891,10 @@ int __init serial_pxa_init(void) { int ret; +#ifndef CONFIG_SERIAL_PXA_CONSOLE + SWITCH_CONSOLE(); +#endif + ret = uart_register_driver(&serial_pxa_reg); if (ret != 0) return ret; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f5079c7..e49580a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1387,6 +1387,16 @@ config FB_PXA_PARAMETERS describes the available parameters. +config FB_MBX + tristate "2700G LCD framebuffer support" + depends on FB && ARCH_PXA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + + If unsure, say N. + config FB_W100 tristate "W100 frame buffer support" depends on FB && PXA_SHARPSL diff --git a/drivers/video/Makefile b/drivers/video/Makefile index aa434e7..c6fe5e4 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_FB_TX3912) += tx3912fb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o +obj-$(CONFIG_FB_MBX) += mbx/ # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o diff --git a/drivers/video/mbx/Makefile b/drivers/video/mbx/Makefile new file mode 100644 index 0000000..ef6b729 --- /dev/null +++ b/drivers/video/mbx/Makefile @@ -0,0 +1,7 @@ +# Makefile for the Linux video drivers. +# 5 Aug 1999, James Simmons, +# Rewritten to use lists instead of if-statements. + +# Each configuration option enables a list of files. + +obj-$(CONFIG_FB_MBX) += mbxfb.o diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c new file mode 100644 index 0000000..93dcfa5 --- /dev/null +++ b/drivers/video/mbx/mbxfb.c @@ -0,0 +1,659 @@ +/* + * linux/drivers/video/mbx/mbxfb.c + * + * Copyright (C) 2006 Compulab, Ltd. + * + * Based on pxafb.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long virt_base_2700; +#include "regs.h" +#include "reg_bits.h" + +#define MIN_XRES 16 +#define MIN_YRES 16 +#define MAX_XRES 2048 +#define MAX_YRES 2048 + +/* FIXME: take care of different chip reivsions with different sizes + of ODFB */ +#define MEMORY_OFFSET 0x60000 + +struct mbxfb_info { + struct device *dev; + + struct resource *fb_res; + struct resource *fb_req; + + struct resource *reg_res; + struct resource *reg_req; + + void __iomem *fb_virt_addr; + unsigned long fb_phys_addr; + + void __iomem *reg_virt_addr; + unsigned long reg_phys_addr; + + int (*platform_probe)(struct fb_info *fb); + int (*platform_remove)(struct fb_info *fb); +}; + +static struct fb_var_screeninfo mbxfb_default __initdata = { + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 480, + .bits_per_pixel = 16, + .red = { 11, 5, 0 }, + .green = { 5, 6, 0 }, + .blue = { 0, 5, 0 }, + .activate = FB_ACTIVATE_TEST, + .height = -1, + .width = -1, + .pixclock = 40000, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 33, + .lower_margin = 10, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, +}; + +static struct fb_fix_screeninfo mbxfb_fix __initdata = { + .id = "MBX", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +struct pixclock_div { + u8 m; + u8 n; + u8 p; +}; + +static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps, struct pixclock_div *div) +{ + u8 m, n, p; + unsigned int err = 0; + unsigned int min_err = ~0x0; + unsigned int clk; + unsigned int best_clk = 0; + unsigned int ref_clk = 13000; /* FIXME: take from platform data */ + unsigned int pixclock; + + /* convert pixclock to KHz */ + pixclock = PICOS2KHZ(pixclock_ps); + + for ( m = 1; m < 64; m++ ) { + for ( n = 1; n < 8; n++ ) { + for ( p = 0; p < 8; p++ ) { + clk = (ref_clk * m) / (n * (1 << p)); + err = (clk > pixclock) ? (clk - pixclock) : + (pixclock - clk); + if ( err < min_err ) { + min_err = err; + best_clk = clk; + div->m = m; + div->n = n; + div->p = p; + } + } + } + } + return KHZ2PICOS(best_clk); +} + +static int +mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int trans, struct fb_info *info) +{ + uint val, ret = 1; + + if ( regno < 255 ) { + val = (red & 0xff) << 16; + val |= (green & 0xff) << 8; + val |= (blue & 0xff) << 0; + GPLUT = Gplut_Lutadr(regno) | Gplut_Lutdata(val); + udelay(1000); + ret = 0; + } + return ret; +} + +static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct pixclock_div div; + + var->pixclock = mbxfb_get_pixclock(var->pixclock, &div); + + if (var->xres < MIN_XRES) + var->xres = MIN_XRES; + if (var->yres < MIN_YRES) + var->yres = MIN_YRES; + if (var->xres > MAX_XRES) + var->xres = MAX_XRES; + if (var->yres > MAX_YRES) + var->yres = MAX_YRES; + var->xres_virtual = + max(var->xres_virtual, var->xres); + var->yres_virtual = + max(var->yres_virtual, var->yres); + + switch (var->bits_per_pixel) { + /* FIXME: implement 8 bits-per-pixel */ + case 8: + var->bits_per_pixel = 16; + case 16: + var->green.length = (var->green.length == 5) ? 5 : 6; + var->red.length = 5; + var->blue.length = 5; + var->transp.length = 6 - var->green.length; + var->blue.offset = 0; + var->green.offset = 5; + var->red.offset = 5 + var->green.length; + var->transp.offset = (5 + var->red.offset) & 15; + break; + case 24: /* RGB 888 */ + case 32: /* RGBA 8888 */ + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.length = var->bits_per_pixel - 24; + var->transp.offset = (var->transp.length) ? 24 : 0; + break; + } + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + + return 0; +} + +static int mbxfb_set_par(struct fb_info *info) +{ + struct fb_var_screeninfo *var = &info->var; + struct pixclock_div div; + ushort hbps, ht, hfps, has; + ushort vbps, vt, vfps, vas; + + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; + + /* setup color mode */ + GSCTRL &= ~(FMsk(GSCTRL_GPIXFMT)); + /* FIXME: add *WORKING* support for 8-bits per color */ + if ( info->var.bits_per_pixel == 8 ) { + GSCTRL |= GSCTRL_GPIXFMT_INDEXED; + GSCTRL |= GSCTRL_LUT_EN; + GSCTRL &= ~GSCTRL_GAMMA_EN; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + fb_alloc_cmap(&info->cmap, 1<var.bits_per_pixel, 0); + } + else { + fb_dealloc_cmap(&info->cmap); + GSCTRL &= ~GSCTRL_LUT_EN; + info->fix.visual = FB_VISUAL_TRUECOLOR; + switch ( info->var.bits_per_pixel ) { + case 16: + if ( info->var.green.length == 5 ) + GSCTRL |= GSCTRL_GPIXFMT_ARGB1555; + else + GSCTRL |= GSCTRL_GPIXFMT_RGB565; + break; + case 24: + GSCTRL |= GSCTRL_GPIXFMT_RGB888; + break; + case 32: + GSCTRL |= GSCTRL_GPIXFMT_ARGB8888; + break; + } + } + + /* setup resolution */ + GSCTRL &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); + GSCTRL |= Gsctrl_Width(info->var.xres - 1) | + Gsctrl_Height(info->var.yres - 1); + + GSADR &= ~(FMsk(GSADR_SRCSTRIDE)); udelay(1000); + GSADR |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / (8 * 16) - 1); udelay(1000); + + /* setup timings */ + var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); + + DISPPLL = Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | Disp_Pll_P(div.p) | DISP_PLL_EN; + + hbps = var->hsync_len; + has = hbps + var->left_margin; + hfps = has + var->xres; + ht = hfps + var->right_margin; + + vbps = var->vsync_len; + vas = vbps + var->upper_margin; + vfps = vas + var->yres; + vt = vfps + var->lower_margin; + + DHT01 = Dht01_Hbps(hbps) | Dht01_Ht(ht); + DHT02 = Dht02_Hlbs(has) | Dht02_Has(has); + DHT03 = Dht03_Hfps(hfps) | Dht03_Hrbs(hfps); + DHDET = Dhdet_Hdes(has) | Dhdet_Hdef(hfps); + + DVT01 = Dvt01_Vbps(vbps) | Dvt01_Vt(vt); + DVT02 = Dvt02_Vtbs(vas) | Dvt02_Vas(vas); + DVT03 = Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps); + DVDET = Dvdet_Vdes(vas) | Dvdet_Vdef(vfps); + DVECTRL = Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps); + DSCTRL |= DSCTRL_SYNCGEN_EN; + + return 0; +} + +static char *blank_mode[] = { + "FB_BLANK_UNBLANK", + "FB_BLANK_NORMAL", + "FB_BLANK_VSYNC_SUSPEND", + "FB_BLANK_HSYNC_SUSPEND", + "FB_BLANK_POWERDOWN", +}; + +static int mbxfb_blank(int blank, struct fb_info *info) +{ + switch (blank) { + case FB_BLANK_POWERDOWN: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_NORMAL: + DSCTRL &= ~DSCTRL_SYNCGEN_EN; udelay(1000); + PIXCLK &= ~PIXCLK_EN; udelay(1000); + VOVRCLK &= ~VOVRCLK_EN; udelay(1000); + break; + case FB_BLANK_UNBLANK: + DSCTRL |= DSCTRL_SYNCGEN_EN; udelay(1000); + PIXCLK |= PIXCLK_EN; udelay(1000); + break; + } + return 0; +} + +static struct fb_ops mbxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = mbxfb_check_var, + .fb_set_par = mbxfb_set_par, + .fb_setcolreg = mbxfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_blank = mbxfb_blank, +}; + +/* + Enable external SDRAM controller. Assume that all clocks are active + by now. +*/ +static void setup_memc(struct fb_info *fbi) +{ + unsigned long tmp; + + /* FIXME: use platfrom specific parameters */ + /* setup SDRAM controller */ + LMCFG = LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS; + udelay(1000); + LMPWR = LMPWR_MC_PWR_ACT; + udelay(1000); + /* setup SDRAM timings */ + LMTIM = Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | Lmtim_Trc(9) | + Lmtim_Tdpl(2); + udelay(1000); + /* setup SDRAM refresh rate */ + LMREFRESH = 0xc2b; + udelay(1000); + /* setup SDRAM type parameters */ + LMTYPE = LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | + LMTYPE_COLSZ_8; + udelay(1000); + /* enable memory controller */ + LMPWR = LMPWR_MC_PWR_ACT; + udelay(1000); + + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); + tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); +} + +static void enable_clocks(struct fb_info* fbi) +{ + /* enable clocks */ + SYSCLKSRC = SYSCLKSRC_PLL_2; udelay(1000); + PIXCLKSRC = PIXCLKSRC_PLL_1; udelay(1000); + CLKSLEEP = 0x00000000; udelay(1000); + COREPLL = Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | CORE_PLL_EN; udelay(1000); + DISPPLL = Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | DISP_PLL_EN; + + VOVRCLK = 0x00000000; udelay(1000); + PIXCLK = PIXCLK_EN; udelay(1000); + MEMCLK = MEMCLK_EN; udelay(1000); + M24CLK = 0x00000006; udelay(1000); + MBXCLK = 0x00000006; udelay(1000); + SDCLK = SDCLK_EN; udelay(1000); + PIXCLKDIV = 0x00000001; udelay(1000); +} + +static void setup_graphics(struct fb_info* fbi) +{ + unsigned long gsctrl; + + gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres-1) | + Gsctrl_Height(fbi->var.yres-1); + switch ( fbi->var.bits_per_pixel ) { + case 16: + if ( fbi->var.green.length == 5 ) + gsctrl |= GSCTRL_GPIXFMT_ARGB1555; + else + gsctrl |= GSCTRL_GPIXFMT_RGB565; + break; + case 24: gsctrl |= GSCTRL_GPIXFMT_RGB888; break; + case 32: gsctrl |= GSCTRL_GPIXFMT_ARGB8888; break; + } + + GSCTRL = gsctrl; udelay(1000); + GBBASE = 0x00000000; udelay(1000); + GDRCTRL = 0x00ffffff; udelay(1000); + GSCADR = GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000); udelay(1000); + GPLUT = 0x00000000; udelay(1000); +} + +static void setup_display(struct fb_info* fbi) +{ + unsigned long dsctrl = 0; + + dsctrl = DSCTRL_BLNK_POL; + if ( fbi->var.sync & FB_SYNC_HOR_HIGH_ACT ) + dsctrl |= DSCTRL_HS_POL; + if ( fbi->var.sync & FB_SYNC_VERT_HIGH_ACT ) + dsctrl |= DSCTRL_VS_POL; + DSCTRL = dsctrl; udelay(1000); + DMCTRL = 0xd0303010; udelay(1000); + DSCTRL |= DSCTRL_SYNCGEN_EN; +} + +static void enable_controller(struct fb_info* fbi) +{ + SYSRST = SYSRST_RST; + udelay(1000); + + enable_clocks(fbi); + setup_memc(fbi); + setup_graphics(fbi); + setup_display(fbi); +} + + +#ifdef CONFIG_PM +/* + * Power management hooks. Note that we won't be called from IRQ context, + * unlike the blank functions above, so we may sleep. + */ +static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) +{ + /* make frame buffer memory enter self-refresh mode */ + LMPWR = LMPWR_MC_PWR_SRM; + while ( LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM ); + + /* reset the device, since it's initial state is 'mostly sleeping' */ + SYSRST = SYSRST_RST; + return 0; +} + +static int mbxfb_resume(struct platform_device *dev) +{ + struct fb_info *fbi = (struct fb_info*)platform_get_drvdata(dev); + + enable_clocks(fbi); +/* setup_graphics(fbi); */ +/* setup_display(fbi); */ + + DSCTRL |= DSCTRL_SYNCGEN_EN; + return 0; +} +#else +#define mbxfb_suspend NULL +#define mbxfb_resume NULL +#endif + +#include "mbxsysfs.c" + +#define res_size(_r) (((_r)->end - (_r)->start) + 1) + +static int mbxfb_probe(struct platform_device *dev) +{ + int ret; + struct fb_info *fbi; + struct mbxfb_info *mfbi; + struct mbxfb_platform_data *pdata; + + dev_dbg(dev, "mbxfb_probe\n"); + + fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); + if ( fbi == NULL ) { + dev_err(&dev->dev, "framebuffer_alloc failed\n"); + return -ENOMEM; + } + + mfbi = fbi->par; + pdata = dev->dev.platform_data; + if ( pdata->probe ) + mfbi->platform_probe = pdata->probe; + if ( pdata->remove ) + mfbi->platform_remove = pdata->remove; + + mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0); + mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1); + + if ( !mfbi->fb_res || !mfbi->reg_res ) { + dev_err(&dev->dev, "no resources found\n"); + ret = -ENODEV; + goto err1; + } + + mfbi->fb_req = request_mem_region(mfbi->fb_res->start, + res_size(mfbi->fb_res), + dev->name); + if ( mfbi->fb_req == NULL ) { + dev_err(&dev->dev, "failed to claim framebuffer memory\n"); + ret = -EINVAL; + goto err1; + } + mfbi->fb_phys_addr = mfbi->fb_res->start; + + mfbi->reg_req = request_mem_region(mfbi->reg_res->start, + res_size(mfbi->reg_res), + dev->name); + if ( mfbi->reg_req == NULL ) { + dev_err(&dev->dev, "failed to claim Marathon registers\n"); + ret = -EINVAL; + goto err2; + } + mfbi->reg_phys_addr = mfbi->reg_res->start; + + mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr, + res_size(mfbi->reg_req)); + if ( !mfbi->reg_virt_addr ) { + dev_err(&dev->dev, "failed to ioremap Marathon registers\n"); + ret = -EINVAL; + goto err3; + } + virt_base_2700 = mfbi->reg_virt_addr; + + mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, + res_size(mfbi->fb_req)); + if ( !mfbi->reg_virt_addr ) { + dev_err(&dev->dev, "failed to ioremap frame buffer\n"); + ret = -EINVAL; + goto err4; + } + + fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); /* FIXME: */ + fbi->screen_size = 8*1024*1024; /* 8 Megs */ /* FIXME: get from platform */ + fbi->fbops = &mbxfb_ops; + + fbi->var = mbxfb_default; + fbi->fix = mbxfb_fix; + fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; + fbi->fix.smem_len = 8*1024*1024; + fbi->fix.line_length = 640*2; + + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret < 0) { + dev_err(&dev->dev, "fb_alloc_cmap failed\n"); + ret = -EINVAL; + goto err5; + } + + ret = register_framebuffer(fbi); + if (ret < 0) { + dev_err(&dev->dev, "register_framebuffer failed\n"); + ret = -EINVAL; + goto err6; + } + + platform_set_drvdata(dev, fbi); + + printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node); + + if ( mfbi->platform_probe ) + mfbi->platform_probe(fbi); + + enable_controller(fbi); + + mbxfb_sysfs_register(fbi); + + return 0; + + err6: + fb_dealloc_cmap(&fbi->cmap); + err5: + iounmap(mfbi->fb_virt_addr); + err4: + iounmap(mfbi->reg_virt_addr); + err3: + release_mem_region(mfbi->reg_res->start, + res_size(mfbi->reg_res)); + err2: + release_mem_region(mfbi->fb_res->start, + res_size(mfbi->fb_res)); + err1: + framebuffer_release(fbi); + + return ret; +} + +static int mbxfb_remove(struct platform_device *dev) +{ + struct fb_info *fbi = (struct fb_info*)platform_get_drvdata(dev); + + SYSRST = SYSRST_RST; + udelay(1000); + + if (fbi) { + struct mbxfb_info *mfbi = fbi->par; + + unregister_framebuffer(fbi); + if ( mfbi ) { + if ( mfbi->platform_remove ) + mfbi->platform_remove(fbi); + + if ( mfbi->fb_virt_addr ) + iounmap(mfbi->fb_virt_addr); + if ( mfbi->reg_virt_addr ) + iounmap(mfbi->reg_virt_addr); + if ( mfbi->reg_req ) + release_mem_region(mfbi->reg_req->start, + res_size(mfbi->reg_req)); + if ( mfbi->fb_req ) + release_mem_region(mfbi->fb_req->start, + res_size(mfbi->fb_req)); + } + framebuffer_release(fbi); + } + + return 0; +} + +static struct platform_driver mbxfb_driver = { + .probe = mbxfb_probe, + .remove = mbxfb_remove, + +#ifdef CONFIG_PM + .suspend = mbxfb_suspend, + .resume = mbxfb_resume, +#endif + .driver = { + .name = "mbx-fb", + }, +}; + +int __devinit mbxfb_init(void) +{ + return platform_driver_register(&mbxfb_driver); +} + +static void __exit mbxfb_exit(void) +{ + platform_driver_unregister(&mbxfb_driver); +} + +module_init(mbxfb_init); +module_exit(mbxfb_exit); + +MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); +MODULE_AUTHOR("Mike Rapoport, Compulab"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/mbx/mbxsysfs.c b/drivers/video/mbx/mbxsysfs.c new file mode 100644 index 0000000..4b9571a --- /dev/null +++ b/drivers/video/mbx/mbxsysfs.c @@ -0,0 +1,129 @@ +static ssize_t sysconf_show(struct class_device * subsys, char * buf) +{ + char * s = buf; + + s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); + s += sprintf(s, "PFBASE = %08lx\n", PFBASE); + s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); + s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); + s += sprintf(s, "SYSRST = %08lx\n", SYSRST); + return (s - buf); +} + +static ssize_t sysconf_store(struct class_device * subsys, const char * buf, size_t n) +{ + return n; +} + +static ssize_t gsctl_show(struct class_device * subsys, char * buf) +{ + char * s = buf; + + s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); + s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); + s += sprintf(s, "GBBASE = %08lx\n", GBBASE); + s += sprintf(s, "VBBASE = %08lx\n", VBBASE); + s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); + s += sprintf(s, "VCMSK = %08lx\n", VCMSK); + s += sprintf(s, "GSCADR = %08lx\n", GSCADR); + s += sprintf(s, "VSCADR = %08lx\n", VSCADR); + s += sprintf(s, "VUBASE = %08lx\n", VUBASE); + s += sprintf(s, "VVBASE = %08lx\n", VVBASE); + s += sprintf(s, "GSADR = %08lx\n", GSADR); + s += sprintf(s, "VSADR = %08lx\n", VSADR); + s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); + s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); + s += sprintf(s, "HCPOS = %08lx\n", HCPOS); + s += sprintf(s, "HCBADR = %08lx\n", HCBADR); + s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); + s += sprintf(s, "GPLUT = %08lx\n", GPLUT); + return (s - buf); +} + +static ssize_t gsctl_store(struct class_device * subsys, const char * buf, size_t n) +{ + return n; +} + +static ssize_t display_show(struct class_device * subsys, char * buf) +{ + char * s = buf; + + s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); + s += sprintf(s, "DHT01 = %08lx\n", DHT01); + s += sprintf(s, "DHT02 = %08lx\n", DHT02); + s += sprintf(s, "DHT03 = %08lx\n", DHT03); + s += sprintf(s, "DVT01 = %08lx\n", DVT01); + s += sprintf(s, "DVT02 = %08lx\n", DVT02); + s += sprintf(s, "DVT03 = %08lx\n", DVT03); + s += sprintf(s, "DBCOL = %08lx\n", DBCOL); + s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); + s += sprintf(s, "DINTRS = %08lx\n", DINTRS); + s += sprintf(s, "DINTRE = %08lx\n", DINTRE); + s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); + s += sprintf(s, "DSIG = %08lx\n", DSIG); + s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); + s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); + s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); + s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); + s += sprintf(s, "DLSTS = %08lx\n", DLSTS); + s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); + s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); + s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); + s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); + s += sprintf(s, "DHDET = %08lx\n", DHDET); + s += sprintf(s, "DVDET = %08lx\n", DVDET); + s += sprintf(s, "DODMSK = %08lx\n", DODMSK); + s += sprintf(s, "CSC01 = %08lx\n", CSC01); + s += sprintf(s, "CSC02 = %08lx\n", CSC02); + s += sprintf(s, "CSC03 = %08lx\n", CSC03); + s += sprintf(s, "CSC04 = %08lx\n", CSC04); + s += sprintf(s, "CSC05 = %08lx\n", CSC05); + return (s - buf); +} + +static ssize_t display_store(struct class_device * subsys, const char * buf, size_t n) +{ + return n; +} + +static ssize_t clock_show(struct class_device * subsys, char * buf) +{ + char * s = buf; + + s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); + s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); + s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); + s += sprintf(s, "COREPLL = %08lx\n", COREPLL); + s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); + s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); + s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); + s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); + s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); + s += sprintf(s, "M24CLK = %08lx\n", M24CLK); + s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); + s += sprintf(s, "SDCLK = %08lx\n", SDCLK); + s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); + return (s - buf); +} + +static ssize_t clock_store(struct class_device * subsys, const char * buf, size_t n) +{ + return n; +} + +static struct class_device_attribute mbx_class_attrs[] = { + __ATTR(sysconf,0644,sysconf_show,sysconf_store), + __ATTR(gsctl,0644,gsctl_show,gsctl_store), + __ATTR(display,0644,display_show,display_store), + __ATTR(clock,0644,clock_show,clock_store), +}; + + +static void mbxfb_sysfs_register(struct fb_info *fbi) +{ + int i; + for (i = 0; i < ARRAY_SIZE(mbx_class_attrs); i++) + class_device_create_file(fbi->class_device, + &mbx_class_attrs[i]); +} diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h new file mode 100644 index 0000000..be152f6 --- /dev/null +++ b/drivers/video/mbx/reg_bits.h @@ -0,0 +1,489 @@ +#ifndef __REG_BITS_2700G_ +#define __REG_BITS_2700G_ + +/* /\* System Configuration Registers (0x03FE_0000 0x03FE_0010) *\/ */ +/* #define SYSCFG __REG_2700G(0x03FE0000) */ +/* #define PFBASE __REG_2700G(0x03FE0004) */ +/* #define PFCEIL __REG_2700G(0x03FE0008) */ +/* #define POLLFLAG __REG_2700G(0x03FE000C) */ + +#define SYSRST_RST (1 << 0) + +/* /\* Interrupt Control Registers (0x03FE_0014 0x03FE_002F) *\/ */ +/* #define NINTPW __REG_2700G(0x03FE0014) */ +/* #define MINTENABLE __REG_2700G(0x03FE0018) */ +/* #define MINTSTAT __REG_2700G(0x03FE001C) */ +/* #define SINTENABLE __REG_2700G(0x03FE0020) */ +/* #define SINTSTAT __REG_2700G(0x03FE0024) */ +/* #define SINTCLR __REG_2700G(0x03FE0028) */ + +/* SYSCLKSRC - SYSCLK Source Control Register */ +#define SYSCLKSRC_SEL Fld(2,0) +#define SYSCLKSRC_REF ((0x0) << FShft(SYSCLKSRC_SEL)) +#define SYSCLKSRC_PLL_1 ((0x1) << FShft(SYSCLKSRC_SEL)) +#define SYSCLKSRC_PLL_2 ((0x2) << FShft(SYSCLKSRC_SEL)) + +/* PIXCLKSRC - PIXCLK Source Control Register */ +#define PIXCLKSRC_SEL Fld(2,0) +#define PIXCLKSRC_REF ((0x0) << FShft(PIXCLKSRC_SEL)) +#define PIXCLKSRC_PLL_1 ((0x1) << FShft(PIXCLKSRC_SEL)) +#define PIXCLKSRC_PLL_2 ((0x2) << FShft(PIXCLKSRC_SEL)) + +/* Clock Disable Register */ +#define CLKSLEEP_SLP (1 << 0) + +/* Core PLL Control Register */ +#define CORE_PLL_M Fld(6,7) +#define Core_Pll_M(x) ((x) << FShft(CORE_PLL_M)) +#define CORE_PLL_N Fld(3,4) +#define Core_Pll_N(x) ((x) << FShft(CORE_PLL_N)) +#define CORE_PLL_P Fld(3,1) +#define Core_Pll_P(x) ((x) << FShft(CORE_PLL_P)) +#define CORE_PLL_EN (1 << 0) + +/* Display PLL Control Register */ +#define DISP_PLL_M Fld(6,7) +#define Disp_Pll_M(x) ((x) << FShft(DISP_PLL_M)) +#define DISP_PLL_N Fld(3,4) +#define Disp_Pll_N(x) ((x) << FShft(DISP_PLL_N)) +#define DISP_PLL_P Fld(3,1) +#define Disp_Pll_P(x) ((x) << FShft(DISP_PLL_P)) +#define DISP_PLL_EN (1 << 0) + +/* PLL status register */ +#define PLLSTAT_CORE_PLL_LOST_L (1 << 3) +#define PLLSTAT_CORE_PLL_LSTS (1 << 2) +#define PLLSTAT_DISP_PLL_LOST_L (1 << 1) +#define PLLSTAT_DISP_PLL_LSTS (1 << 0) + +/* Video and scale clock control register */ +#define VOVRCLK_EN (1 << 0) + +/* Pixel clock control register */ +#define PIXCLK_EN (1 << 0) + +/* Memory clock control register */ +#define MEMCLK_EN (1 << 0) + +/* MBX clock control register */ +#define MBXCLK_DIV Fld(2,2) +#define MBXCLK_DIV_1 ((0x0) << FShft(MBXCLK_DIV)) +#define MBXCLK_DIV_2 ((0x1) << FShft(MBXCLK_DIV)) +#define MBXCLK_DIV_3 ((0x2) << FShft(MBXCLK_DIV)) +#define MBXCLK_DIV_4 ((0x3) << FShft(MBXCLK_DIV)) +#define MBXCLK_EN Fld(2,0) +#define MBXCLK_EN_NONE ((0x0) << FShft(MBXCLK_EN)) +#define MBXCLK_EN_2D ((0x1) << FShft(MBXCLK_EN)) +#define MBXCLK_EN_BOTH ((0x2) << FShft(MBXCLK_EN)) + +/* M24 clock control register */ +#define M24CLK_DIV Fld(2,1) +#define M24CLK_DIV_1 ((0x0) << FShft(M24CLK_DIV)) +#define M24CLK_DIV_2 ((0x1) << FShft(M24CLK_DIV)) +#define M24CLK_DIV_3 ((0x2) << FShft(M24CLK_DIV)) +#define M24CLK_DIV_4 ((0x3) << FShft(M24CLK_DIV)) +#define M24CLK_EN (1 << 0) + +/* SDRAM clock control register */ +#define SDCLK_EN (1 << 0) + +/* PixClk Divisor Register */ +#define PIXCLKDIV_PD Fld(9,0) +#define Pixclkdiv_Pd(x) ((x) << FShft(PIXCLKDIV_PD)) + +/* LCD Config control register */ +#define LCDCFG_IN_FMT Fld(3,28) +#define Lcdcfg_In_Fmt(x) ((x) << FShft(LCDCFG_IN_FMT)) +#define LCDCFG_LCD1DEN_POL (1 << 27) +#define LCDCFG_LCD1FCLK_POL (1 << 26) +#define LCDCFG_LCD1LCLK_POL (1 << 25) +#define LCDCFG_LCD1D_POL (1 << 24) +#define LCDCFG_LCD2DEN_POL (1 << 23) +#define LCDCFG_LCD2FCLK_POL (1 << 22) +#define LCDCFG_LCD2LCLK_POL (1 << 21) +#define LCDCFG_LCD2D_POL (1 << 20) +#define LCDCFG_LCD1_TS (1 << 19) +#define LCDCFG_LCD1D_DS (1 << 18) +#define LCDCFG_LCD1C_DS (1 << 17) +#define LCDCFG_LCD1_IS_IN (1 << 16) +#define LCDCFG_LCD2_TS (1 << 3) +#define LCDCFG_LCD2D_DS (1 << 2) +#define LCDCFG_LCD2C_DS (1 << 1) +#define LCDCFG_LCD2_IS_IN (1 << 0) + +/* On-Die Frame Buffer Power Control Register */ +#define ODFBPWR_SLOW (1 << 2) +#define ODFBPWR_MODE Fld(2,0) +#define ODFBPWR_MODE_ACT ((0x0) << FShft(ODFBPWR_MODE)) +#define ODFBPWR_MODE_ACT_LP ((0x1) << FShft(ODFBPWR_MODE)) +#define ODFBPWR_MODE_SLEEP ((0x2) << FShft(ODFBPWR_MODE)) +#define ODFBPWR_MODE_SHUTD ((0x3) << FShft(ODFBPWR_MODE)) + +/* On-Die Frame Buffer Power State Status Register */ +#define ODFBSTAT_ACT (1 << 2) +#define ODFBSTAT_SLP (1 << 1) +#define ODFBSTAT_SDN (1 << 0) + +/* /\* GPIO Registers (0x03FE_006C 0x03FE_007F) *\/ */ +/* #define GPIOCGF __REG_2700G(0x03FE006C) */ +/* #define GPIOHI __REG_2700G(0x03FE0070) */ +/* #define GPIOLO __REG_2700G(0x03FE0074) */ +/* #define GPIOSTAT __REG_2700G(0x03FE0078) */ + +/* /\* Pulse Width Modulator (PWM) Registers (0x03FE_0200 0x03FE_02FF) *\/ */ +/* #define PWMRST __REG_2700G(0x03FE0200) */ +/* #define PWMCFG __REG_2700G(0x03FE0204) */ +/* #define PWM0DIV __REG_2700G(0x03FE0210) */ +/* #define PWM0DUTY __REG_2700G(0x03FE0214) */ +/* #define PWM0PER __REG_2700G(0x03FE0218) */ +/* #define PWM1DIV __REG_2700G(0x03FE0220) */ +/* #define PWM1DUTY __REG_2700G(0x03FE0224) */ +/* #define PWM1PER __REG_2700G(0x03FE0228) */ + + +/* LMRST - Local Memory (SDRAM) Reset */ +#define LMRST_MC_RST (1 << 0) + +/* LMCFG - Local Memory (SDRAM) Configuration Register */ +#define LMCFG_LMC_DS (1 << 5) +#define LMCFG_LMD_DS (1 << 4) +#define LMCFG_LMA_DS (1 << 3) +#define LMCFG_LMC_TS (1 << 2) +#define LMCFG_LMD_TS (1 << 1) +#define LMCFG_LMA_TS (1 << 0) + +/* LMPWR - Local Memory (SDRAM) Power Control Register */ +#define LMPWR_MC_PWR_CNT Fld(2,0) +#define LMPWR_MC_PWR_ACT ((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */ +#define LMPWR_MC_PWR_SRM ((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */ +#define LMPWR_MC_PWR_DPD ((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */ + +/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */ +#define LMPWRSTAT_MC_PWR_CNT Fld(2,0) +#define LMPWRSTAT_MC_PWR_ACT ((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */ +#define LMPWRSTAT_MC_PWR_SRM ((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */ +#define LMPWRSTAT_MC_PWR_DPD ((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */ + +/* LMTYPE - Local Memory (SDRAM) Type Register */ +#define LMTYPE_CASLAT Fld(3,10) +#define LMTYPE_CASLAT_1 ((0x1) << FShft(LMTYPE_CASLAT)) +#define LMTYPE_CASLAT_2 ((0x2) << FShft(LMTYPE_CASLAT)) +#define LMTYPE_CASLAT_3 ((0x3) << FShft(LMTYPE_CASLAT)) +#define LMTYPE_BKSZ Fld(2,8) +#define LMTYPE_BKSZ_1 ((0x1) << FShft(LMTYPE_BKSZ)) +#define LMTYPE_BKSZ_2 ((0x2) << FShft(LMTYPE_BKSZ)) +#define LMTYPE_ROWSZ Fld(4,4) +#define LMTYPE_ROWSZ_11 ((0xb) << FShft(LMTYPE_ROWSZ)) +#define LMTYPE_ROWSZ_12 ((0xc) << FShft(LMTYPE_ROWSZ)) +#define LMTYPE_ROWSZ_13 ((0xd) << FShft(LMTYPE_ROWSZ)) +#define LMTYPE_COLSZ Fld(4,0) +#define LMTYPE_COLSZ_7 ((0x7) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_8 ((0x8) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_9 ((0x9) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_10 ((0xa) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_11 ((0xb) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_12 ((0xc) << FShft(LMTYPE_COLSZ)) + +/* LMTIM - Local Memory (SDRAM) Timing Register */ +#define LMTIM_TRAS Fld(4,16) +#define Lmtim_Tras(x) ((x) << FShft(LMTIM_TRAS)) +#define LMTIM_TRP Fld(4,12) +#define Lmtim_Trp(x) ((x) << FShft(LMTIM_TRP)) +#define LMTIM_TRCD Fld(4,8) +#define Lmtim_Trcd(x) ((x) << FShft(LMTIM_TRCD)) +#define LMTIM_TRC Fld(4,4) +#define Lmtim_Trc(x) ((x) << FShft(LMTIM_TRC)) +#define LMTIM_TDPL Fld(4,0) +#define Lmtim_Tdpl(x) ((x) << FShft(LMTIM_TDPL)) + +/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */ +#define LMREFRESH_TREF Fld(2,0) +#define Lmrefresh_Tref(x) ((x) << FShft(LMREFRESH_TREF)) + +/* #define LMCEMR __REG_2700G(0x03FE1010) */ +/* #define LMPROTMIN __REG_2700G(0x03FE1020) */ +/* #define LMPROTMAX __REG_2700G(0x03FE1024) */ +/* #define LMPROTCFG __REG_2700G(0x03FE1028) */ +/* #define LMPROTERR __REG_2700G(0x03FE102C) */ + +/* GSCTRL - Graphics surface control register */ +#define GSCTRL_LUT_EN (1 << 31) +#define GSCTRL_GPIXFMT Fld(4,27) +#define GSCTRL_GPIXFMT_INDEXED ((0x0) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_ARGB4444 ((0x4) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_ARGB1555 ((0x5) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_RGB888 ((0x6) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_RGB565 ((0x7) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_ARGB8888 ((0x8) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GAMMA_EN (1 << 26) + +#define GSCTRL_GSWIDTH Fld(11,11) +#define Gsctrl_Width(Pixel) /* Display Width [1..2048 pix.] */ \ + (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH)) + +#define GSCTRL_GSHEIGHT Fld(11,0) +#define Gsctrl_Height(Pixel) /* Display Height [1..2048 pix.] */ \ + (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT)) + +/* GBBASE fileds */ +#define GBBASE_GLALPHA Fld(8,24) +#define Gbbase_Glalpha(x) ((x) << FShft(GBBASE_GLALPHA)) + +#define GBBASE_COLKEY Fld(24,0) +#define Gbbase_Colkey(x) ((x) << FShft(GBBASE_COLKEY)) + +/* GDRCTRL fields */ +#define GDRCTRL_PIXDBL (1 << 31) +#define GDRCTRL_PIXHLV (1 << 30) +#define GDRCTRL_LNDBL (1 << 29) +#define GDRCTRL_LNHLV (1 << 28) +#define GDRCTRL_COLKEYM Fld(24,0) +#define Gdrctrl_Colkeym(x) ((x) << FShft(GDRCTRL_COLKEYM)) + +/* GSCADR graphics stream control address register fields */ +#define GSCADR_STR_EN (1 << 31) +#define GSCADR_COLKEY_EN (1 << 30) +#define GSCADR_COLKEYSCR (1 << 29) +#define GSCADR_BLEND_M Fld(2,27) +#define GSCADR_BLEND_NONE ((0x0) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_INV ((0x1) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_GLOB ((0x2) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_PIX ((0x3) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_POS Fld(2,24) +#define GSCADR_BLEND_GFX ((0x0) << FShft(GSCADR_BLEND_POS)) +#define GSCADR_BLEND_VID ((0x1) << FShft(GSCADR_BLEND_POS)) +#define GSCADR_BLEND_CUR ((0x2) << FShft(GSCADR_BLEND_POS)) +#define GSCADR_GBASE_ADR Fld(23,0) +#define Gscadr_Gbase_Adr(x) ((x) << FShft(GSCADR_GBASE_ADR)) + +/* GSADR graphics stride address register fields */ +#define GSADR_SRCSTRIDE Fld(10,22) +#define Gsadr_Srcstride(x) ((x) << FShft(GSADR_SRCSTRIDE)) +#define GSADR_XSTART Fld(11,11) +#define Gsadr_Xstart(x) ((x) << FShft(GSADR_XSTART)) +#define GSADR_YSTART Fld(11,0) +#define Gsadr_Ystart(y) ((y) << FShft(GSADR_YSTART)) + +/* GPLUT graphics palette register fields */ +#define GPLUT_LUTADR Fld(8,24) +#define Gplut_Lutadr(x) ((x) << FShft(GPLUT_LUTADR)) +#define GPLUT_LUTDATA Fld(24,0) +#define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) + +/* #define VSCTRL __REG_2700G(0x03FE2004) */ +/* #define VBBASE __REG_2700G(0x03FE2024) */ +/* #define VCMSK __REG_2700G(0x03FE2044) */ +/* #define VSCADR __REG_2700G(0x03FE2064) */ +/* #define VUBASE __REG_2700G(0x03FE2084) */ +/* #define VVBASE __REG_2700G(0x03FE20A4) */ +/* #define VSADR __REG_2700G(0x03FE20C4) */ + + +/* HCCTRL - Hardware Cursor Register fields */ +#define HCCTRL_CUR_EN (1 << 31) +#define HCCTRL_COLKEY_EN (1 << 29) +#define HCCTRL_COLKEYSRC (1 << 28) +#define HCCTRL_BLEND_M Fld(2,26) +#define HCCTRL_BLEND_NONE ((0x0) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_BLEND_INV ((0x1) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_BLEND_GLOB ((0x2) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_BLEND_PIX ((0x3) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_CPIXFMT Fld(3,23) +#define HCCTRL_CPIXFMT_RGB332 ((0x3) << FShft(HCCTRL_CPIXFMT)) +#define HCCTRL_CPIXFMT_ARGB4444 ((0x4) << FShft(HCCTRL_CPIXFMT)) +#define HCCTRL_CPIXFMT_ARGB1555 ((0x5) << FShft(HCCTRL_CPIXFMT)) +#define HCCTRL_CBASE_ADR Fld(23,0) +#define Hcctrl_Cbase_Adr(x) ((x) << FShft(HCCTRL_CBASE_ADR)) + +/* HCSIZE Hardware Cursor Size Register fields */ +#define HCSIZE_BLEND_POS Fld(2,29) +#define HCSIZE_BLEND_GFX ((0x0) << FShft(HCSIZE_BLEND_POS)) +#define HCSIZE_BLEND_VID ((0x1) << FShft(HCSIZE_BLEND_POS)) +#define HCSIZE_BLEND_CUR ((0x2) << FShft(HCSIZE_BLEND_POS)) +#define HCSIZE_CWIDTH Fld(3,16) +#define Hcsize_Cwidth(x) ((x) << FShft(HCSIZE_CWIDTH)) +#define HCSIZE_CHEIGHT Fld(3,0) +#define Hcsize_Cheight(x) ((x) << FShft(HCSIZE_CHEIGHT)) + +/* HCPOS Hardware Cursor Position Register fields */ +#define HCPOS_SWITCHSRC (1 << 30) +#define HCPOS_CURBLINK Fld(6,24) +#define Hcpos_Curblink(x) ((x) << FShft(HCPOS_CURBLINK)) +#define HCPOS_XSTART Fld(12,12) +#define Hcpos_Xstart(x) ((x) << FShft(HCPOS_XSTART)) +#define HCPOS_YSTART Fld(12,0) +#define Hcpos_Ystart(y) ((y) << FShft(HCPOS_YSTART)) + +/* HCBADR Hardware Cursor Blend Address Register */ +#define HCBADR_GLALPHA Fld(8,24) +#define Hcbadr_Glalpha(x) ((x) << FShft(HCBADR_GLALPHA)) +#define HCBADR_COLKEY Fld(24,0) +#define Hcbadr_Colkey(x) ((x) << FShft(HCBADR_COLKEY)) + +/* HCCKMSK - Hardware Cursor Color Key Mask Register */ +#define HCCKMSK_COLKEY_M Fld(24,0) +#define Hcckmsk_Colkey_M(x) ((x) << FShft(HCCKMSK_COLKEY_M)) + +/* DSCTRL - Display sync control register */ +#define DSCTRL_SYNCGEN_EN (1 << 31) +#define DSCTRL_DPL_RST (1 << 29) +#define DSCTRL_PWRDN_M (1 << 28) +#define DSCTRL_UPDSYNCCNT (1 << 26) +#define DSCTRL_UPDINTCNT (1 << 25) +#define DSCTRL_UPDCNT (1 << 24) +#define DSCTRL_UPDWAIT Fld(4,16) +#define Dsctrl_Updwait(x) ((x) << FShft(DSCTRL_UPDWAIT)) +#define DSCTRL_CLKPOL (1 << 11) +#define DSCTRL_CSYNC_EN (1 << 10) +#define DSCTRL_VS_SLAVE (1 << 7) +#define DSCTRL_HS_SLAVE (1 << 6) +#define DSCTRL_BLNK_POL (1 << 5) +#define DSCTRL_BLNK_DIS (1 << 4) +#define DSCTRL_VS_POL (1 << 3) +#define DSCTRL_VS_DIS (1 << 2) +#define DSCTRL_HS_POL (1 << 1) +#define DSCTRL_HS_DIS (1 << 0) + +/* DHT01 - Display horizontal timing register 01 */ +#define DHT01_HBPS Fld(12,16) +#define Dht01_Hbps(x) ((x) << FShft(DHT01_HBPS)) +#define DHT01_HT Fld(12,0) +#define Dht01_Ht(x) ((x) << FShft(DHT01_HT)) + +/* DHT02 - Display horizontal timing register 02 */ +#define DHT02_HAS Fld(12,16) +#define Dht02_Has(x) ((x) << FShft(DHT02_HAS)) +#define DHT02_HLBS Fld(12,0) +#define Dht02_Hlbs(x) ((x) << FShft(DHT02_HLBS)) + +/* DHT03 - Display horizontal timing register 03 */ +#define DHT03_HFPS Fld(12,16) +#define Dht03_Hfps(x) ((x) << FShft(DHT03_HFPS)) +#define DHT03_HRBS Fld(12,0) +#define Dht03_Hrbs(x) ((x) << FShft(DHT03_HRBS)) + +/* DVT01 - Display vertical timing register 01 */ +#define DVT01_VBPS Fld(12,16) +#define Dvt01_Vbps(x) ((x) << FShft(DVT01_VBPS)) +#define DVT01_VT Fld(12,0) +#define Dvt01_Vt(x) ((x) << FShft(DVT01_VT)) + +/* DVT02 - Display vertical timing register 02 */ +#define DVT02_VAS Fld(12,16) +#define Dvt02_Vas(x) ((x) << FShft(DVT02_VAS)) +#define DVT02_VTBS Fld(12,0) +#define Dvt02_Vtbs(x) ((x) << FShft(DVT02_VTBS)) + +/* DVT03 - Display vertical timing register 03 */ +#define DVT03_VFPS Fld(12,16) +#define Dvt03_Vfps(x) ((x) << FShft(DVT03_VFPS)) +#define DVT03_VBBS Fld(12,0) +#define Dvt03_Vbbs(x) ((x) << FShft(DVT03_VBBS)) + +/* DVECTRL - display vertical event control register */ +#define DVECTRL_VEVENT Fld(12,16) +#define Dvectrl_Vevent(x) ((x) << FShft(DVECTRL_VEVENT)) +#define DVECTRL_VFETCH Fld(12,0) +#define Dvectrl_Vfetch(x) ((x) << FShft(DVECTRL_VFETCH)) + +/* DHDET - display horizontal DE timing register */ +#define DHDET_HDES Fld(12,16) +#define Dhdet_Hdes(x) ((x) << FShft(DHDET_HDES)) +#define DHDET_HDEF Fld(12,0) +#define Dhdet_Hdef(x) ((x) << FShft(DHDET_HDEF)) + +/* DVDET - display vertical DE timing register */ +#define DVDET_VDES Fld(12,16) +#define Dvdet_Vdes(x) ((x) << FShft(DVDET_VDES)) +#define DVDET_VDEF Fld(12,0) +#define Dvdet_Vdef(x) ((x) << FShft(DVDET_VDEF)) + +/* DODMSK - display output data mask register */ +#define DODMSK_MASK_LVL (1 << 31) +#define DODMSK_BLNK_LVL (1 << 30) +#define DODMSK_MASK_B Fld(8,16) +#define Dodmsk_Mask_B(x) ((x) << FShft(DODMSK_MASK_B)) +#define DODMSK_MASK_G Fld(8,8) +#define Dodmsk_Mask_G(x) ((x) << FShft(DODMSK_MASK_G)) +#define DODMSK_MASK_R Fld(8,0) +#define Dodmsk_Mask_R(x) ((x) << FShft(DODMSK_MASK_R)) + +/* DBCOL - display border color control register */ +#define DBCOL_BORDCOL Fld(24,0) +#define Dbcol_Bordcol(x) ((x) << FShft(DBCOL_BORDCOL)) + +/* DVLNUM - display vertical line number register */ +#define DVLNUM_VLINE Fld(12,0) +#define Dvlnum_Vline(x) ((x) << FShft(DVLNUM_VLINE)) + +/* DMCTRL - Display Memory Control Register */ +#define DMCTRL_MEM_REF Fld(2,30) +#define DMCTRL_MEM_REF_ACT ((0x0) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_MEM_REF_HB ((0x1) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_MEM_REF_VB ((0x2) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_MEM_REF_BOTH ((0x3) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_UV_THRHLD Fld(6,24) +#define Dmctrl_Uv_Thrhld(x) ((x) << FShft(DMCTRL_UV_THRHLD)) +#define DMCTRL_V_THRHLD Fld(7,16) +#define Dmctrl_V_Thrhld(x) ((x) << FShft(DMCTRL_V_THRHLD)) +#define DMCTRL_D_THRHLD Fld(7,8) +#define Dmctrl_D_Thrhld(x) ((x) << FShft(DMCTRL_D_THRHLD)) +#define DMCTRL_BURSTLEN Fld(6,0) +#define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) + + +/* DLSTS - display load status register */ +#define DLSTS_RLD_ADONE (1 << 23) +/* #define DLSTS_RLD_ADOUT Fld(23,0) */ + +/* DLLCTRL - display list load control register */ +#define DLLCTRL_RLD_ADRLN Fld(8,24) +#define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) + +/* #define DSIG __REG_2700G(0x03FE2184) */ +/* #define DINTRS __REG_2700G(0x03FE2178) */ +/* #define DINTRE __REG_2700G(0x03FE217C) */ +/* #define DINTRCNT __REG_2700G(0x03FE2180) */ +/* #define DUCTRL __REG_2700G(0x03FE230C) */ + +/* BGCOLOR - background color control register */ +/* #define BGCOLOR __REG_2700G(0x03FE2174) */ + +/* #define CLIPCTRL __REG_2700G(0x03FE218C) */ +/* SPOCTRL - Scale Pitch/Order Control Register */ +#define SPOCTRL_H_SC_BP (1 << 31) +#define SPOCTRL_V_SC_BP (1 << 30) +#define SPOCTRL_HV_SC_OR (1 << 29) +#define SPOCTRL_VS_UR_C (1 << 27) +#define SPOCTRL_VORDER Fld(2,16) +#define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) +#define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) +#define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) +#define SPOCTRL_VPITCH Fld(16,0) +#define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) + +/* #define SVCTRL __REG_2700G(0x03FE2194) */ + +/* /\* 0x03FE_2198 *\/ */ +/* /\* 0x03FE_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 *\/ */ + +/* #define SHCTRL __REG_2700G(0x03FE21B0) */ + +/* /\* 0x03FE_21B4 *\/ */ +/* /\* 0x03FE_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 *\/ */ + +/* #define SSSIZE __REG_2700G(0x03FE21D8) */ + +/* /\* 0x03FE_2200 *\/ */ +/* /\* 0x03FE_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 *\/ */ + +/* /\* 0x03FE_2250 *\/ */ +/* /\* 0x03FE_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 *\/ */ + +/* #define CSC01 __REG_2700G(0x03FE2330) */ +/* #define CSC02 __REG_2700G(0x03FE2334) */ +/* #define CSC03 __REG_2700G(0x03FE2338) */ +/* #define CSC04 __REG_2700G(0x03FE233C) */ +/* #define CSC05 __REG_2700G(0x03FE2340) */ + +#endif /* __REG_BITS_2700G_ */ diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h new file mode 100644 index 0000000..edf0f14 --- /dev/null +++ b/drivers/video/mbx/regs.h @@ -0,0 +1,192 @@ +#ifndef __REGS_2700G_ +#define __REGS_2700G_ + +/* extern unsigned long virt_base_2700; */ +#define __REG_2700G(x) (*(volatile unsigned long*)((x)+virt_base_2700)) + +/* System Configuration Registers (0x0000_0000 0x0000_0010) */ +#define SYSCFG __REG_2700G(0x00000000) +#define PFBASE __REG_2700G(0x00000004) +#define PFCEIL __REG_2700G(0x00000008) +#define POLLFLAG __REG_2700G(0x0000000c) +#define SYSRST __REG_2700G(0x00000010) + +/* Interrupt Control Registers (0x0000_0014 0x0000_002F) */ +#define NINTPW __REG_2700G(0x00000014) +#define MINTENABLE __REG_2700G(0x00000018) +#define MINTSTAT __REG_2700G(0x0000001c) +#define SINTENABLE __REG_2700G(0x00000020) +#define SINTSTAT __REG_2700G(0x00000024) +#define SINTCLR __REG_2700G(0x00000028) + +/* Clock Control Registers (0x0000_002C 0x0000_005F) */ +#define SYSCLKSRC __REG_2700G(0x0000002c) +#define PIXCLKSRC __REG_2700G(0x00000030) +#define CLKSLEEP __REG_2700G(0x00000034) +#define COREPLL __REG_2700G(0x00000038) +#define DISPPLL __REG_2700G(0x0000003c) +#define PLLSTAT __REG_2700G(0x00000040) +#define VOVRCLK __REG_2700G(0x00000044) +#define PIXCLK __REG_2700G(0x00000048) +#define MEMCLK __REG_2700G(0x0000004c) +#define M24CLK __REG_2700G(0x00000054) +#define MBXCLK __REG_2700G(0x00000054) +#define SDCLK __REG_2700G(0x00000058) +#define PIXCLKDIV __REG_2700G(0x0000005c) + +/* LCD Port Control Register (0x0000_0060 0x0000_006F) */ +#define LCD_CONFIG __REG_2700G(0x00000060) + +/* On-Die Frame Buffer Registers (0x0000_0064 0x0000_006B) */ +#define ODFBPWR __REG_2700G(0x00000064) +#define ODFBSTAT __REG_2700G(0x00000068) + +/* GPIO Registers (0x0000_006C 0x0000_007F) */ +#define GPIOCGF __REG_2700G(0x0000006c) +#define GPIOHI __REG_2700G(0x00000070) +#define GPIOLO __REG_2700G(0x00000074) +#define GPIOSTAT __REG_2700G(0x00000078) + +/* Pulse Width Modulator (PWM) Registers (0x0000_0200 0x0000_02FF) */ +#define PWMRST __REG_2700G(0x00000200) +#define PWMCFG __REG_2700G(0x00000204) +#define PWM0DIV __REG_2700G(0x00000210) +#define PWM0DUTY __REG_2700G(0x00000214) +#define PWM0PER __REG_2700G(0x00000218) +#define PWM1DIV __REG_2700G(0x00000220) +#define PWM1DUTY __REG_2700G(0x00000224) +#define PWM1PER __REG_2700G(0x00000228) + +/* Identification (ID) Registers (0x0000_0300 0x0000_0FFF) */ +#define ID __REG_2700G(0x00000FF0) + +/* Local Memory (SDRAM) Interface Registers (0x0000_1000 0x0000_1FFF) */ +#define LMRST __REG_2700G(0x00001000) +#define LMCFG __REG_2700G(0x00001004) +#define LMPWR __REG_2700G(0x00001008) +#define LMPWRSTAT __REG_2700G(0x0000100c) +#define LMCEMR __REG_2700G(0x00001010) +#define LMTYPE __REG_2700G(0x00001014) +#define LMTIM __REG_2700G(0x00001018) +#define LMREFRESH __REG_2700G(0x0000101c) +#define LMPROTMIN __REG_2700G(0x00001020) +#define LMPROTMAX __REG_2700G(0x00001024) +#define LMPROTCFG __REG_2700G(0x00001028) +#define LMPROTERR __REG_2700G(0x0000102c) + +/* Plane Controller Registers (0x0000_2000 0x0000_2FFF) */ +#define GSCTRL __REG_2700G(0x00002000) +#define VSCTRL __REG_2700G(0x00002004) +#define GBBASE __REG_2700G(0x00002020) +#define VBBASE __REG_2700G(0x00002024) +#define GDRCTRL __REG_2700G(0x00002040) +#define VCMSK __REG_2700G(0x00002044) +#define GSCADR __REG_2700G(0x00002060) +#define VSCADR __REG_2700G(0x00002064) +#define VUBASE __REG_2700G(0x00002084) +#define VVBASE __REG_2700G(0x000020a4) +#define GSADR __REG_2700G(0x000020c0) +#define VSADR __REG_2700G(0x000020c4) +#define HCCTRL __REG_2700G(0x00002100) +#define HCSIZE __REG_2700G(0x00002110) +#define HCPOS __REG_2700G(0x00002120) +#define HCBADR __REG_2700G(0x00002130) +#define HCCKMSK __REG_2700G(0x00002140) +#define GPLUT __REG_2700G(0x00002150) +#define DSCTRL __REG_2700G(0x00002154) +#define DHT01 __REG_2700G(0x00002158) +#define DHT02 __REG_2700G(0x0000215c) +#define DHT03 __REG_2700G(0x00002160) +#define DVT01 __REG_2700G(0x00002164) +#define DVT02 __REG_2700G(0x00002168) +#define DVT03 __REG_2700G(0x0000216c) +#define DBCOL __REG_2700G(0x00002170) +#define BGCOLOR __REG_2700G(0x00002174) +#define DINTRS __REG_2700G(0x00002178) +#define DINTRE __REG_2700G(0x0000217c) +#define DINTRCNT __REG_2700G(0x00002180) +#define DSIG __REG_2700G(0x00002184) +#define DMCTRL __REG_2700G(0x00002188) +#define CLIPCTRL __REG_2700G(0x0000218c) +#define SPOCTRL __REG_2700G(0x00002190) +#define SVCTRL __REG_2700G(0x00002194) + +/* 0x0000_2198 */ +/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */ +#define VSCOEFF0 __REG_2700G(0x00002198) +#define VSCOEFF1 __REG_2700G(0x0000219c) +#define VSCOEFF2 __REG_2700G(0x000021a0) +#define VSCOEFF3 __REG_2700G(0x000021a4) +#define VSCOEFF4 __REG_2700G(0x000021a8) + +#define SHCTRL __REG_2700G(0x000021b0) + +/* 0x0000_21B4 */ +/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */ +#define HSCOEFF0 __REG_2700G(0x000021b4) +#define HSCOEFF1 __REG_2700G(0x000021b8) +#define HSCOEFF2 __REG_2700G(0x000021bc) +#define HSCOEFF3 __REG_2700G(0x000021b0) +#define HSCOEFF4 __REG_2700G(0x000021c4) +#define HSCOEFF5 __REG_2700G(0x000021c8) +#define HSCOEFF6 __REG_2700G(0x000021cc) +#define HSCOEFF7 __REG_2700G(0x000021d0) +#define HSCOEFF8 __REG_2700G(0x000021d4) + +#define SSSIZE __REG_2700G(0x000021D8) + +/* 0x0000_2200 */ +/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */ +#define VIDGAM0 __REG_2700G(0x00002200) +#define VIDGAM1 __REG_2700G(0x00002204) +#define VIDGAM2 __REG_2700G(0x00002208) +#define VIDGAM3 __REG_2700G(0x0000220c) +#define VIDGAM4 __REG_2700G(0x00002210) +#define VIDGAM5 __REG_2700G(0x00002214) +#define VIDGAM6 __REG_2700G(0x00002218) +#define VIDGAM7 __REG_2700G(0x0000221c) +#define VIDGAM8 __REG_2700G(0x00002220) +#define VIDGAM9 __REG_2700G(0x00002224) +#define VIDGAM10 __REG_2700G(0x00002228) +#define VIDGAM11 __REG_2700G(0x0000222c) +#define VIDGAM12 __REG_2700G(0x00002230) +#define VIDGAM13 __REG_2700G(0x00002234) +#define VIDGAM14 __REG_2700G(0x00002238) +#define VIDGAM15 __REG_2700G(0x0000223c) +#define VIDGAM16 __REG_2700G(0x00002240) + +/* 0x0000_2250 */ +/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */ +#define GFXGAM0 __REG_2700G(0x00002250) +#define GFXGAM1 __REG_2700G(0x00002254) +#define GFXGAM2 __REG_2700G(0x00002258) +#define GFXGAM3 __REG_2700G(0x0000225c) +#define GFXGAM4 __REG_2700G(0x00002260) +#define GFXGAM5 __REG_2700G(0x00002264) +#define GFXGAM6 __REG_2700G(0x00002268) +#define GFXGAM7 __REG_2700G(0x0000226c) +#define GFXGAM8 __REG_2700G(0x00002270) +#define GFXGAM9 __REG_2700G(0x00002274) +#define GFXGAM10 __REG_2700G(0x00002278) +#define GFXGAM11 __REG_2700G(0x0000227c) +#define GFXGAM12 __REG_2700G(0x00002280) +#define GFXGAM13 __REG_2700G(0x00002284) +#define GFXGAM14 __REG_2700G(0x00002288) +#define GFXGAM15 __REG_2700G(0x0000228c) +#define GFXGAM16 __REG_2700G(0x00002290) + +#define DLSTS __REG_2700G(0x00002300) +#define DLLCTRL __REG_2700G(0x00002304) +#define DVLNUM __REG_2700G(0x00002308) +#define DUCTRL __REG_2700G(0x0000230c) +#define DVECTRL __REG_2700G(0x00002310) +#define DHDET __REG_2700G(0x00002314) +#define DVDET __REG_2700G(0x00002318) +#define DODMSK __REG_2700G(0x0000231c) +#define CSC01 __REG_2700G(0x00002330) +#define CSC02 __REG_2700G(0x00002334) +#define CSC03 __REG_2700G(0x00002338) +#define CSC04 __REG_2700G(0x0000233c) +#define CSC05 __REG_2700G(0x00002340) + +#endif /* __REGS_2700G_ */ diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 53ad61f..76675f6 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -48,6 +48,11 @@ #include #include #include +#ifdef CONFIG_PXA27x +#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 3 */ +#endif + + /* * Complain if VAR is out of range. */ @@ -113,9 +118,15 @@ pxafb_setpalettereg(u_int regno, u_int r if (fbi->fb.var.grayscale) { val = ((blue >> 8) & 0x00ff); } else { +#ifdef CONFIG_ARMCORE_REV11 + val = (((red & 0xff) << 16) & 0xfc0000); + val |= (((green & 0xff) << 8) & 0xfc00); + val |= (((blue & 0xff) << 0) & 0x00fc); +#else val = ((red >> 0) & 0xf800); val |= ((green >> 5) & 0x07e0); val |= ((blue >> 11) & 0x001f); +#endif } fbi->palette_cpu[regno] = val; ret = 0; @@ -426,6 +437,8 @@ static struct fb_ops pxafb_ops = { * We take account of the PPCR clock setting. * From PXA Developer's Manual: * + * If PCDDIV = 0 then: + * * PixelClock = LCLK * ------------- * 2 ( PCD + 1 ) @@ -434,6 +447,17 @@ static struct fb_ops pxafb_ops = { * ------------- - 1 * 2(PixelClock) * + * + * If PCDDIV = 1 then: + * + * PixelClock = LCLK + * ------------- + * ( PCD + 1 ) + * + * PCD = LCLK + * ------------- - 1 + * PixelClock + * * Where: * LCLK = LCD/Memory Clock * PCD = LCCR3[7:0] @@ -448,22 +472,64 @@ static struct fb_ops pxafb_ops = { * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 ) * -------------------------------------- - 1 * 2 + * or + * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 ) - 1 * * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below. */ -static inline unsigned int get_pcd(unsigned int pixclock) +static inline unsigned int get_pcd(unsigned int pixclock, unsigned int *lccr4) { - unsigned long long pcd; + /* pcd1 is for PCDDIV=0 and pcd2 for PCDDIV=1 */ + unsigned long long pcd1, pcd2; + unsigned long long clk1, clk2; + unsigned long long dif1, dif2; + + *lccr4 = LCCR4; /* FIXME: Need to take into account Double Pixel Clock mode * (DPC) bit? or perhaps set it based on the various clock * speeds */ - pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; - do_div(pcd, 100000000 * 2); + pcd1 = pcd2 = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; + do_div(pcd1, 100000000 * 2); /* pcd1 /= 100000000 * 2; */ + do_div(pcd2, 100000000); /* pcd2 /= 100000000; */ + +/* clk1 = 100000000*(2 * (pcd1 + 1))/get_lcdclk_frequency_10khz(); */ +/* clk2 = 100000000*(pcd2 + 1)/get_lcdclk_frequency_10khz(); */ + + clk1 = 100000000*(2 * (pcd1 + 1)); + clk2 = 100000000*(pcd2 + 1); + do_div(clk1, get_lcdclk_frequency_10khz()); + do_div(clk2, get_lcdclk_frequency_10khz()); + + pr_debug("get_pcd: pcd1 = %lld, dotclock = %lld\n", pcd1, clk1); + pr_debug("get_pcd: pcd2 = %lld, dotclock = %lld\n", pcd2, clk2); + + dif1 = pixclock - clk1; + if ( clk1 > pixclock ) + dif1 *= -1; + + dif2 = pixclock - clk2; + if ( clk2 > pixclock ) + dif2 *= -1; + + if ( dif1 > dif2 ) { + *lccr4 |= (1 << 31); + pr_debug(KERN_INFO "get_pcd: setting pixclock to high rate\n"); + return (unsigned int)pcd2; + } + else { + *lccr4 &= ~(1 << 31); + pr_debug(KERN_INFO "get_pcd: setting pixclock to low rate\n"); + return (unsigned int)pcd1; + } + /* no need for this, since we should subtract 1 anyway. they cancel */ /* pcd += 1; */ /* make up for integer math truncations */ - return (unsigned int)pcd; +/* return (unsigned int)pcd2; */ + + /* never get here */ + return (unsigned int)0; } /* @@ -505,7 +571,9 @@ static int pxafb_activate_var(struct fb_ { struct pxafb_lcd_reg new_regs; u_long flags; - u_int lines_per_panel, pcd = get_pcd(var->pixclock); + u_int lines_per_panel; + u_int lccr4; + u_int pcd = get_pcd(var->pixclock, &lccr4); pr_debug("pxafb: Configuring PXA LCD\n"); @@ -735,10 +803,18 @@ static void pxafb_setup_gpio(struct pxaf pxa_gpio_mode(GPIO75_LCD_LCLK_MD); pxa_gpio_mode(GPIO76_LCD_PCLK_MD); pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); + +#ifdef CONFIG_ARMCORE_REV11 + pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT); + pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT); +#endif } static void pxafb_enable_controller(struct pxafb_info *fbi) { + unsigned int lccr4; + unsigned int pcd = get_pcd(fbi->fb.var.pixclock, &lccr4); + pr_debug("pxafb: Enabling LCD controller\n"); pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); @@ -751,7 +827,20 @@ static void pxafb_enable_controller(stru pxa_set_cken(CKEN16_LCD, 1); /* Sequence from 11.7.10 */ - LCCR3 = fbi->reg_lccr3; +#ifdef CONFIG_ARMCORE_REV12 + LCCR4 = lccr4; +#else + LCCR4 = 0 | (2 << 15) | lccr4; +#endif + + fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); + +#ifdef CONFIG_ARMCORE_REV12 + LCCR3 = (fbi->reg_lccr3);//& (~(7 << 24))) | (3 << 24); +#else + LCCR3 = (fbi->reg_lccr3 | (3 << 30)) ;//& (~(7 << 24))) | (3 << 24); +#endif + LCCR2 = fbi->reg_lccr2; LCCR1 = fbi->reg_lccr1; LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB; @@ -1083,6 +1172,7 @@ static struct pxafb_info * __init pxafb_ addr = addr + sizeof(struct pxafb_info); fbi->fb.pseudo_palette = addr; + fbi->fb.var.pixclock = inf->pixclock; fbi->max_xres = inf->xres; fbi->fb.var.xres = inf->xres; fbi->fb.var.xres_virtual = inf->xres; diff --git a/include/asm-arm/arch-pxa/cm-x270.h b/include/asm-arm/arch-pxa/cm-x270.h new file mode 100644 index 0000000..7099ae7 --- /dev/null +++ b/include/asm-arm/arch-pxa/cm-x270.h @@ -0,0 +1,72 @@ +/* + * linux/include/asm/arch-pxa/armcore.h + * + * Compulab Ltd., 2003 + * + * ARMCore registers + */ + +#include + +#define CMX270_CS1_PHYS (PXA_CS1_PHYS) +#define MARATHON_PHYS (PXA_CS2_PHYS) +#define CMX270_IDE104_PHYS (PXA_CS3_PHYS) +#define CMX270_IT8152_PHYS (PXA_CS4_PHYS) + +#define PXA_CS_SIZE (64*1024*1024) + +/* Virtual map */ + +#define CMX270_VIRT_BASE (0xe8000000) + +#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE) +#define CMX270_IDE104_VIRT (CMX270_IT8152_VIRT + PXA_CS_SIZE) + + +/* GPIO related definitions */ +#define GPIO_IT8152_IRQ (22) +#define GPIO_RED_LED (93) +#define GPIO_GREEN_LED (94) + + +#define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ) +#define PME_IRQ IRQ_GPIO(0) +#define CMX270_IDE_IRQ IRQ_GPIO(100) +#define CMX270_GPIRQ1 IRQ_GPIO(101) +#define CMX270_TOUCHIRQ IRQ_GPIO(96) +#define CMX270_ETHIRQ IRQ_GPIO(10) +#define CMX270_GFXIRQ IRQ_GPIO(95) +#define CMX270_NANDIRQ IRQ_GPIO(89) +#define CMX270_MMC_IRQ IRQ_GPIO(83) + +/* LED macros */ +#define CMX270_RED_ON() GPCR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED) +#define CMX270_RED_OFF() GPSR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED) +#define CMX270_GREEN_ON() GPCR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED) +#define CMX270_GREEN_OFF() GPSR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED) + +/* PCMCIA related definitions */ +#define PCC_DETECT(x) (GPLR(84 - (x)) & GPIO_bit(84 - (x))) +#define PCC_READY(x) (GPLR(82 - (x)) & GPIO_bit(81 - (x))) + +#define PCMCIA_S0_CD_VALID IRQ_GPIO(84) +#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES + +#define PCMCIA_S1_CD_VALID IRQ_GPIO(83) +#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES + +#define PCMCIA_S0_RDYINT IRQ_GPIO(82) +#define PCMCIA_S1_RDYINT IRQ_GPIO(81) + +#define PCMCIA_RESET_GPIO 53 + + + + + + + + + + + diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index 3e70bd9..cb4fb2f 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -80,4 +80,15 @@ extern unsigned int get_lcdclk_frequency #endif +#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) +#define HAVE_ARCH_PCI_SET_DMA_MASK +#ifndef __ASSEMBLY__ +extern unsigned long armcore_pcibios_min_io; +extern unsigned long armcore_pcibios_min_mem; +#endif +#define PCIBIOS_MIN_IO (armcore_pcibios_min_io) +#define PCIBIOS_MIN_MEM (armcore_pcibios_min_mem) +#define pcibios_assign_all_busses() 1 +#endif + #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index 05c4b70..f0259cd 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -176,7 +176,8 @@ #define NR_IRQS (IRQ_S1_BVD1_STSCHG + #elif defined(CONFIG_SHARP_LOCOMO) #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) #elif defined(CONFIG_ARCH_LUBBOCK) || \ - defined(CONFIG_MACH_MAINSTONE) + defined(CONFIG_MACH_MAINSTONE) || \ + defined(CONFIG_MACH_ARMCORE) #define NR_IRQS (IRQ_BOARD_END) #else #define NR_IRQS (IRQ_BOARD_START) @@ -217,3 +218,24 @@ #define IRQ_LOCOMO_KEY_BASE (IRQ_BOARD_S #define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1) #define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2) #define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3) + +/* ITE8152 irqs on CM-x2xx */ +#ifdef CONFIG_MACH_ARMCORE +#define IT8152_IRQ(x) (IRQ_BOARD_START + (x)) +#define PCISERR IT8152_IRQ(0) +#define H2PTADR IT8152_IRQ(1) +#define H2PMAR IT8152_IRQ(2) +#define PCI_INTA IT8152_IRQ(3) +#define PCI_INTB IT8152_IRQ(4) +#define PCI_INTC IT8152_IRQ(5) +#define PCI_INTD IT8152_IRQ(6) +#define USB_INT IT8152_IRQ(7) +#define AUDIO_INT IT8152_IRQ(8) +#define CDMA_INT IT8152_IRQ(9) +#define IRQ_ITESER IT8152_IRQ(10) +#define IT8152_IRQ_MAX IT8152_IRQ(10) + + +#undef NR_IRQS +#define NR_IRQS IT8152_IRQ_MAX+1 +#endif diff --git a/include/asm-arm/arch-pxa/marathonfb.h b/include/asm-arm/arch-pxa/marathonfb.h new file mode 100644 index 0000000..97b69ef --- /dev/null +++ b/include/asm-arm/arch-pxa/marathonfb.h @@ -0,0 +1,28 @@ +#ifndef __MARATHON_FB_H +#define __MARATHON_FB_H + +struct mbxfb_val { + unsigned int defval; + unsigned int min; + unsigned int max; +}; + +struct fb_info; + +struct mbxfb_platform_data { + /* Screen info */ + struct mbxfb_val xres; + struct mbxfb_val yres; + struct mbxfb_val bpp; + + /* Memory info */ + unsigned long memsize; /* if 0 use ODFB? */ + unsigned long timings1; + unsigned long timings2; + unsigned long timings3; + + int (*probe)(struct fb_info *fb); + int (*remove)(struct fb_info *fb); +}; + +#endif /* __MARATHON_FB_H */ diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h index eaf6d43..98807e7 100644 --- a/include/asm-arm/arch-pxa/memory.h +++ b/include/asm-arm/arch-pxa/memory.h @@ -17,6 +17,19 @@ #define __ASM_ARCH_MEMORY_H */ #define PHYS_OFFSET UL(0xa0000000) + +#ifdef CONFIG_PCI_HOST_ITE8152 +#ifndef __ASSEMBLY__ +void it8152_adjust_zones(int node, unsigned long *size, unsigned long *holes); + +#define arch_adjust_zones(node, size, holes) \ + it8152_adjust_zones(node, size, holes) + +#define ISA_DMA_THRESHOLD (SZ_64M - 1) +#endif +#endif + + /* * Virtual view <-> DMA view memory address translations * virt_to_bus: Used to translate the virtual address to an diff --git a/include/asm-arm/arch-pxa/pxafbsetup.h b/include/asm-arm/arch-pxa/pxafbsetup.h new file mode 100644 index 0000000..8a7c8de --- /dev/null +++ b/include/asm-arm/arch-pxa/pxafbsetup.h @@ -0,0 +1,39 @@ +/* + Panel specific LCD controller setup + */ + +#ifndef _PXAFBSETUP_H +#define _PXAFBSETUP_H + +#define MTYPE_STN320x240 0 +#define MTYPE_TFT640x480 1 +#define MTYPE_CRT640x480 2 +#define MTYPE_CRT800x600 3 +#define MTYPE_CRT1024x768 4 +#define MTYPE_USER_DEFINED 5 +#define MTYPE_TFT320x240 6 +#define MTYPE_STN640x480 7 + +#define CMAP_GREYSCALE 0 +#define CMAP_INVERSE 0 +#define CMAP_STATIC 0 + + +// Example for user defined display +// Hitach SX19V-009 +#define LCD_PIXCLOCK 38461 +#define LCD_BPP 8 +#define LCD_XRES 640 +#define LCD_YRES 480 +#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 4 +#define LCD_VERTICAL_SYNC_PULSE_WIDTH 2 +#define LCD_BEGIN_OF_LINE_WAIT_COUNT 10 +#define LCD_BEGIN_FRAME_WAIT_COUNT 5 +#define LCD_END_OF_LINE_WAIT_COUNT 10 +#define LCD_END_OF_FRAME_WAIT_COUNT 5 +#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT) +#define LCD_LCCR0 (LCCR0_LDM | LCCR0_IUM | LCCR0_QDM | LCCR0_BM | LCCR0_OUM ) +#define LCD_LCCR3 (LCCR3_PixClkDiv(0x02) | LCCR3_Acb(0xff)) +#define LCD_NAME "Hitachi SX19V-009-ZZA-1" + +#endif diff --git a/include/asm-arm/hardware/it8152.h b/include/asm-arm/hardware/it8152.h new file mode 100644 index 0000000..d28210d --- /dev/null +++ b/include/asm-arm/hardware/it8152.h @@ -0,0 +1,104 @@ +/* + * arch/arm/mach-pxa/it8152.h + * + * Compulab Ltd., 2006 + * + * ITE 8152 companion chip definitions + */ + + +/* #define CMX270_IT8152_VIRT (CMX270_VIRT_BASE) */ + + +extern unsigned long it8152_base_address; + +#define IT8152_IO_BASE (it8152_base_address + 0x03e00000) +#define IT8152_CFGREG_BASE (it8152_base_address + 0x03f00000) + +/* #define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ) */ + +#define IT8152_SHORT_IO(x) (*((volatile unsigned short *)(IT8152_CFGREG_BASE+(x)))) +#define IT8152_LONG_IO(x) (*((volatile unsigned long *)(IT8152_CFGREG_BASE+(x)))) + + +#define IT8152_PCI_MEMBASE (*((volatile unsigned long *)(it8152_base_address))) +/* #define IT8152_PCI_IOBASE (*((volatile unsigned long *)(it8152_base_address + 0x3e00000))) */ + +#define IT8152_PCI_IACK (*((volatile unsigned long *)(it8152_base_address + 0x3f00808))) +#define IT8152_PCI_CFG_ADDR (*((volatile unsigned long *)(it8152_base_address + 0x3f00800))) +#define IT8152_PCI_CFG_DATA (*((volatile unsigned long *)(it8152_base_address + 0x3f00804))) + +#define IT_BUSNUM_SHF 16 +#define IT_DEVNUM_SHF 11 +#define IT_FUNCNUM_SHF 8 +#define IT_REGNUM_SHF 2 + +/* Power management & PLL registers */ +#define IT8152_PMPLL_DSR IT8152_LONG_IO(0x00) +#define IT8152_PMPLL_DSSR IT8152_LONG_IO(0x04) +#define IT8152_PMPLL_PLLCR IT8152_LONG_IO(0x20) +#define IT8152_PMPLL_MFSR IT8152_LONG_IO(0x24) + +/* Memory controller */ +#define IT8152_MC_REG_OFFSET 0x100 + +#define IT8152_MC_SDCR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x00) +#define IT8152_MC_PCICR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x04) + +/* Interrupt related definitions */ +#define IT8152_INTC_REG_OFFSET 0x300 + +#define IT8152_INTC_LDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x00) +#define IT8152_INTC_LDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x04) +#define IT8152_INTC_LDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x08) +#define IT8152_INTC_LDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x0C) +#define IT8152_INTC_LDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x10) +#define IT8152_INTC_LDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x14) +#define IT8152_INTC_LPCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x20) +#define IT8152_INTC_LPPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x24) +#define IT8152_INTC_LPCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x28) +#define IT8152_INTC_LPPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x2C) +#define IT8152_INTC_LPNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x30) +#define IT8152_INTC_LPNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x34) +#define IT8152_INTC_PDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x40) +#define IT8152_INTC_PDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x44) +#define IT8152_INTC_PDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x48) +#define IT8152_INTC_PDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x4C) +#define IT8152_INTC_PDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x50) +#define IT8152_INTC_PDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x54) +#define IT8152_INTC_INTC_TYPER IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0xFC) + +#define IT8152_UART_BASE IT8152_LONG_IO(0x200) + +#define IT8152_GPIO_REG_OFFSET 0x500 + +#define IT8152_GPIO_GPLR IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET) +#define IT8152_GPIO_GPCR12 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x04) +#define IT8152_GPIO_GPCR34 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x08) + + +/* Interrupt bit definitions */ +#define PCISERR_BIT (1<<14) +#define H2PTADR_BIT (1<<13) +#define H2PMAR_BIT (1<<12) +#define PCI_INTD_BIT (1<<11) +#define PCI_INTC_BIT (1<<10) +#define PCI_INTB_BIT (1<<9) +#define PCI_INTA_BIT (1<<8) +#define CDMA_INT_BIT (1<<2) +#define USB_INT_BIT (1<<1) +#define AUDIO_INT_BIT (1<<0) + +/* IT8152 UART */ +#define ITESER_BIT (1<<5) + + + + + + + + + + + diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 751eea5..bc45d11 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1568,6 +1568,7 @@ #define PCI_DEVICE_ID_EFFICEON 0x0060 #define PCI_VENDOR_ID_ROCKWELL 0x127A #define PCI_VENDOR_ID_ITE 0x1283 +#define PCI_DEVICE_ID_ITE_IT8152 0x8152 #define PCI_DEVICE_ID_ITE_IT8172G 0x8172 #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801 #define PCI_DEVICE_ID_ITE_8211 0x8211 diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 3020ca2..ba1dc8a 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -150,7 +150,7 @@ static const struct ac97_codec_id snd_ac { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, { 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, -{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, +{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index a444a78..0bb1d71 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -2823,3 +2823,33 @@ int mpatch_si3036(struct snd_ac97 * ac97 snd_ac97_write_cache(ac97, 0x68, 0); return 0; } + +/* + * UCB1400 codec + */ +static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = { +AC97_SINGLE("Headphone driver", 0x6a, 6, 1, 0), +AC97_SINGLE("DC filter", 0x6a, 4, 1, 0), +AC97_SINGLE("Smart power mode", 0x6c, 4, 3, 0), +}; + +static int patch_ucb1400_specific(struct snd_ac97 * ac97) +{ + int idx, err; + for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) + if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) + return err; + return 0; +} + +static struct snd_ac97_build_ops patch_ucb1400_ops = { + .build_specific = patch_ucb1400_specific, +}; + +int patch_ucb1400(struct snd_ac97 * ac97) +{ + ac97->build_ops = &patch_ucb1400_ops; + snd_ac97_write(ac97, 0x6a, 0x0050); + snd_ac97_write(ac97, 0x6c, 0x0030); + return 0; +} diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index 5060cb6..068b674 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h @@ -58,4 +58,5 @@ int patch_cm9780(struct snd_ac97 * ac97) int patch_vt1616(struct snd_ac97 * ac97); int patch_vt1617a(struct snd_ac97 * ac97); int patch_it2646(struct snd_ac97 * ac97); +int patch_ucb1400(struct snd_ac97 * ac97); int mpatch_si3036(struct snd_ac97 * ac97);