Tried to post earlier and did not get through, can send patch file separately if mail server wont accept it. Daniel Laird ------------------------------------------------------ The following patch add support for the NXP PNX833x SOC. More specifically it adds support for the STB222/5 variant. This has I2C support, NAND and onboard ethernet support. SATA, USB, NOR flash, WATCHDOG are all pending patches after I get this in :-). arch/mips/Kconfig | 33 arch/mips/Makefile | 8 arch/mips/configs/pnx8335-stb225_defconfig | 1150 +++++++++++++++++++++ arch/mips/nxp/pnx833x/common/Makefile | 1 arch/mips/nxp/pnx833x/common/gdb_hook.c | 162 +++ arch/mips/nxp/pnx833x/common/interrupts.c | 363 ++++++ arch/mips/nxp/pnx833x/common/platform.c | 337 ++++++ arch/mips/nxp/pnx833x/common/prom.c | 69 + arch/mips/nxp/pnx833x/common/reset.c | 48 arch/mips/nxp/pnx833x/common/setup.c | 63 + arch/mips/nxp/pnx833x/stb22x/Makefile | 1 arch/mips/nxp/pnx833x/stb22x/board.c | 138 ++ drivers/i2c/busses/Kconfig | 12 drivers/i2c/busses/Makefile | 1 drivers/i2c/busses/i2c-pnx0105.c | 328 ++++++ drivers/net/Kconfig | 9 drivers/net/Makefile | 1 drivers/net/ip3902.c | 1534 +++++++++++++++++++++++++++++ include/asm-mips/mach-pnx833x/gpio.h | 171 +++ include/asm-mips/mach-pnx833x/irq.h | 138 ++ include/asm-mips/mach-pnx833x/pnx833x.h | 194 +++ include/asm-mips/mach-pnx833x/war.h | 25 include/linux/i2c-id.h | 1 include/linux/i2c-pnx0105.h | 58 + 24 files changed, 4845 insertions(+) Signed-off-by: daniel.j.laird <daniel.j.laird@xxxxxxx> diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/configs/pnx8335-stb225_defconfig linux-2.6.26-rc4/arch/mips/configs/pnx8335-stb225_defconfig --- linux-2.6.26-rc4.orig/arch/mips/configs/pnx8335-stb225_defconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/configs/pnx8335-stb225_defconfig 2008-06-04 15:58:03.000000000 +0100 @@ -0,0 +1,1150 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.26-rc4 +# Wed Jun 4 15:57:17 2008 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_NXP_STB220 is not set +CONFIG_NXP_STB225=y +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +# CONFIG_WR_PPMC is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_CEVT_R4K=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_SOC_PNX833X=y +CONFIG_SOC_PNX8335=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR2=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +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_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_128=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=128 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_KEXEC is not set +# CONFIG_SECCOMP is not set +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_CLASSIC_RCU=y + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_MMU=y +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +CONFIG_INET_AH=y +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# 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_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_NOSWAP is not set +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_LE_BYTE_SWAP=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x18000000 +CONFIG_MTD_PHYSMAP_LEN=0x04000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# 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 +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_SATA_PMP=y +CONFIG_ATA_SFF=y +# CONFIG_SATA_MV is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_DM9000 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +# CONFIG_IP3902 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_ALGOPCA=y + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_PLATFORM is not set +CONFIG_I2C_PNX0105=y + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +CONFIG_DVB_CORE=y +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_DVB_CAPTURE_DRIVERS=y +# CONFIG_TTPCI_EEPROM is not set +# CONFIG_DVB_B2C2_FLEXCOP is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# DVB-S (satellite) frontends +# +# CONFIG_DVB_CX24110 is not set +# CONFIG_DVB_CX24123 is not set +# CONFIG_DVB_MT312 is not set +# CONFIG_DVB_S5H1420 is not set +# CONFIG_DVB_STV0299 is not set +# CONFIG_DVB_TDA8083 is not set +# CONFIG_DVB_TDA10086 is not set +# CONFIG_DVB_VES1X93 is not set +# CONFIG_DVB_TUNER_ITD1000 is not set +# CONFIG_DVB_TDA826X is not set +# CONFIG_DVB_TUA6100 is not set + +# +# DVB-T (terrestrial) frontends +# +# CONFIG_DVB_SP8870 is not set +# CONFIG_DVB_SP887X is not set +# CONFIG_DVB_CX22700 is not set +# CONFIG_DVB_CX22702 is not set +# CONFIG_DVB_L64781 is not set +CONFIG_DVB_TDA1004X=y +# CONFIG_DVB_NXT6000 is not set +# CONFIG_DVB_MT352 is not set +# CONFIG_DVB_ZL10353 is not set +# CONFIG_DVB_DIB3000MB is not set +# CONFIG_DVB_DIB3000MC is not set +# CONFIG_DVB_DIB7000M is not set +# CONFIG_DVB_DIB7000P is not set +# CONFIG_DVB_TDA10048 is not set + +# +# DVB-C (cable) frontends +# +# CONFIG_DVB_VES1820 is not set +# CONFIG_DVB_TDA10021 is not set +# CONFIG_DVB_TDA10023 is not set +# CONFIG_DVB_STV0297 is not set + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_LGDT330X is not set +# CONFIG_DVB_S5H1409 is not set +# CONFIG_DVB_AU8522 is not set +# CONFIG_DVB_S5H1411 is not set + +# +# Digital terrestrial only tuners/PLL +# +# CONFIG_DVB_PLL is not set +# CONFIG_DVB_TUNER_DIB0070 is not set + +# +# SEC control devices for DVB-S +# +# CONFIG_DVB_LNBP21 is not set +# CONFIG_DVB_ISL6405 is not set +# CONFIG_DVB_ISL6421 is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO 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=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_DETECT=y +# CONFIG_SND_PCM_XRUN_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA MIPS devices +# + +# +# System on Chip audio support +# +# CONFIG_SND_SOC is not set + +# +# ALSA SoC audio for Freescale SOCs +# + +# +# SoC Audio for the Texas Instruments OMAP +# + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# 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_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# 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=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# 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_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +# 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=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +# 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=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SAMPLES is not set +CONFIG_CMDLINE="" +CONFIG_SYS_SUPPORTS_KGDB=y + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/Kconfig linux-2.6.26-rc4/arch/mips/Kconfig --- linux-2.6.26-rc4.orig/arch/mips/Kconfig 2008-06-03 10:56:51.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/Kconfig 2008-06-03 17:12:19.000000000 +0100 @@ -311,6 +311,19 @@ select SYS_HAS_CPU_VR41XX select GENERIC_HARDIRQS_NO__DO_IRQ +config NXP_STB220 + bool "NXP STB220 board" + select SOC_PNX833X + help + Support for NXP Semiconductors STB220 Development Board. + +config NXP_STB225 + bool "NXP 225 board" + select SOC_PNX833X + select SOC_PNX8335 + help + Support for NXP Semiconductors STB225 Development Board. + config PNX8550_JBS bool "NXP PNX8550 based JBS board" select PNX8550 @@ -947,6 +960,26 @@ bool select SERIAL_RM9000 +config SOC_PNX833X + bool + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select DMA_NONCOHERENT + select SYS_HAS_EARLY_PRINTK + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_BIG_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ + select SYS_SUPPORTS_KGDB + select GENERIC_GPIO + select CPU_MIPSR2_IRQ_VI + +config SOC_PNX8335 + bool + select SOC_PNX833X + config PNX8550 bool select SOC_PNX8550 diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/Makefile linux-2.6.26-rc4/arch/mips/Makefile --- linux-2.6.26-rc4.orig/arch/mips/Makefile 2008-06-03 10:56:51.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/Makefile 2008-06-03 17:13:03.000000000 +0100 @@ -409,6 +409,14 @@ # load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 +# NXP STB225 +core-$(CONFIG_SOC_PNX833X) += arch/mips/nxp/pnx833x/common/ +cflags-$(CONFIG_SOC_PNX833X) += -Iinclude/asm-mips/mach-pnx833x +libs-$(CONFIG_NXP_STB220) += arch/mips/nxp/pnx833x/stb22x/ +load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 +libs-$(CONFIG_NXP_STB225) += arch/mips/nxp/pnx833x/stb22x/ +load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 + # # Common NXP PNX8550 # diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/gdb_hook.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/gdb_hook.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/gdb_hook.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/gdb_hook.c 2008-06-05 11:16:42.000000000 +0100 @@ -0,0 +1,162 @@ +/* + * gdb_hook.c: gdb hook for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on PNX8550. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*********************************************** +* INCLUDE FILES * +************************************************/ + +#include <asm/mach-pnx833x/pnx833x.h> +#include <linux/serial_pnx8xxx.h> + +/*********************************************** +* LOCAL MACROS * +************************************************/ + +#define UART0 (unsigned char *)PNX833X_UART0_PORTS_START +#define UART1 (unsigned char *)PNX833X_UART1_PORTS_START + +/*********************************************** +* LOCAL TYPEDEFS * +************************************************/ + +/*********************************************** +* STATIC FUNCTION PROTOTYPES * +************************************************/ + +/*********************************************** +* STATIC DATA * +************************************************/ + +static unsigned char *kgdb_uart = UART1; +static unsigned char *console_uart = UART0; +static volatile int delay_count; + +/*********************************************** +* EXPORTED DATA * +************************************************/ + +/*********************************************** +* FUNCTION IMPLEMENTATION * +************************************************/ + +static unsigned int serial_in(unsigned char *base_address, int offset) +{ + return *((unsigned int volatile *)(base_address + offset)); +} + +static void serial_out(unsigned char *base_address, int offset, int value) +{ + *((unsigned int volatile *)(base_address + offset)) = value; +} + +static void do_delay(void) +{ + int i; + for (i = 0; i < 10000; i++) + delay_count++; +} + +static int put_char(unsigned char *base_address, char c) +{ + /* Wait for TX to be ready */ + while (((serial_in(base_address, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) > 15) + do_delay(); + + /* Send the next character */ + serial_out(base_address, PNX8XXX_FIFO, c); + serial_out(base_address, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX); + + return 1; +} + +static char get_char(unsigned char *base_address) +{ + char output; + + /* Wait for RX to be ready */ + while ((serial_in(base_address, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_RXFIFO) == 0) + do_delay(); + + /* Get the character */ + output = serial_in(base_address, PNX8XXX_FIFO) & 0xFF; + + /* Move onto the next character in the buffer */ + serial_out(base_address, PNX8XXX_LCR, serial_in(base_address, PNX8XXX_LCR) | PNX8XXX_UART_LCR_RX_NEXT); + serial_out(base_address, PNX8XXX_ICLR, PNX8XXX_UART_INT_RX); + + return output; +} + +static void serial_init(unsigned char *base_address) +{ + serial_out(base_address, PNX8XXX_LCR, PNX8XXX_UART_LCR_8BIT | PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST); + serial_out(base_address, PNX8XXX_MCR, PNX8XXX_UART_MCR_DTR | PNX8XXX_UART_MCR_RTS); + serial_out(base_address, PNX8XXX_BAUD, 1); /* 115200 Baud */ + serial_out(base_address, PNX8XXX_CFG, 0x00060030); + serial_out(base_address, PNX8XXX_ICLR, -1); + serial_out(base_address, PNX8XXX_IEN, 0); +} + +static void setup_serial_output(void) +{ + static bool initialised; + if (!initialised) { + serial_init(kgdb_uart); + serial_init(console_uart); + initialised = true; + } +} + +int rs_kgdb_hook(int tty_no, int speed) +{ + kgdb_uart = tty_no ? UART1 : UART0; + console_uart = tty_no ? UART0 : UART1; + + setup_serial_output(); + + return speed; +} + +int prom_putchar(char c) +{ + setup_serial_output(); + return put_char(console_uart, c); +} + +char prom_getchar(void) +{ + setup_serial_output(); + return get_char(console_uart); +} + +int put_debug_char(char c) +{ + setup_serial_output(); + return put_char(kgdb_uart, c); +} + +char get_debug_char(void) +{ + setup_serial_output(); + return get_char(kgdb_uart); +} diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/interrupts.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/interrupts.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/interrupts.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/interrupts.c 2008-06-05 11:44:06.000000000 +0100 @@ -0,0 +1,363 @@ +/* + * interrupts.c: Interrupt mappings for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/hardirq.h> +#include <linux/interrupt.h> +#include <asm/mipsregs.h> +#include <asm/irq_cpu.h> +#include <irq.h> +#include <gpio.h> + +static const unsigned int irq_prio[PNX833X_PIC_NUM_IRQ] = +{ + 0, /* unused */ + 4, /* PNX833X_PIC_I2C0_INT 1 */ + 4, /* PNX833X_PIC_I2C1_INT 2 */ + 1, /* PNX833X_PIC_UART0_INT 3 */ + 1, /* PNX833X_PIC_UART1_INT 4 */ + 6, /* PNX833X_PIC_TS_IN0_DV_INT 5 */ + 6, /* PNX833X_PIC_TS_IN0_DMA_INT 6 */ + 7, /* PNX833X_PIC_GPIO_INT 7 */ + 4, /* PNX833X_PIC_AUDIO_DEC_INT 8 */ + 5, /* PNX833X_PIC_VIDEO_DEC_INT 9 */ + 4, /* PNX833X_PIC_CONFIG_INT 10 */ + 4, /* PNX833X_PIC_AOI_INT 11 */ + 9, /* PNX833X_PIC_SYNC_INT 12 */ + 9, /* PNX8335_PIC_SATA_INT 13 */ + 4, /* PNX833X_PIC_OSD_INT 14 */ + 9, /* PNX833X_PIC_DISP1_INT 15 */ + 4, /* PNX833X_PIC_DEINTERLACER_INT 16 */ + 9, /* PNX833X_PIC_DISPLAY2_INT 17 */ + 4, /* PNX833X_PIC_VC_INT 18 */ + 4, /* PNX833X_PIC_SC_INT 19 */ + 9, /* PNX833X_PIC_IDE_INT 20 */ + 9, /* PNX833X_PIC_IDE_DMA_INT 21 */ + 6, /* PNX833X_PIC_TS_IN1_DV_INT 22 */ + 6, /* PNX833X_PIC_TS_IN1_DMA_INT 23 */ + 4, /* PNX833X_PIC_SGDX_DMA_INT 24 */ + 4, /* PNX833X_PIC_TS_OUT_INT 25 */ + 4, /* PNX833X_PIC_IR_INT 26 */ + 3, /* PNX833X_PIC_VMSP1_INT 27 */ + 3, /* PNX833X_PIC_VMSP2_INT 28 */ + 4, /* PNX833X_PIC_PIBC_INT 29 */ + 4, /* PNX833X_PIC_TS_IN0_TRD_INT 30 */ + 4, /* PNX833X_PIC_SGDX_TPD_INT 31 */ + 5, /* PNX833X_PIC_USB_INT 32 */ + 4, /* PNX833X_PIC_TS_IN1_TRD_INT 33 */ + 4, /* PNX833X_PIC_CLOCK_INT 34 */ + 4, /* PNX833X_PIC_SGDX_PARSER_INT 35 */ + 4, /* PNX833X_PIC_VMSP_DMA_INT 36 */ +#if defined(CONFIG_SOC_PNX8335) + 4, /* PNX8335_PIC_MIU_INT 37 */ + 4, /* PNX8335_PIC_AVCHIP_IRQ_INT 38 */ + 9, /* PNX8335_PIC_SYNC_HD_INT 39 */ + 9, /* PNX8335_PIC_DISP_HD_INT 40 */ + 9, /* PNX8335_PIC_DISP_SCALER_INT 41 */ + 4, /* PNX8335_PIC_OSD_HD1_INT 42 */ + 4, /* PNX8335_PIC_DTL_WRITER_Y_INT 43 */ + 4, /* PNX8335_PIC_DTL_WRITER_C_INT 44 */ + 4, /* PNX8335_PIC_DTL_EMULATOR_Y_IR_INT 45 */ + 4, /* PNX8335_PIC_DTL_EMULATOR_C_IR_INT 46 */ + 4, /* PNX8335_PIC_DENC_TTX_INT 47 */ + 4, /* PNX8335_PIC_MMI_SIF0_INT 48 */ + 4, /* PNX8335_PIC_MMI_SIF1_INT 49 */ + 4, /* PNX8335_PIC_MMI_CDMMU_INT 50 */ + 4, /* PNX8335_PIC_PIBCS_INT 51 */ + 12, /* PNX8335_PIC_ETHERNET_INT 52 */ + 3, /* PNX8335_PIC_VMSP1_0_INT 53 */ + 3, /* PNX8335_PIC_VMSP1_1_INT 54 */ + 4, /* PNX8335_PIC_VMSP1_DMA_INT 55 */ + 4, /* PNX8335_PIC_TDGR_DE_INT 56 */ + 4, /* PNX8335_PIC_IR1_IRQ_INT 57 */ +#endif +}; + +static void pic_dispatch(void) +{ + unsigned int irq = PNX833X_REGFIELD(PIC_INT_SRC, INT_SRC); + + if ((irq >= 1) && (irq < (PNX833X_PIC_NUM_IRQ))) { + unsigned long priority = PNX833X_PIC_INT_PRIORITY; + PNX833X_PIC_INT_PRIORITY = irq_prio[irq]; + + if (irq == PNX833X_PIC_GPIO_INT) { + unsigned long mask = PNX833X_PIO_INT_STATUS & PNX833X_PIO_INT_ENABLE; + int pin; + while ((pin = ffs(mask & 0xffff))) { + pin -= 1; + do_IRQ(PNX833X_GPIO_IRQ_BASE + pin); + mask &= ~(1 << pin); + } + } else { + do_IRQ(irq + PNX833X_PIC_IRQ_BASE); + } + + PNX833X_PIC_INT_PRIORITY = priority; + } else { + printk(KERN_ERR "plat_irq_dispatch: unexpected irq %u\n", irq); + } +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & STATUSF_IP4) + pic_dispatch(); + else if (pending & STATUSF_IP7) + do_IRQ(PNX833X_TIMER_IRQ); + else + spurious_interrupt(); +} + +static inline void pnx833x_hard_enable_pic_irq(unsigned int irq) +{ + /* Currently we do this by setting IRQ priority to 1. + If priority support is being implemented, 1 should be repalced + by a better value. */ + PNX833X_PIC_INT_REG(irq) = irq_prio[irq]; +} + +static inline void pnx833x_hard_disable_pic_irq(unsigned int irq) +{ + /* Disable IRQ by writing setting it's priority to 0 */ + PNX833X_PIC_INT_REG(irq) = 0; +} + +static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */ +#define IRQFLAG_STARTED 1 +#define IRQFLAG_DISABLED 2 + +static DEFINE_SPINLOCK(irq_lock); + +static unsigned int pnx833x_startup_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + spin_lock_irqsave(&irq_lock, flags); + + irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */ + pnx833x_hard_enable_pic_irq(pic_irq); + + spin_unlock_irqrestore(&irq_lock, flags); + return 0; +} + +static void pnx833x_shutdown_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + spin_lock_irqsave(&irq_lock, flags); + + irqflags[pic_irq] = 0; /* not started */ + pnx833x_hard_disable_pic_irq(pic_irq); + + spin_unlock_irqrestore(&irq_lock, flags); +} + +static void pnx833x_enable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + spin_lock_irqsave(&irq_lock, flags); + + irqflags[pic_irq] &= ~IRQFLAG_DISABLED; + if (irqflags[pic_irq] == IRQFLAG_STARTED) + pnx833x_hard_enable_pic_irq(pic_irq); + + spin_unlock_irqrestore(&irq_lock, flags); +} + +static void pnx833x_disable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + spin_lock_irqsave(&irq_lock, flags); + + irqflags[pic_irq] |= IRQFLAG_DISABLED; + pnx833x_hard_disable_pic_irq(pic_irq); + + spin_unlock_irqrestore(&irq_lock, flags); +} + +static void pnx833x_ack_pic_irq(unsigned int irq) +{ +} + +static void pnx833x_end_pic_irq(unsigned int irq) +{ +} + +static DEFINE_SPINLOCK(gpio_irq_lock); + +static unsigned int pnx833x_startup_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + spin_lock_irqsave(&gpio_irq_lock, flags); + gpio_enable_irq(pin); + spin_unlock_irqrestore(&gpio_irq_lock, flags); + return 0; +} + +static void pnx833x_enable_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + spin_lock_irqsave(&gpio_irq_lock, flags); + gpio_enable_irq(pin); + spin_unlock_irqrestore(&gpio_irq_lock, flags); +} + +static void pnx833x_disable_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + spin_lock_irqsave(&gpio_irq_lock, flags); + gpio_disable_irq(pin); + spin_unlock_irqrestore(&gpio_irq_lock, flags); +} + +static void pnx833x_ack_gpio_irq(unsigned int irq) +{ +} + +static void pnx833x_end_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + spin_lock_irqsave(&gpio_irq_lock, flags); + gpio_clear_irq(pin); + spin_unlock_irqrestore(&gpio_irq_lock, flags); +} + +static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + int gpio_mode; + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + gpio_mode = GPIO_INT_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + gpio_mode = GPIO_INT_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + gpio_mode = GPIO_INT_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_HIGH: + gpio_mode = GPIO_INT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + gpio_mode = GPIO_INT_LEVEL_LOW; + break; + default: + gpio_mode = GPIO_INT_NONE; + break; + } + + gpio_setup_irq(gpio_mode, pin); + + return 0; +} + +static struct irq_chip pnx833x_pic_irq_type = { + .typename = "PNX-PIC", + .startup = pnx833x_startup_pic_irq, + .shutdown = pnx833x_shutdown_pic_irq, + .enable = pnx833x_enable_pic_irq, + .disable = pnx833x_disable_pic_irq, + .ack = pnx833x_ack_pic_irq, + .end = pnx833x_end_pic_irq +}; + +static struct irq_chip pnx833x_gpio_irq_type = { + .typename = "PNX-GPIO", + .startup = pnx833x_startup_gpio_irq, + .shutdown = pnx833x_disable_gpio_irq, + .enable = pnx833x_enable_gpio_irq, + .disable = pnx833x_disable_gpio_irq, + .ack = pnx833x_ack_gpio_irq, + .end = pnx833x_end_gpio_irq, + .set_type = pnx833x_set_type_gpio_irq +}; + +void __init arch_init_irq(void) +{ + unsigned int irq; + + /* setup standard internal cpu irqs */ + mips_cpu_irq_init(); + + /* Set IRQ information in irq_desc */ + for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { + pnx833x_hard_disable_pic_irq(irq); + set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); + } + + for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) + set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); + + /* Set PIC priority limiter register to 0 */ + PNX833X_PIC_INT_PRIORITY = 0; + + /* Setup GPIO IRQ dispatching */ + pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); + + /* Enable PIC IRQs (HWIRQ2) */ + if (cpu_has_vint) + set_vi_handler(4, pic_dispatch); + + write_c0_status(read_c0_status() | IE_IRQ2); +} + + +void __init plat_time_init(void) +{ + /* calculate mips_hpt_frequency based on PNX833X_CLOCK_CPUCP_CTL reg */ + + extern unsigned long mips_hpt_frequency; + unsigned long reg = PNX833X_CLOCK_CPUCP_CTL; + + if (!(PNX833X_BIT(reg, CLOCK_CPUCP_CTL, EXIT_RESET))) { + /* Functional clock is disabled so use crystal frequency */ + mips_hpt_frequency = 25; + } else { +#if defined(CONFIG_SOC_PNX8335) + /* Functional clock is enabled, so get clock multiplier */ + mips_hpt_frequency = 90 + (10 * PNX8335_REGFIELD(CLOCK_PLL_CPU_CTL, FREQ)); +#else + static const unsigned long int freq[4] = {240, 160, 120, 80}; + mips_hpt_frequency = freq[PNX833X_FIELD(reg, CLOCK_CPUCP_CTL, DIV_CLOCK)]; +#endif + } + + printk(KERN_INFO "CPU clock is %ld MHz\n", mips_hpt_frequency); + + mips_hpt_frequency *= 500000; +} + diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/Makefile linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/Makefile --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/Makefile 2008-03-03 13:09:30.000000000 +0000 @@ -0,0 +1 @@ +obj-y := interrupts.o platform.o prom.o setup.o reset.o gdb_hook.o diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/platform.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/platform.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/platform.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/platform.c 2008-06-05 11:09:06.000000000 +0100 @@ -0,0 +1,337 @@ +/* + * platform.c: platform support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on software written by: + * Nikita Youshchenko <yoush@xxxxxxxxxx>, based on PNX8550 code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/resource.h> +#include <linux/serial.h> +#include <linux/serial_pnx8xxx.h> +#include <linux/i2c-pnx0105.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include <irq.h> +#include <pnx833x.h> + +#if defined(CONFIG_SERIAL_PNX8XXX) || defined(CONFIG_SERIAL_PNX8XXX_MODULE) +static u64 uart_dmamask = ~(u32)0; + +static struct resource pnx833x_uart_resources[] = { + [0] = { + .start = PNX833X_UART0_PORTS_START, + .end = PNX833X_UART0_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX833X_PIC_UART0_INT, + .end = PNX833X_PIC_UART0_INT, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = PNX833X_UART1_PORTS_START, + .end = PNX833X_UART1_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = PNX833X_PIC_UART1_INT, + .end = PNX833X_PIC_UART1_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct pnx8xxx_port pnx8xxx_ports[] = { + [0] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX833X_UART0_PORTS_START, + .mapbase = PNX833X_UART0_PORTS_START, + .irq = PNX833X_PIC_UART0_INT, + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + }, + [1] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX833X_UART1_PORTS_START, + .mapbase = PNX833X_UART1_PORTS_START, + .irq = PNX833X_PIC_UART1_INT, + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + }, +}; + +static struct platform_device pnx833x_uart_device = { + .name = "pnx8xxx-uart", + .id = -1, + .dev = { + .dma_mask = &uart_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = pnx8xxx_ports, + }, + .num_resources = ARRAY_SIZE(pnx833x_uart_resources), + .resource = pnx833x_uart_resources, +}; +#endif + +#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE) +static u64 ehci_dmamask = ~(u32)0; + +static struct resource pnx833x_usb_ehci_resources[] = { + [0] = { + .start = PNX833X_USB_PORTS_START, + .end = PNX833X_USB_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX833X_PIC_USB_INT, + .end = PNX833X_PIC_USB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_usb_ehci_device = { + .name = "pnx833x-ehci", + .id = -1, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pnx833x_usb_ehci_resources), + .resource = pnx833x_usb_ehci_resources, +}; +#endif + +#if defined(CONFIG_I2C_PNX0105) || defined(CONFIG_I2C_PNX0105_MODULE) +static struct resource pnx833x_i2c0_resources[] = { + { + .start = PNX833X_I2C0_PORTS_START, + .end = PNX833X_I2C0_PORTS_END, + .flags = IORESOURCE_MEM, + }, + { + .start = PNX833X_PIC_I2C0_INT, + .end = PNX833X_PIC_I2C0_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource pnx833x_i2c1_resources[] = { + { + .start = PNX833X_I2C1_PORTS_START, + .end = PNX833X_I2C1_PORTS_END, + .flags = IORESOURCE_MEM, + }, + { + .start = PNX833X_PIC_I2C1_INT, + .end = PNX833X_PIC_I2C1_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { + { + .base = PNX833X_I2C0_PORTS_START, + .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ + .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */ + .bus_addr = 0, /* no slave support */ + }, + { + .base = PNX833X_I2C1_PORTS_START, + .irq = -1, /* on high freq, polling is faster */ + /*.irq = PNX833X_PIC_I2C1_INT,*/ + .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */ + .bus_addr = 0, /* no slave support */ + }, +}; + +static struct platform_device pnx833x_i2c0_device = { + .name = "i2c-pnx0105", + .id = 0, + .dev = { + .platform_data = &pnx833x_i2c_dev[0], + }, + .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources), + .resource = pnx833x_i2c0_resources, +}; + +static struct platform_device pnx833x_i2c1_device = { + .name = "i2c-pnx0105", + .id = 1, + .dev = { + .platform_data = &pnx833x_i2c_dev[1], + }, + .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources), + .resource = pnx833x_i2c1_resources, +}; +#endif + +#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE) +static u64 ethernet_dmamask = ~(u32)0; + +static struct resource pnx833x_ethernet_resources[] = { + [0] = { + .start = PNX8335_IP3902_PORTS_START, + .end = PNX8335_IP3902_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8335_PIC_ETHERNET_INT, + .end = PNX8335_PIC_ETHERNET_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_ethernet_device = { + .name = "ip3902-eth", + .id = -1, + .dev = { + .dma_mask = ðernet_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pnx833x_ethernet_resources), + .resource = pnx833x_ethernet_resources, +}; +#endif + +#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE) +static struct resource pnx833x_sata_resources[] = { + [0] = { + .start = PNX8335_SATA_PORTS_START, + .end = PNX8335_SATA_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8335_PIC_SATA_INT, + .end = PNX8335_PIC_SATA_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_sata_device = { + .name = "pnx833x-sata", + .id = -1, + .num_resources = ARRAY_SIZE(pnx833x_sata_resources), + .resource = pnx833x_sata_resources, +}; +#endif + +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + +#define STB225_NAND_BASE 0x18000000 /* I/O location(gets remapped)*/ +#define STB225_NAND_CLE_MASK 0x00100000 /* I/O location with CLE high */ +#define STB225_NAND_ALE_MASK 0x00010000 /* I/O location with ALE high */ + +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probes[] = { "cmdlinepart", 0 }; +#endif + +static void +pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, (void __iomem *)(nandaddr + STB225_NAND_CLE_MASK)); + else + writeb(cmd, (void __iomem *) (nandaddr + STB225_NAND_ALE_MASK)); +} + +static struct platform_nand_data pnx833x_flash_nand_data = { + .chip = { + .chip_delay = 25, +#ifdef CONFIG_MTD_PARTITIONS + .part_probe_types = part_probes, +#endif + }, + .ctrl = { + .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl + } +}; + +/* Set start to be the correct address (STB225_NAND_BASE with no 0xb!!), + 12 bytes more seems to be the standard that allows for NAND access.*/ +static struct resource pnx833x_flash_nand_resource = { + .start = STB225_NAND_BASE, + .end = STB225_NAND_BASE + 12, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device pnx833x_flash_nand = { + .name = "gen_nand", + .id = -1, + .num_resources = 1, + .resource = &pnx833x_flash_nand_resource, + .dev = { + .platform_data = &pnx833x_flash_nand_data, + }, +}; +#endif /* CONFIG_MTD_NAND_PLATFORM */ + +static struct platform_device *pnx833x_platform_devices[] __initdata = { +#if defined(CONFIG_SERIAL_PNX8XXX) || defined(CONFIG_SERIAL_PNX8XXX_MODULE) + &pnx833x_uart_device, +#endif +#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE) + &pnx833x_usb_ehci_device, +#endif +#if defined(CONFIG_I2C_PNX0105) || defined(CONFIG_I2C_PNX0105_MODULE) + &pnx833x_i2c0_device, + &pnx833x_i2c1_device, +#endif +#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE) + &pnx833x_ethernet_device, +#endif +#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE) + &pnx833x_sata_device, +#endif +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + &pnx833x_flash_nand, +#endif +}; + +int __init pnx833x_platform_init(void) +{ + int res; + + if (ARRAY_SIZE(pnx833x_platform_devices)) { + res = platform_add_devices(pnx833x_platform_devices, + ARRAY_SIZE(pnx833x_platform_devices)); + } + return res; +} + +arch_initcall(pnx833x_platform_init); diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/prom.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/prom.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/prom.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/prom.c 2008-06-05 09:26:59.000000000 +0100 @@ -0,0 +1,69 @@ +/* + * prom.c: + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on software written by: + * Nikita Youshchenko <yoush@xxxxxxxxxx>, based on PNX8550 code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/init.h> +#include <asm/bootinfo.h> +#include <linux/string.h> + +void __init prom_init_cmdline(void) +{ + int argc = fw_arg0; + char **argv = (char **)fw_arg1; + char *c = &(arcs_cmdline[0]); + int i; + + for (i = 1; i < argc; i++) { + strcpy(c, argv[i]); + c += strlen(argv[i]); + if (i < argc-1) + *c++ = ' '; + } + *c = 0; +} + +char __init *prom_getenv(char *envname) +{ + extern char **prom_envp; + char **env = prom_envp; + int i; + + i = strlen(envname); + + while (*env) { + if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') + return *env + i + 1; + env++; + } + + return 0; +} + +void __init prom_free_prom_memory(void) +{ +} + +char * __init prom_getcmdline(void) +{ + return arcs_cmdline; +} + diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/reset.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/reset.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/reset.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/reset.c 2008-06-05 11:27:00.000000000 +0100 @@ -0,0 +1,48 @@ +/* + * reset.c: reset support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on software written by: + * Nikita Youshchenko <yoush@xxxxxxxxxx>, based on PNX8550 code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/slab.h> +#include <linux/reboot.h> +#include <pnx833x.h> + +void pnx833x_machine_restart(char *command) +{ + printk(KERN_ALERT "\n\nRestarting ...\n\n"); + + PNX833X_RESET_CONTROL_2 = 0; + PNX833X_RESET_CONTROL = 0; +} + +void pnx833x_machine_halt(void) +{ + printk(KERN_ALERT "\n\nSystem halted.\n\n"); + + while (1) + __asm__ __volatile__ ("wait"); +} + +void pnx833x_machine_power_off(void) +{ + printk(KERN_ALERT "\n\nPower off not implemented."); + pnx833x_machine_halt(); +} diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/setup.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/setup.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/common/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/common/setup.c 2008-06-05 11:46:31.000000000 +0100 @@ -0,0 +1,63 @@ +/* + * setup.c: Setup PNX833X Soc. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on software written by: + * Nikita Youshchenko <yoush@xxxxxxxxxx>, based on PNX8550 code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/pci.h> +#include <asm/reboot.h> +#include <pnx833x.h> +#include <gpio.h> + +extern void pnx833x_board_setup(void); +extern void pnx833x_machine_restart(char *); +extern void pnx833x_machine_halt(void); +extern void pnx833x_machine_power_off(void); + +int __init plat_mem_setup(void) +{ + /* fake pci bus to avoid bounce buffers */ + PCI_DMA_BUS_IS_PHYS = 1; + + /* set mips clock to 320MHz */ +#if defined(CONFIG_SOC_PNX8335) + PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); +#endif + gpio_init(); /* so it will be ready in board_setup() */ + + pnx833x_board_setup(); + + _machine_restart = pnx833x_machine_restart; + _machine_halt = pnx833x_machine_halt; + pm_power_off = pnx833x_machine_power_off; + + /* IO/MEM resources. */ + set_io_port_base(KSEG1); + ioport_resource.start = 0; + ioport_resource.end = ~0; + iomem_resource.start = 0; + iomem_resource.end = ~0; + + return 0; +} diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/board.c linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/board.c --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/board.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/board.c 2008-06-05 11:17:10.000000000 +0100 @@ -0,0 +1,138 @@ +/* + * board.c: STB225 board support. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on software written by: + * Nikita Youshchenko <yoush@xxxxxxxxxx>, based on PNX8550 code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/init.h> +#include <asm/bootinfo.h> +#include <linux/mm.h> +#include <pnx833x.h> +#include <gpio.h> + +/* endianess twiddlers */ +#define PNX8335_DEBUG0 0x4400 +#define PNX8335_DEBUG1 0x4404 +#define PNX8335_DEBUG2 0x4408 +#define PNX8335_DEBUG3 0x440c +#define PNX8335_DEBUG4 0x4410 +#define PNX8335_DEBUG5 0x4414 +#define PNX8335_DEBUG6 0x4418 +#define PNX8335_DEBUG7 0x441c + +int prom_argc; +char **prom_argv = 0, **prom_envp = 0; + +extern void prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP STB22x"; +} + +static inline unsigned long env_or_default(char *env, unsigned long dfl) +{ + char *str = prom_getenv(env); + return str ? simple_strtol(str, 0, 0) : dfl; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize = env_or_default("memsize", 0x02000000); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +void __init pnx833x_board_setup(void) +{ +#if defined(CONFIG_SERIAL_PNX8XXX) || defined(CONFIG_SERIAL_PNX8XXX_MODULE) + gpio_select_function_alt(4); + gpio_select_output(4); + gpio_select_function_alt(5); + gpio_select_input(5); + gpio_select_function_alt(6); + gpio_select_input(6); + gpio_select_function_alt(7); + gpio_select_output(7); +#endif + +#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE) + gpio_select_function_alt(25); + gpio_select_function_alt(26); +#endif + +#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE) + gpio_select_function_alt(27); + gpio_select_function_alt(28); + gpio_select_function_alt(29); + gpio_select_function_alt(30); + gpio_select_function_alt(31); + gpio_select_function_alt(32); + gpio_select_function_alt(33); +#endif + +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + /* Setup MIU for NAND access on CS0... + * + * (it seems that we must also configure CS1 for reliable operation, + * otherwise the first read ID command will fail if it's read as 4 bytes + * but pass if it's read as 1 word.) + */ + + /* Setup MIU CS0 & CS1 timing */ + PNX833X_MIU_SEL0 = 0; + PNX833X_MIU_SEL1 = 0; + PNX833X_MIU_SEL0_TIMING = 0x50003081; + PNX833X_MIU_SEL1_TIMING = 0x50003081; + + /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ + gpio_select_function_alt(0); + + /* Setup GPIO 04 to input NAND read/busy signal */ + gpio_select_function_io(4); + gpio_select_input(4); + + /* Setup GPIO 05 to disable NAND write protect */ + gpio_select_function_io(5); + gpio_select_output(5); + gpio_write(1, 5); + +#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) + + /* Set up MIU for 16-bit NOR access on CS0 and CS1... */ + + /* Setup MIU CS0 & CS1 timing */ + PNX833X_MIU_SEL0 = 1; + PNX833X_MIU_SEL1 = 1; + PNX833X_MIU_SEL0_TIMING = 0x6A08D082; + PNX833X_MIU_SEL1_TIMING = 0x6A08D082; + + /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ + gpio_select_function_alt(0); +#endif +} diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/Makefile linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/Makefile --- linux-2.6.26-rc4.orig/arch/mips/nxp/pnx833x/stb22x/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/nxp/pnx833x/stb22x/Makefile 2008-03-03 13:09:30.000000000 +0000 @@ -0,0 +1 @@ +lib-y := board.o diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/i2c/busses/i2c-pnx0105.c linux-2.6.26-rc4/drivers/i2c/busses/i2c-pnx0105.c --- linux-2.6.26-rc4.orig/drivers/i2c/busses/i2c-pnx0105.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/drivers/i2c/busses/i2c-pnx0105.c 2008-06-05 11:25:57.000000000 +0100 @@ -0,0 +1,328 @@ +/* + * i2c-pnx0105.c: driver for PNX833X I2C (IP0105 Block) + * + * Copyright 2008 NXP Semiconductors + * Daniel Laird <daniel.j.laird@xxxxxxx> + * + * Copyright (C) 2006 Nikita Youshchenko <yoush@xxxxxxxxxx> + * + * Partially based on i2c-pca-isa driver, Copyright (C) 2004 Arcom Control + * Systems. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/i2c-id.h> +#include <linux/i2c-pnx0105.h> +#include <linux/i2c-algo-pca.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +static inline unsigned long i2c_pnx0105_in(struct i2c_pnx0105_dev *dev, int offset) +{ + return readl((unsigned long *)(dev->base + offset)); +} + +static inline void i2c_pnx0105_out(struct i2c_pnx0105_dev *dev, int offset, unsigned long value) +{ + writel(value, (unsigned long *)(dev->base + offset)); +} + +static void i2c_pnx0105_writebyte(void *pa, int reg, int val) +{ + struct i2c_algo_pca_data *algo_data = container_of(pa, struct i2c_algo_pca_data, data); + struct i2c_pnx0105_dev *dev = container_of(algo_data, struct i2c_pnx0105_dev, algo_data); + int old_si; + +#ifdef DEBUG + static char *names[] = { "T/O", "DAT", "ADR", "CON"}; + printk(KERN_DEBUG "i2c_pnx0105(0x%08lx): write %s <= %#04x\n", dev->base, names[reg], val); +#endif + + switch (reg) { + + case I2C_PCA_DAT: + i2c_pnx0105_out(dev, I2C_PNX0105_DAT, val & 255); + break; + + case I2C_PCA_ADR: + i2c_pnx0105_out(dev, I2C_PNX0105_ADDRESS, val & 255); + break; + + case I2C_PCA_CON: + /* Possible RACE: just after init, or after stop, + SI bit is zero. That means that when STA bit + is written, hardware starts to process it + immediately. It could complete very fast (or + perhaps thread may get preempted), so when code + several lines below is executed, SI could already + be set to indicate that STA processing is complete. + In this case, SI must NOT be cleared here, so + hardware won't continue and send slave address + before it was written to register. + However, if SI bit is currently set, hardware + won't process command immediately, and SI should + be cleared at the bottom, to enable processing. + Solution: just check SI here, and clear it only + if it was set before any new value was written + to command register. + */ + old_si = i2c_pnx0105_in(dev, I2C_PNX0105_INT_STATUS) & 1; + + i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, val & 255); + + /* We have to process STO bit separately */ + if (val & I2C_PCA_CON_STO) + i2c_pnx0105_out(dev, I2C_PNX0105_STOP, 1); + + /* And also SI bit ... */ + if (old_si && !(val & I2C_PCA_CON_SI)) { + i2c_pnx0105_out(dev, I2C_PNX0105_INT_CLEAR, 1); + if (dev->irq > -1 && !(val & I2C_PCA_CON_STO)) + i2c_pnx0105_out(dev, I2C_PNX0105_INT_ENABLE, 1); + } + + break; + + default: + BUG(); + } +} + +static int i2c_pnx0105_readbyte(void *pa, int reg) +{ + struct i2c_algo_pca_data *algo_data = container_of(pa, struct i2c_algo_pca_data, data); + struct i2c_pnx0105_dev *dev = container_of(algo_data, struct i2c_pnx0105_dev, algo_data); + int res = 0; + + switch (reg) { + + case I2C_PCA_STA: + if (dev->timeout) { + res = 0xff; + dev->timeout = 0; + } else + res = i2c_pnx0105_in(dev, I2C_PNX0105_STATUS) & 255; + break; + + case I2C_PCA_DAT: + res = i2c_pnx0105_in(dev, I2C_PNX0105_DAT) & 255; + break; + + case I2C_PCA_CON: + res = i2c_pnx0105_in(dev, I2C_PNX0105_CONTROL) & 255; + + /* Read SI bit from elsewhere */ + if (i2c_pnx0105_in(dev, I2C_PNX0105_INT_STATUS)) + res |= I2C_PCA_CON_SI; + else + res &= ~I2C_PCA_CON_SI; + + break; + + default: + BUG(); + } + +#ifdef DEBUG + { + static char *names[] = { "STA", "DAT", "ADR", "CON"}; + printk(KERN_DEBUG "i2c_pnx0105(0x%08lx): read %s => %#04x\n", dev->base, names[reg], res); + } +#endif + return res; +} + +static inline void i2c_pnx0105_reset(struct i2c_pnx0105_dev *dev) +{ + unsigned long val = i2c_pnx0105_in(dev, I2C_PNX0105_CONTROL) & 0x47; + i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, val | 0x40); + i2c_pnx0105_out(dev, I2C_PNX0105_STOP, 1); + i2c_pnx0105_out(dev, I2C_PNX0105_INT_CLEAR, 1); + udelay(200); + i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, val); +} + +static inline int i2c_pnx0105_intr_condition(struct i2c_pnx0105_dev *dev) +{ + return i2c_pnx0105_in(dev, I2C_PNX0105_INT_STATUS) & 1; +} + +static int i2c_pnx0105_waitforcompletion(void *pa) +{ + struct i2c_algo_pca_data *algo_data = container_of(pa, struct i2c_algo_pca_data, data); + struct i2c_pnx0105_dev *dev = container_of(algo_data, struct i2c_pnx0105_dev, algo_data); + + /* Set some timeout */ +#define JIFFIES_TO_WAIT ((HZ / 100) + 1) /* attempt to model 10 milliseconds */ + + if (dev->irq > -1) { + wait_event_timeout(dev->wait, + i2c_pnx0105_intr_condition(dev), JIFFIES_TO_WAIT); + } else { + unsigned long end = jiffies + JIFFIES_TO_WAIT; + while (!i2c_pnx0105_intr_condition(dev) && + time_before(jiffies, end)) { + if (in_atomic()) + udelay(100); + else + schedule(); + } + } + + if (i2c_pnx0105_intr_condition(dev)) + return 0; + + /* Timeout. Reset device and make next status read to return 0xff */ + i2c_pnx0105_reset(dev); + dev->timeout = 1; + return -EIO; /* Ignored anyway */ +} + +static irqreturn_t i2c_pnx0105_interrupt(int this_irq, void *dev_id) +{ + struct i2c_pnx0105_dev *dev = (struct i2c_pnx0105_dev *)dev_id; + + /* Disable interrupt for a while (until it's actually handled) */ + i2c_pnx0105_out(dev, I2C_PNX0105_INT_ENABLE, 0); + + /* Wake up any process waiting for this interrupt */ + wake_up_interruptible(&dev->wait); + + return IRQ_HANDLED; +} + +static int __devinit i2c_pnx0105_probe(struct platform_device *pdev) +{ + struct i2c_pnx0105_dev *dev = (struct i2c_pnx0105_dev *) pdev->dev.platform_data; + struct i2c_algo_pca_data *algo_data = &dev->algo_data; + struct i2c_adapter *adap = &dev->adap; + int res; + + algo_data->write_byte = i2c_pnx0105_writebyte; + algo_data->read_byte = i2c_pnx0105_readbyte; + algo_data->wait_for_completion = i2c_pnx0105_waitforcompletion; + + adap->owner = THIS_MODULE; + adap->id = I2C_HW_A_PNX0105; + adap->algo_data = algo_data; + strncpy(adap->name, pdev->name, I2C_NAME_SIZE); + + dev->timeout = 0; + init_waitqueue_head(&dev->wait); + + if (request_region(dev->base, I2C_PNX0105_IO_SIZE, "i2c-pnx") == 0) { + printk(KERN_ERR "i2c-pnx0105: request_region(0x%08lx) failed\n", + dev->base); + return -EBUSY; + } + + /* Disable interrupt - just to be sure ... */ + i2c_pnx0105_out(dev, I2C_PNX0105_INT_ENABLE, 0); + + if (dev->irq > -1) { + res = request_irq(dev->irq, i2c_pnx0105_interrupt, 0, "i2c-pnx", dev); + if (res < 0) { + printk(KERN_ERR "i2c-pnx0105: request_irq() failed\n"); + goto err_region; + } + } + + /* Rude attempt to probe hardware, to avoid future hangups if it is + not responding */ + i2c_pnx0105_out(dev, I2C_PNX0105_CONTROL, 0x60); + udelay(200); + res = i2c_pnx0105_intr_condition(dev) ? 0 : -ENODEV; + i2c_pnx0105_reset(dev); + + if (res < 0) { + printk(KERN_ERR "i2c-pnx0105: device at 0x%08lx is not responding\n", + dev->base); + goto err_irq; + } + + res = i2c_pca_add_bus(adap); + if (res < 0) { + printk(KERN_ERR "i2c-pnx0105: i2c_pca_add_bus() failed\n"); + goto err_irq; + } + + printk(KERN_INFO "i2c-pnx0105: registered device at 0x%08lx", dev->base); + if (dev->irq > -1) + printk(KERN_ERR ", irq %d", dev->irq); + printk(KERN_INFO "\n"); + + return 0; + +err_irq: + if (dev->irq > -1) + free_irq(dev->irq, dev); + +err_region: + release_region(dev->base, I2C_PNX0105_IO_SIZE); + + return res; +} + +static int __devexit i2c_pnx0105_remove(struct platform_device *pdev) +{ + struct i2c_pnx0105_dev *dev = (struct i2c_pnx0105_dev *) pdev->dev.platform_data; + struct i2c_adapter *adap = &dev->adap; + int res; + + res = i2c_del_adapter(adap); + if (res < 0) + return res; + + if (dev->irq > -1) + free_irq(dev->irq, dev); + + release_region(dev->base, I2C_PNX0105_IO_SIZE); + + return 0; +} + +static struct platform_driver i2c_pnx0105_driver = { + .probe = i2c_pnx0105_probe, + .remove = __devexit_p(i2c_pnx0105_remove), + .driver = { + .owner = THIS_MODULE, + .name = "i2c-pnx0105", + }, +}; + +static int __init i2c_pnx0105_init(void) +{ + return platform_driver_register(&i2c_pnx0105_driver); +} + +static void __exit i2c_pnx0105_cleanup(void) +{ + platform_driver_unregister(&i2c_pnx0105_driver); +} + +module_init(i2c_pnx0105_init); +module_exit(i2c_pnx0105_cleanup); + +MODULE_AUTHOR("Nikita Youshchenko <yoush@xxxxxxxxxx>"); +MODULE_DESCRIPTION("PNX833X I2C driver"); +MODULE_LICENSE("GPL"); + + diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/i2c/busses/Kconfig linux-2.6.26-rc4/drivers/i2c/busses/Kconfig --- linux-2.6.26-rc4.orig/drivers/i2c/busses/Kconfig 2008-06-03 10:56:53.000000000 +0100 +++ linux-2.6.26-rc4/drivers/i2c/busses/Kconfig 2008-06-04 09:29:35.000000000 +0100 @@ -677,6 +677,18 @@ This driver can also be built as a module. If so, the module will be called i2c-pnx. +config I2C_PNX0105 + tristate "I2C bus support for Philips PNX8XXX targets" + depends on I2C && SOC_PNX833X + select I2C_ALGOPCA + default y + help + Support for NXP PNX SoC internal I2C (IP0105). + Say y or m if you want to use PNX I2C interfaces. + + This driver can also be built as a module. If so, the module + will be called i2c-pnx0105. + config I2C_PMCMSP tristate "PMC MSP I2C TWI Controller" depends on PMC_MSP diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/i2c/busses/Makefile linux-2.6.26-rc4/drivers/i2c/busses/Makefile --- linux-2.6.26-rc4.orig/drivers/i2c/busses/Makefile 2008-06-03 10:56:53.000000000 +0100 +++ linux-2.6.26-rc4/drivers/i2c/busses/Makefile 2008-06-04 09:29:40.000000000 +0100 @@ -34,6 +34,7 @@ obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o +obj-$(CONFIG_I2C_PNX0105) += i2c-pnx0105.o obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/net/ip3902.c linux-2.6.26-rc4/drivers/net/ip3902.c --- linux-2.6.26-rc4.orig/drivers/net/ip3902.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/drivers/net/ip3902.c 2008-06-05 11:27:28.000000000 +0100 @@ -0,0 +1,1534 @@ +/* + * ip3902.c: NXP ip3902 embedded 10/100 Ethernet controller support + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * Based on ax88796.c, by Ben Dooks. + * Based on previous ip3902.c by Nikita V. Youshchenko + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/isapnp.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/crc32.h> +#include <linux/inet_lro.h> +#include <asm/system.h> +#include <linux/io.h> + +#define DRVNAME "ip3902-eth" +#define DRVVERSION "1.00" + +#define IP3902_NAPI + +/* "Strange hardware" support macros */ + +/* These control endianness of descriptors and statuses. + * If none if LITTLE_ENDIAN_xxx and BIG_ENDIAN_xxx is defined, system endian + * is used for xxx */ +#define LITTLE_ENDIAN_DESCRIPTORS +#undef BIG_ENDIAN_DESCRIPTORS +#undef LITTLE_ENDIAN_STATUSES +#define BIG_ENDIAN_STATUSES + +#define ETH_RX_SKB_SIZE 0x600 /* 1536 bytes, just over max mtu */ +#define TX_RING_SIZE 64 +#define RX_RING_SIZE 64 +#define IP3902_NAPI_WEIGHT 48 +#define MAX_LRO_DESCRIPTORS 6 +#define LRO_THRESHOLD 3 + +#define BYTES_IN_ETHERNET_CRC 4 +#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) + +#define NEXT_TX(i) (((i) == TX_RING_SIZE-1) ? 0 : (i)+1) +#define NEXT_RX(i) (((i) == RX_RING_SIZE-1) ? 0 : (i)+1) + +/* Access to IP3902 registers */ + +/* Alcatel (Packet Engines) core registers */ +#define MAC1_REG 0x000 /* R/W: MAC configuration register 1 */ +#define MAC2_REG 0x004 /* R/W: MAC configuration register 2 */ +#define IPGT_REG 0x008 /* R/W: Back-to-Back Inter-Packet-Gap register */ +#define IPGR_REG 0x00c /* R/W: Non Back-to-Back Inter-Packet-Gap register */ +#define CLRT_REG 0x010 /* R/W: Collision window / Retry register */ +#define MAXF_REG 0x014 /* R/W: Maximum Frame register */ +#define SUPP_REG 0x018 /* R/W: PHY Support register */ +#define TEST_REG 0x01C /* R/W: Test register */ +#define MCFG_REG 0x020 /* R/W: MII Mgmt Con???guration register */ +#define MCMD_REG 0x024 /* R/W: MII Mgmt Command register */ +#define MADR_REG 0x028 /* R/W: MII Mgmt Address register */ +#define MWTD_REG 0x02C /* WO: MII Mgmt Write Data register */ +#define MRDD_REG 0x030 /* RO: MII Mgmt Read Data register */ +#define MIND_REG 0x034 /* RO: MII Mgmt Indicators register */ +#define SA0_REG 0x040 /* R/W: Station Address 0 register */ +#define SA1_REG 0x044 /* R/W: Station Address 1 register */ +#define SA2_REG 0x048 /* R/W: Station Address 2 register */ + +/* Control registers */ +#define COMMAND_REG 0x100 /* R/W: Command register */ +#define STATUS_REG 0x104 /* RO: Status register */ +#define RX_DESC_REG 0x108 /* R/W: Receive descriptor base address register */ +#define RX_STATUS_REG 0x10C /* R/W: Receive status base address register */ +#define RX_DESC_NUMBER_REG 0x110 /* R/W: Receive number of descriptors register */ +#define RX_PRODUCE_INDEX_REG 0x114 /* RO: Receive produce index register */ +#define RX_CONSUME_INDEX_REG 0x118 /* R/W: Receive consume index register */ +#define TX_DESC_REG 0x11C /* R/W: Non real-time transmit descriptor base address register */ +#define TX_STATUS_REG 0x120 /* R/W: Non real-time transmit status base address register */ +#define TX_DESC_NUMBER_REG 0x124 /* R/W: Non real-time transmit number of descriptors register */ +#define TX_PRODUCE_INDEX_REG 0x128 /* R/W: Non real-time transmit produce index register */ +#define TX_CONSUME_INDEX_REG 0x12C /* RO: Non real-time transmit consume index register */ +#define TX_RT_DESC_REG 0x130 /* R/W: Real-time transmit descriptor base address register */ +#define TX_RT_STATUS_REG 0x134 /* R/W: Real-time transmit status base address register */ +#define TX_RT_DESC_NUMBER_REG 0x138 /* R/W: Real-time transmit number of descriptors register */ +#define TX_RT_PRODUCE_INDEX_REG 0x13C /* R/W: Real-time transmit produce index register */ +#define TX_RT_CONSUME_INDEX_REG 0x140 /* RO: Real-time transmit consume index register */ +#define QOS_TIMEOUT_REG 0x148 /* R/W: Transmit quality of service time-out register */ +#define TSV0_REG 0x158 /* RO: Transmit status vector 0 register */ +#define TSV1_REG 0x15C /* RO: Transmit status vector 1 register */ +#define RSV_REG 0x160 /* RO: Receive status vector register */ +#define FC_COUNTER_REG 0x170 /* R/W: Flow control counter register */ +#define FC_STATUS_REG 0x174 /* RO: Flow control status register */ + +/* Rx filter registers */ +#define FILTER_CTRL_REG 0x200 /* R/W: Receive filter control register */ +#define FILTER_WOL_STATUS_REG 0x204 /* RO: Receive filter WoL status register */ +#define FILTER_WOL_CLEAR_REG 0x208 /* WO: Receive filter WoL clear register */ +#define HASH_FILTER_L_REG 0x210 /* R/W: Hash filter table LSBs register */ +#define HASH_FILTER_H_REG 0x214 /* R/W: Hash filter table MSBs register */ + +/* DVP Standard registers */ +#define INT_STATUS_REG 0xFE0 /* RO: Interrupt status register */ +#define INT_ENABLE_REG 0xFE4 /* R/W: Interrupt enable register */ +#define INT_CLEAR_REG 0xFE8 /* WO: Interrupt clear register */ +#define INT_SET_REG 0xFEC /* WO: Interrupt set register */ +#define POWERDOWN_REG 0xFF4 /* R/W: Power-down register */ +#define MODULE_ID_REG 0xFFC /* RO: Module ID register */ + +/* Bits for MAC1 register */ +#define MAC1_SOFT_RESET (1 << 15) +#define MAC1_TX_FLOW_CONTROL (1 << 3) +#define MAC1_RX_FLOW_CONTROL (1 << 2) +#define MAC1_RECEIVE_PASS_ALL (1 << 1) +#define MAC1_RECEIVE_ENABLE (1 << 0) + +/* Bits for MAC2 register */ +#define MAC2_AUTO_DETECT_PAD_ENABLE (1 << 7) +#define MAC2_VLAN_PAD_ENABLE (1 << 6) +#define MAC2_PAD_CRC_ENABLE (1 << 5) +#define MAC2_CRC_ENABLE (1 << 4) +#define MAC2_FULL_DUPLEX (1 << 0) + +#define INITIAL_MAC2 (MAC2_AUTO_DETECT_PAD_ENABLE | MAC2_VLAN_PAD_ENABLE | MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE) + +/* Recommended values for IPGT register (see sec. 3.3.2.3 0f datasheet */ +#define IPGT_FD_VALUE 0x15 +#define IPGT_HD_VALUE 0x12 + +/* Bits for MCMD register */ +#define MCMD_READ (1 << 0) + +/* Bits for MIND register */ +#define MIND_NOT_VALID (1 << 2) +#define MIND_BUSY (1 << 0) + +/* Bits for command register */ +#define COMMAND_ENABLE_QOS (1 << 11) +#define COMMAND_FULL_DUPLEX (1 << 10) +#define COMMAND_RMII_MODE (1 << 9) +#define COMMAND_TX_FLOW_CONTROL (1 << 8) +#define COMMAND_PROMISC (1 << 7) +#define COMMAND_ALLOW_SHORT (1 << 6) +#define COMMAND_RX_RESET (1 << 5) +#define COMMAND_TX_RESET (1 << 4) +#define COMMAND_RESET (1 << 3) +#define COMMAND_TX_RT_ENABLE (1 << 2) +#define COMMAND_TX_ENABLE (1 << 1) +#define COMMAND_RX_ENABLE (1 << 0) + +/* Bits for receive filter control register */ +#define FILTER_ACCEPT_SELF (1 << 5) +#define FILTER_ACCEPT_MCAST_HASH (1 << 4) +#define FILTER_ACCEPT_UCAST_HASH (1 << 3) +#define FILTER_ACCEPT_MCAST_ANY (1 << 2) +#define FILTER_ACCEPT_BCAST_ANY (1 << 1) +#define FILTER_ACCEPT_UCAST_ANY (1 << 0) + +/* Bits for interrupt registers */ +#define WAKEUP_INT (1 << 13) +#define SOFT_INT (1 << 12) +#define TX_RT_DONE_INT (1 << 11) +#define TX_RT_FINISHED_INT (1 << 10) +#define TX_RT_ERROR_INT (1 << 9) +#define TX_RT_UNDERRUN_INT (1 << 8) +#define TX_DONE_INT (1 << 7) +#define TX_FINISHED_INT (1 << 6) +#define TX_ERROR_INT (1 << 5) +#define TX_UNDERRUN_INT (1 << 4) +#define RX_DONE_INT (1 << 3) +#define RX_FINISHED_INT (1 << 2) +#define RX_ERROR_INT (1 << 1) +#define RX_OVERRUN_INT (1 << 0) + +/* Bit for POWERDOWN register */ +#define POWERDOWN_VALUE (1 << 31) + +/* Bits for TX control */ +#define TX_CONTROL_INT (1 << 31) +#define TX_CONTROL_LAST (1 << 30) +#define TX_CONTROL_CRC (1 << 29) +#define TX_CONTROL_PAD (1 << 28) +#define TX_CONTROL_HUGE (1 << 27) +#define TX_CONTROL_OVERRIDE (1 << 26) + +/* these flags used for non-last fragment of a frame */ +#define TX_CONTROL_ALL_NOTLAST (TX_CONTROL_CRC | TX_CONTROL_PAD | TX_CONTROL_OVERRIDE) +/* these flags used for last fragment of a frame, and for single-fragment + * frames */ +#define TX_CONTROL_ALL_LAST (TX_CONTROL_ALL_NOTLAST | TX_CONTROL_LAST | TX_CONTROL_INT) + +/* Bits for TX status */ +#define TX_STATUS_ERROR (1 << 31) +#define TX_STATUS_UNDERRUN (1 << 29) +#define TX_STATUS_LATE_COLLISION (1 << 28) +#define TX_STATUS_MANY_COLLISIONS (1 << 27) +#define TX_STATUS_MANY_DEFER (1 << 26) +#define TX_STATUS_COLLISIONS(s) ((s >> 21) & 15) + +/* Bits for RX control */ +#define RX_CONTROL_INT (1 << 31) + +/* Bits for RX status */ +#define RX_STATUS_ERROR (1 << 31) +#define RX_STATUS_LAST_FRAG (1 << 30) +#define RX_STATUS_OVERRUN (1 << 28) +#define RX_STATUS_ALIGNMENT_ERROR (1 << 27) +#define RX_STATUS_RANGE_ERROR (1 << 26) +#define RX_STATUS_LENGTH_ERROR (1 << 25) +#define RX_STATUS_SYMBOL_ERROR (1 << 24) +#define RX_STATUS_CRC_ERROR (1 << 23) +#define RX_STATUS_BROADCAST (1 << 22) +#define RX_STATUS_MULTICAST (1 << 21) +#define RX_STATUS_FAIL_FILTER (1 << 20) +#define RX_STATUS_VLAN (1 << 19) +#define RX_STATUS_CONTROL_FRAME (1 << 18) +#define RX_STATUS_LENGTH(s) ((s & 0x7ff) + 1) + +/* Bits for RSV register */ +#define RSV_VLAN (1 << 30) +#define RSV_CONTROL_FRAME (1 << 27) +#define RSV_DRIBBLE_NIBBLE (1 << 26) +#define RSV_BROADCAST (1 << 25) +#define RSV_MULTICAST (1 << 24) +#define RSV_LENGTH_OUT_OF_RANGE (1 << 22) +#define RSV_LENGTH_CHECK_ERROR (1 << 21) +#define RSV_CRC_ERROR (1 << 20) +#define RSV_RECEIVE_CODE_VIOLATION (1 << 19) +#define RSV_MASK 0xFFFF + +static char *mac_address; +module_param(mac_address, charp, S_IRUGO); +MODULE_PARM_DESC(mac_address, "MAC address of the device"); + + +/* device private data */ +struct ip3902_descriptor { + unsigned long address; + unsigned long control; +}; + +struct ip3902_rx_status { + unsigned long status; + unsigned long hash_crc; +}; + +struct ip3902_dma_struct { + struct ip3902_descriptor rx_desc[RX_RING_SIZE]; + struct ip3902_rx_status rx_status[RX_RING_SIZE]; + struct ip3902_descriptor tx_desc[TX_RING_SIZE]; + unsigned long tx_status[TX_RING_SIZE]; +}; + +struct ip3902_private { + spinlock_t mii_lock; + struct mii_if_info mii; + u32 msg_enable; + + spinlock_t lock; + struct net_device *ndev; + struct platform_device *pdev; + struct resource *bus; + void __iomem *mem; +#ifdef IP3902_NAPI + struct napi_struct napi; +#endif + + struct ip3902_dma_struct *ds; /* descriptors and statuses */ + dma_addr_t ds_dma; + + struct sk_buff *rx_skb[RX_RING_SIZE]; /* where to recieve to */ + struct sk_buff *tx_skb[TX_RING_SIZE]; /* where to send from */ + bool tx_first_desc[TX_RING_SIZE]; /* true if this is the first desc of an skb */ + + int rx_next_allocate; /* index in rx ring where skb should be allocated */ + int rx_next_consume; /* index in rx ring where data should be read when available */ + int tx_next_produce; /* index in tx ring where new data should be put */ + int tx_next_deallocate; /* index in tx ring of first not freed skb */ + +#ifdef CONFIG_INET_LRO + bool use_lro; + int lro_count; + struct net_lro_mgr lro_mgr; + struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS]; + struct timer_list lro_timer; +#endif + + unsigned char running; + unsigned char resume_open; + +}; + +static inline unsigned long ip3902_read_reg(struct net_device *ndev, int reg) +{ + unsigned long value = readl((void * __iomem)(ndev->base_addr + reg)); + return value; +} + +static inline void ip3902_write_reg(struct net_device *ndev, int reg, + unsigned long val) +{ + writel(val, (void * __iomem)(ndev->base_addr + reg)); +} + +static inline void ip3902_write_tx_desc(struct ip3902_private *ip3902_priv, int pos, unsigned long address, unsigned long control) +{ +#if defined(BIG_ENDIAN_DESCRIPTORS) + ip3902_priv->ds->tx_desc[pos].address = cpu_to_be32(address); + ip3902_priv->ds->tx_desc[pos].control = cpu_to_be32(control); +#elif defined(LITTLE_ENDIAN_DESCRIPTORS) + ip3902_priv->ds->tx_desc[pos].address = cpu_to_le32(address); + ip3902_priv->ds->tx_desc[pos].control = cpu_to_le32(control); +#else + ip3902_priv->ds->tx_desc[pos].address = address; + ip3902_priv->ds->tx_desc[pos].control = control; +#endif + wmb(); +} + +static inline void ip3902_read_tx_desc(struct ip3902_private *ip3902_priv, int pos, dma_addr_t *address, int *length) +{ +#if defined(BIG_ENDIAN_DESCRIPTORS) + *address = (dma_addr_t)be32_to_cpu(ip3902_priv->ds->tx_desc[pos].address); + *length = (int)be32_to_cpu(ip3902_priv->ds->tx_desc[pos].control) & 0xffff; +#elif defined(LITTLE_ENDIAN_DESCRIPTORS) + *address = (dma_addr_t)le32_to_cpu(ip3902_priv->ds->tx_desc[pos].address); + *length = (int)le32_to_cpu(ip3902_priv->ds->tx_desc[pos].control) & 0xffff; +#else + *address = (dma_addr_t)ip3902_priv->ds->tx_desc[pos].address; + *length = (int)ip3902_priv->ds->tx_desc[pos].control & 0xffff; +#endif +} + +static inline unsigned long ip3902_read_tx_status(struct ip3902_private *ip3902_priv, int pos) +{ +#if defined(BIG_ENDIAN_STATUSES) + return be32_to_cpu(ip3902_priv->ds->tx_status[pos]); +#elif defined(LITTLE_ENDIAN_STATUSES) + return le32_to_cpu(ip3902_priv->ds->tx_status[pos]); +#else + return ip3902_priv->ds->tx_status[pos]; +#endif +} + +static inline void ip3902_write_rx_desc(struct ip3902_private *ip3902_priv, int pos, unsigned long address, unsigned long control) +{ +#if defined(BIG_ENDIAN_DESCRIPTORS) + ip3902_priv->ds->rx_desc[pos].address = cpu_to_be32(address); + ip3902_priv->ds->rx_desc[pos].control = cpu_to_be32(control); +#elif defined(LITTLE_ENDIAN_DESCRIPTORS) + ip3902_priv->ds->rx_desc[pos].address = cpu_to_le32(address); + ip3902_priv->ds->rx_desc[pos].control = cpu_to_le32(control); +#else + ip3902_priv->ds->rx_desc[pos].address = address; + ip3902_priv->ds->rx_desc[pos].control = control; +#endif + wmb(); +} + +static inline void ip3902_read_rx_desc(struct ip3902_private *ip3902_priv, int pos, dma_addr_t *address, int *length) +{ +#if defined(BIG_ENDIAN_DESCRIPTORS) + *address = (dma_addr_t)be32_to_cpu(ip3902_priv->ds->rx_desc[pos].address); + *length = (int)be32_to_cpu(ip3902_priv->ds->rx_desc[pos].control) & 0xffff; +#elif defined(LITTLE_ENDIAN_DESCRIPTORS) + *address = (dma_addr_t)le32_to_cpu(ip3902_priv->ds->rx_desc[pos].address); + *length = (int)le32_to_cpu(ip3902_priv->ds->rx_desc[pos].control) & 0xffff; +#else + *address = (dma_addr_t)ip3902_priv->ds->rx_desc[pos].address; + *length = (int)ip3902_priv->ds->rx_desc[pos].control & 0xffff; +#endif +} + +static inline unsigned long ip3902_read_rx_status(struct net_device *ndev, struct ip3902_private *ip3902_priv, int pos) +{ +#if defined(BIG_ENDIAN_STATUSES) + return be32_to_cpu(ip3902_priv->ds->rx_status[pos].status); +#elif defined(LITTLE_ENDIAN_STATUSES) + return le32_to_cpu(ip3902_priv->ds->rx_status[pos].status); +#else + return ip3902_priv->ds->rx_status[pos].status; +#endif +} + +static inline void ip3902_write_madr_reg(struct net_device *ndev, int phy_id, int location) +{ + /* assume ranges of phy_id and location are correct - we set masks in + * struct mii_if_info for that */ + + unsigned long val = (phy_id << 8) | location; + ip3902_write_reg(ndev, MADR_REG, val); +} + +static inline int ip3902_wait_mdio_op_complete(struct net_device *ndev, unsigned long mask) +{ + int timeout = 10000; /* to avoid hangup in case of unexpected badness ... */ + + while (--timeout > 0) { + if ((ip3902_read_reg(ndev, MIND_REG) & mask) == 0) + return 0; + udelay(1); + } + + return -EIO; +} + +static int ip3902_mdio_read(struct net_device *ndev, int phy_id, int location) +{ + ip3902_write_madr_reg(ndev, phy_id, location); + ip3902_write_reg(ndev, MCMD_REG, 0); + ip3902_write_reg(ndev, MCMD_REG, MCMD_READ); + if (ip3902_wait_mdio_op_complete(ndev, MIND_NOT_VALID | MIND_BUSY) < 0) + return 0; + else + return ip3902_read_reg(ndev, MRDD_REG) & 0xffff; +} + +static void ip3902_mdio_write(struct net_device *ndev, int phy_id, int location, int val) +{ + ip3902_write_madr_reg(ndev, phy_id, location); + ip3902_write_reg(ndev, MWTD_REG, val & 0xffff); + ip3902_wait_mdio_op_complete(ndev, MIND_BUSY); +} + +static inline int ip3902_nr_free_descs(int head, int tail, int size) +{ + int free; + + if (head >= tail) + free = (tail + size) - head; + else + free = tail - head; + + return free; +} + +static void ip3902_eth_rx_refill_descs(struct net_device *ndev, struct ip3902_private *ip3902_priv) +{ + do { + int rx_index = ip3902_priv->rx_next_allocate; + struct sk_buff *skb = netdev_alloc_skb(ndev, ETH_RX_SKB_SIZE + dma_get_cache_alignment()); + + if (skb) { + int unaligned = (((u32)skb->data) + ETH_HLEN) & (dma_get_cache_alignment() - 1); + unsigned long desc_address; + + if (unaligned) + skb_reserve(skb, (dma_get_cache_alignment() - unaligned)); + + desc_address = dma_map_single(NULL, skb->data, ETH_RX_SKB_SIZE, DMA_FROM_DEVICE); + ip3902_write_rx_desc(ip3902_priv, rx_index, desc_address, (ETH_RX_SKB_SIZE - 1) | RX_CONTROL_INT); + + ip3902_priv->rx_skb[rx_index] = skb; + ip3902_priv->rx_next_allocate = NEXT_RX(rx_index); + } else { + ip3902_write_reg(ndev, RX_CONSUME_INDEX_REG, ip3902_priv->rx_next_allocate); + return; + } + } while (ip3902_priv->rx_next_allocate != ip3902_priv->rx_next_consume); + + ip3902_write_reg(ndev, RX_CONSUME_INDEX_REG, ip3902_priv->rx_next_allocate); +} + +static int ip3902_eth_receive_queue(struct net_device *ndev, struct ip3902_private *ip3902_priv, int budget) +{ + int rx_index = ip3902_priv->rx_next_consume; + int write_index = ip3902_read_reg(ndev, RX_PRODUCE_INDEX_REG); + int received = 0; + int limit; + + do { + limit = write_index; + spin_lock(&ip3902_priv->lock); + while (rx_index != limit) { + unsigned long status = ip3902_read_rx_status(ndev, ip3902_priv, rx_index); + + if (!(status & RX_STATUS_LAST_FRAG)) { + printk(DRVNAME ": broken RX status: %08lx\n", status); + continue; + } + + if (status & RX_STATUS_FAIL_FILTER) + continue; + + /* Looks like hardware returns RANGE_ERROR for each frame */ + if (status & (RX_STATUS_OVERRUN | RX_STATUS_ALIGNMENT_ERROR | RX_STATUS_LENGTH_ERROR | RX_STATUS_CRC_ERROR)) { + ndev->stats.rx_errors++; + + if (status & RX_STATUS_OVERRUN) + ndev->stats.rx_fifo_errors++; + + if (status & RX_STATUS_ALIGNMENT_ERROR) + ndev->stats.rx_frame_errors++; + + if (status & (RX_STATUS_RANGE_ERROR | RX_STATUS_LENGTH_ERROR)) + ndev->stats.rx_length_errors++; + + if (status & RX_STATUS_CRC_ERROR) + ndev->stats.rx_crc_errors++; + + } else { + if (--budget < 0) { + /* we got packets, but no quota */ + /* store current ring pointer state */ + ip3902_priv->rx_next_consume = rx_index; + return received; + } else { + struct sk_buff *skb = ip3902_priv->rx_skb[rx_index]; + int length = RX_STATUS_LENGTH(status); + dma_addr_t data_addr; + int data_length; + + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += length; + if (status & RX_STATUS_MULTICAST) + ndev->stats.multicast++; + + skb_put(skb, length - BYTES_IN_ETHERNET_CRC); + skb->protocol = eth_type_trans(skb, ndev); + +#ifdef CONFIG_INET_LRO + if (ip3902_priv->use_lro) + lro_receive_skb(&ip3902_priv->lro_mgr, skb, ip3902_priv); + else + netif_receive_skb(skb); + + ip3902_priv->lro_count++; +#else +#ifdef IP3902_NAPI + netif_receive_skb(skb); +#else + netif_rx(skb); +#endif +#endif + + ip3902_read_rx_desc(ip3902_priv, rx_index, &data_addr, &data_length); + dma_unmap_single(NULL, data_addr, ETH_RX_SKB_SIZE, DMA_FROM_DEVICE); + + ip3902_priv->rx_skb[rx_index] = NULL; + ndev->last_rx = jiffies; + received++; + } + } + rx_index = NEXT_RX(rx_index); + } + + spin_unlock(&ip3902_priv->lock); + ip3902_priv->rx_next_consume = rx_index; + ip3902_eth_rx_refill_descs(ndev, ip3902_priv); + write_index = ip3902_read_reg(ndev, RX_PRODUCE_INDEX_REG); + } while (limit != write_index); + +#ifdef CONFIG_INET_LRO + if (ip3902_priv->use_lro) { + if (timer_pending(&ip3902_priv->lro_timer)) { + mod_timer(&ip3902_priv->lro_timer, jiffies + 2); + } else { + ip3902_priv->lro_timer.expires = jiffies + 2; + add_timer(&ip3902_priv->lro_timer); + } + } +#endif + + return received; +} + +#ifdef IP3902_NAPI +static int ip3902_poll(struct napi_struct *napi, int budget) +{ + struct ip3902_private *ip3902_priv = container_of(napi, struct ip3902_private, napi); + struct net_device *ndev = ip3902_priv->ndev; + int work_done; + + work_done = ip3902_eth_receive_queue(ndev, ip3902_priv, budget); + + if (work_done < budget) { + ip3902_write_reg(ndev, INT_CLEAR_REG, RX_DONE_INT); + ip3902_write_reg(ndev, INT_CLEAR_REG, 0); + netif_rx_complete(ndev, napi); + ip3902_write_reg(ndev, INT_ENABLE_REG, (TX_UNDERRUN_INT | RX_DONE_INT | RX_OVERRUN_INT)); + } + + return work_done; +} +#endif + +#ifdef CONFIG_INET_LRO +static void ip3902_lro_timeout(unsigned long data) +{ + struct ip3902_private *ip3902_priv = (struct ip3902_private *)data; + + spin_lock(&ip3902_priv->lock); + if (ip3902_priv->lro_count <= LRO_THRESHOLD) { + ip3902_priv->use_lro = false; + ip3902_priv->lro_count = 0; + } + lro_flush_all(&ip3902_priv->lro_mgr); + spin_unlock(&ip3902_priv->lock); +} +#endif + +#define ip3902_eth_free_completed_tx_descs(ndev, priv) ip3902_eth_free_tx_descs(ndev, priv, 0) +#define ip3902_eth_free_all_tx_descs(ndev, priv) ip3902_eth_free_tx_descs(ndev, priv, 1) + +static void ip3902_eth_free_tx_descs(struct net_device *ndev, struct ip3902_private *ip3902_priv, int force) +{ + int limit; + + if (force) + limit = ip3902_priv->tx_next_produce; + else + limit = ip3902_read_reg(ndev, TX_CONSUME_INDEX_REG); + + while (ip3902_priv->tx_next_deallocate != limit) { + int length; + int tx_index; + unsigned long status; + dma_addr_t addr; + struct sk_buff *skb; + + tx_index = ip3902_priv->tx_next_deallocate; + + ip3902_priv->tx_next_deallocate = NEXT_TX(tx_index); + ip3902_read_tx_desc(ip3902_priv, tx_index, &addr, &length); + skb = ip3902_priv->tx_skb[tx_index]; + + status = ip3902_read_tx_status(ip3902_priv, tx_index); + if (status & TX_STATUS_ERROR) { + ndev->stats.tx_errors++; + if (status & TX_STATUS_LATE_COLLISION) + ndev->stats.tx_aborted_errors++; + + if (status & (TX_STATUS_MANY_COLLISIONS | TX_STATUS_MANY_DEFER)) + ndev->stats.tx_window_errors++; + + } else { + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + ndev->stats.collisions += TX_STATUS_COLLISIONS(status); + } + + if (skb) + ip3902_priv->tx_skb[tx_index] = NULL; + + if (ip3902_priv->tx_first_desc[tx_index] == true) + dma_unmap_single(NULL, addr, length, DMA_TO_DEVICE); + else + dma_unmap_page(NULL, addr, length, DMA_TO_DEVICE); + + if (skb) + dev_kfree_skb_irq(skb); + } +} + +static void ip3902_reset_tx(struct net_device *ndev, struct ip3902_private *ip3902_priv, int initial) +{ + unsigned long val; + + /* Reset Tx hardware */ + val = ip3902_read_reg(ndev, COMMAND_REG); + val &= ~(COMMAND_TX_RT_ENABLE | COMMAND_TX_ENABLE); + val |= COMMAND_TX_RESET; + ip3902_write_reg(ndev, COMMAND_REG, val); + + if (!initial) + ip3902_eth_free_all_tx_descs(ndev, ip3902_priv); + + ip3902_priv->tx_next_produce = 0; + ip3902_priv->tx_next_deallocate = 0; + + /* Configure Tx registers */ + ip3902_write_reg(ndev, TX_DESC_REG, ip3902_priv->ds_dma + offsetof(struct ip3902_dma_struct, tx_desc)); + ip3902_write_reg(ndev, TX_STATUS_REG, ip3902_priv->ds_dma + offsetof(struct ip3902_dma_struct, tx_status)); + ip3902_write_reg(ndev, TX_DESC_NUMBER_REG, TX_RING_SIZE - 1); + ip3902_write_reg(ndev, TX_PRODUCE_INDEX_REG, ip3902_priv->tx_next_produce); + ip3902_write_reg(ndev, TX_CONSUME_INDEX_REG, ip3902_priv->tx_next_deallocate); +} + +static void ip3902_reset_rx(struct net_device *ndev, struct ip3902_private *ip3902_priv, int init) +{ + unsigned long val; + + /* Reset Rx hardware */ + val = ip3902_read_reg(ndev, COMMAND_REG); + val &= ~COMMAND_RX_ENABLE; + val |= COMMAND_RX_RESET; + ip3902_write_reg(ndev, COMMAND_REG, val); + + /* Set maximum frame size register */ + ip3902_write_reg(ndev, MAXF_REG, ETH_RX_SKB_SIZE); + + if (init) { + ip3902_priv->rx_next_allocate = 0; + ip3902_priv->rx_next_consume = 0; + ip3902_eth_rx_refill_descs(ndev, ip3902_priv); + } + + /* Prepare skb's for Rx (any skb's already prepared will be reused) + * and configure Rx registers */ + ip3902_write_reg(ndev, RX_DESC_REG, ip3902_priv->ds_dma + offsetof(struct ip3902_dma_struct, rx_desc)); + ip3902_write_reg(ndev, RX_STATUS_REG, ip3902_priv->ds_dma + offsetof(struct ip3902_dma_struct, rx_status)); + ip3902_write_reg(ndev, RX_DESC_NUMBER_REG, RX_RING_SIZE - 1); + ip3902_write_reg(ndev, RX_PRODUCE_INDEX_REG, ip3902_priv->rx_next_consume); +} + +static inline void ip3902_start_tx(struct net_device *ndev) +{ + unsigned long val; + + val = ip3902_read_reg(ndev, COMMAND_REG); + val |= COMMAND_TX_ENABLE; + ip3902_write_reg(ndev, COMMAND_REG, val); +} + +static inline void ip3902_start_rx(struct net_device *ndev) +{ + unsigned long val; + + /* First on high-level ... */ + val = ip3902_read_reg(ndev, COMMAND_REG); + val |= (COMMAND_RX_ENABLE | COMMAND_ALLOW_SHORT); + ip3902_write_reg(ndev, COMMAND_REG, val); + + /* ... and then on low-level (after high level is ready to receive) */ + val = ip3902_read_reg(ndev, MAC1_REG); + val |= MAC1_RECEIVE_ENABLE; /* flow control frames won't be passed to driver */ + ip3902_write_reg(ndev, MAC1_REG, val); +} + +/* Interrupt handler body - split out to use both in interrupt handler + * and in net poll controller. + * + * Internal routine, called with lock held. */ +static void ip3902_do_handle_interrupt(struct net_device *ndev, struct ip3902_private *ip3902_priv, unsigned long status) +{ + ip3902_write_reg(ndev, INT_CLEAR_REG, status); + ip3902_write_reg(ndev, INT_CLEAR_REG, 0); + + if (status & TX_UNDERRUN_INT) { + printk(KERN_ERR DRVNAME ": %s: fatal Tx underrun, resetting Tx\n", ndev->name); + ip3902_reset_tx(ndev, ip3902_priv, 0); + ip3902_start_tx(ndev); + } + + if (status & RX_OVERRUN_INT) { + printk(KERN_ERR DRVNAME ": %s: fatal Rx overrun, resetting Rx\n", ndev->name); + ip3902_reset_rx(ndev, ip3902_priv, 0); + ip3902_start_rx(ndev); + } else if (status & RX_DONE_INT) { +#ifdef IP3902_NAPI + /* Disable the Rx interrupt */ + ip3902_write_reg(ndev, INT_ENABLE_REG, (RX_OVERRUN_INT | TX_UNDERRUN_INT)); + netif_rx_schedule(ndev, &ip3902_priv->napi); +#else + ip3902_eth_receive_queue(ndev, ip3902_priv, RX_RING_SIZE); +#endif + } +} + +static irqreturn_t ip3902_interrupt(int irq, void *dev_instance) +{ + struct net_device *ndev = (struct net_device *) dev_instance; + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + unsigned long status; + + status = ip3902_read_reg(ndev, INT_STATUS_REG) & (TX_DONE_INT | TX_UNDERRUN_INT | RX_DONE_INT | RX_OVERRUN_INT); + do { + if (!status) { + return IRQ_NONE; + } else { + ip3902_do_handle_interrupt(ndev, ip3902_priv, status); + status = ip3902_read_reg(ndev, INT_STATUS_REG) & (TX_DONE_INT | TX_UNDERRUN_INT | RX_DONE_INT | RX_OVERRUN_INT); + } + } while (status); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void ip3902_net_poll(struct net_device *ndev) +{ + disable_irq_lockdep(ndev->irq); + ip3902_interrupt(ndev->irq, ndev); + enable_irq_lockdep(ndev->irq); +} +#endif + +static int eth_alloc_tx_desc_index(struct ip3902_private *ip3902_priv) +{ + int tx_desc_curr; + + tx_desc_curr = ip3902_priv->tx_next_produce; + ip3902_priv->tx_next_produce = NEXT_TX(tx_desc_curr); + + return tx_desc_curr; +} + +static void eth_tx_fill_frag_descs(struct ip3902_private *ip3902_priv, struct sk_buff *skb) +{ + int frag = 0; + int tx_index; + + do { + skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; + unsigned long desc_address; + unsigned long desc_control; + + tx_index = eth_alloc_tx_desc_index(ip3902_priv); + + if (frag == (skb_shinfo(skb)->nr_frags - 1)) { + desc_control = (this_frag->size - 1) | TX_CONTROL_ALL_NOTLAST; + ip3902_priv->tx_skb[tx_index] = skb; + } else { + desc_control = (this_frag->size - 1) | TX_CONTROL_ALL_LAST; + ip3902_priv->tx_skb[tx_index] = NULL; + } + + ip3902_priv->tx_first_desc[tx_index] = false; + desc_address = dma_map_page(NULL, this_frag->page, + this_frag->page_offset, + this_frag->size, + DMA_TO_DEVICE); + ip3902_write_tx_desc(ip3902_priv, tx_index, desc_address, desc_control); + } while (++frag < skb_shinfo(skb)->nr_frags); +} + +static int ip3902_submit_skb_for_tx(struct net_device *ndev, struct sk_buff *skb) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + int nr_frags; + int free_desc; + int ret = 0; + +#ifdef CONFIG_INET_LRO + if (ip3902_priv->lro_count > LRO_THRESHOLD) + ip3902_priv->use_lro = true; + + ip3902_priv->lro_count = 0; +#endif + + free_desc = ip3902_nr_free_descs(ip3902_priv->tx_next_produce, ip3902_priv->tx_next_deallocate, TX_RING_SIZE); + nr_frags = skb_shinfo(skb)->nr_frags; + + if (free_desc <= nr_frags) { + ip3902_eth_free_completed_tx_descs(ndev, ip3902_priv); + free_desc = ip3902_nr_free_descs(ip3902_priv->tx_next_produce, ip3902_priv->tx_next_deallocate, TX_RING_SIZE); + } + + if (free_desc > nr_frags) { + unsigned long desc_address; + unsigned long desc_control; + int tx_index; + int length; + + tx_index = eth_alloc_tx_desc_index(ip3902_priv); + + if (nr_frags) { + eth_tx_fill_frag_descs(ip3902_priv, skb); + length = skb_headlen(skb); + desc_control = (length - 1) | TX_CONTROL_ALL_NOTLAST; + ip3902_priv->tx_skb[tx_index] = NULL; + } else { + length = skb->len; + desc_control = (length - 1) | TX_CONTROL_ALL_LAST; + ip3902_priv->tx_skb[tx_index] = skb; + } + + ip3902_priv->tx_first_desc[tx_index] = true; + desc_address = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + + ip3902_write_tx_desc(ip3902_priv, tx_index, desc_address, desc_control); + ip3902_write_reg(ndev, TX_PRODUCE_INDEX_REG, ip3902_priv->tx_next_produce); + ip3902_eth_free_completed_tx_descs(ndev, ip3902_priv); + } else { + ret = -ENOMEM; + } + + return ret; +} + +static int ip3902_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + int ret; + + BUG_ON(netif_queue_stopped(ndev)); + BUG_ON(skb == NULL); + ret = ip3902_submit_skb_for_tx(ndev, skb); + + if (ret) { + printk(KERN_ERR "%s: transmit with queue full\n", ndev->name); + netif_stop_queue(ndev); + } else { + ndev->stats.tx_bytes += skb->len; + ndev->stats.tx_packets++; + ndev->trans_start = jiffies; + } + + return ret; /* success */ +} + +static void ip3902_do_set_rx_filter(struct net_device *ndev, struct ip3902_private *ip3902_priv) +{ + unsigned long creg, freg; + + creg = ip3902_read_reg(ndev, COMMAND_REG); + if (ndev->flags & IFF_PROMISC) { + /* If interface is in promiscuous mode, just disable filter */ + ip3902_write_reg(ndev, COMMAND_REG, creg | COMMAND_PROMISC); + return; + } + /* Enable filter */ + ip3902_write_reg(ndev, COMMAND_REG, creg & ~COMMAND_PROMISC); + + /* Frames for self address and broadcast frames are always accepted */ + freg = FILTER_ACCEPT_SELF | FILTER_ACCEPT_BCAST_ANY; + + if (ndev->flags & IFF_ALLMULTI) { + /* Accept all multicast frames */ + freg |= FILTER_ACCEPT_MCAST_ANY; + } else if (ndev->mc_count > 0) { + /* Accept some multicast frames */ + u64 hash_mask = 0; + struct dev_mc_list *mc; + + freg |= FILTER_ACCEPT_MCAST_HASH; + for (mc = ndev->mc_list; mc; mc = mc->next) { + int b = (ether_crc(ETH_ALEN, mc->dmi_addr) >> 23) & 0x3f; + hash_mask |= (1 << b); + } + ip3902_write_reg(ndev, HASH_FILTER_L_REG, hash_mask & 0xffffffff); + ip3902_write_reg(ndev, HASH_FILTER_H_REG, hash_mask >> 32); + } + + ip3902_write_reg(ndev, FILTER_CTRL_REG, freg); +} + +static void ip3902_set_rx_filter(struct net_device *ndev) +{ + struct ip3902_private *ip3902_priv = (struct ip3902_private *)netdev_priv(ndev); + + ip3902_do_set_rx_filter(ndev, ip3902_priv); +} + +static void set_duplex_mode(struct net_device *ndev, int duplex) +{ + unsigned long val; + + if (duplex) { + /* Full Duplex mode */ + + val = ip3902_read_reg(ndev, MAC2_REG); + val |= MAC2_FULL_DUPLEX; + ip3902_write_reg(ndev, MAC2_REG, val); + + ip3902_write_reg(ndev, IPGT_REG, IPGT_FD_VALUE); + + val = ip3902_read_reg(ndev, COMMAND_REG); + val |= COMMAND_FULL_DUPLEX; + ip3902_write_reg(ndev, COMMAND_REG, val); + } else { + /* Half Duplex mode */ + + val = ip3902_read_reg(ndev, MAC2_REG); + val &= ~MAC2_FULL_DUPLEX; + ip3902_write_reg(ndev, MAC2_REG, val); + + ip3902_write_reg(ndev, IPGT_REG, IPGT_HD_VALUE); + + val = ip3902_read_reg(ndev, COMMAND_REG); + val &= ~COMMAND_FULL_DUPLEX; + ip3902_write_reg(ndev, COMMAND_REG, val); + } +} + +static int ip3902_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + unsigned int duplex_changed; + unsigned long flags; + int rc; + + if (!netif_running(ndev)) + return -EINVAL; + + spin_lock_irqsave(&ip3902_priv->mii_lock, flags); + rc = generic_mii_ioctl(&ip3902_priv->mii, if_mii(req), cmd, &duplex_changed); + spin_unlock_irqrestore(&ip3902_priv->mii_lock, flags); + if (duplex_changed) + set_duplex_mode(ndev, ip3902_priv->mii.full_duplex); + + return rc; +} + +/* ethtool ops */ + +static void ip3902_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *info) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + + strcpy(info->driver, DRVNAME); + strcpy(info->version, DRVVERSION); + strcpy(info->bus_info, ip3902_priv->ndev->name); +} + +static int ip3902_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + unsigned long flags; + + spin_lock_irqsave(&ip3902_priv->mii_lock, flags); + mii_ethtool_gset(&ip3902_priv->mii, cmd); + spin_lock_irqsave(&ip3902_priv->mii_lock, flags); + + return 0; +} + +static int ip3902_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + unsigned long flags; + int rc; + + spin_lock_irqsave(&ip3902_priv->mii_lock, flags); + rc = mii_ethtool_sset(&ip3902_priv->mii, cmd); + spin_lock_irqsave(&ip3902_priv->mii_lock, flags); + + return rc; +} + +static int ip3902_nway_reset(struct net_device *ndev) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + return mii_nway_restart(&ip3902_priv->mii); +} + +static u32 ip3902_get_link(struct net_device *ndev) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + return mii_link_ok(&ip3902_priv->mii); +} + +static const struct ethtool_ops ip3902_ethtool_ops = { + .get_drvinfo = ip3902_get_drvinfo, + .get_settings = ip3902_get_settings, + .set_settings = ip3902_set_settings, + .nway_reset = ip3902_nway_reset, + .get_link = ip3902_get_link, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +}; + +/* setup code */ + +static void ip3902_eth_update_mac_address(struct net_device *ndev) +{ + ip3902_write_reg(ndev, SA0_REG, (ndev->dev_addr[5] << 8) | ndev->dev_addr[4]); + ip3902_write_reg(ndev, SA1_REG, (ndev->dev_addr[3] << 8) | ndev->dev_addr[2]); + ip3902_write_reg(ndev, SA2_REG, (ndev->dev_addr[1] << 8) | ndev->dev_addr[0]); +} + +static int ip3902_eth_set_mac_address(struct net_device *ndev, void *addr) +{ + int i; + + for (i = 0; i < 6; i++) + /* +2 is for the offset of the HW addr type */ + ndev->dev_addr[i] = ((unsigned char *)addr)[i + 2]; + + ip3902_eth_update_mac_address(ndev); + return 0; +} + +static void ip3902_hw_deinit(struct net_device *ndev) +{ + unsigned long val; + + /* Stop Rx and Tx hardware and disable interrupts */ + val = ip3902_read_reg(ndev, COMMAND_REG); + val &= ~(COMMAND_TX_ENABLE | COMMAND_RX_ENABLE); + ip3902_write_reg(ndev, COMMAND_REG, val); + ip3902_write_reg(ndev, INT_ENABLE_REG, 0); + + /* Put low-level hardware into reset, and high-level into poweroff */ + ip3902_write_reg(ndev, MAC1_REG, MAC1_SOFT_RESET); + ip3902_write_reg(ndev, POWERDOWN_REG, POWERDOWN_VALUE); +} + +static int ethernet_phy_get(struct net_device *ndev) +{ + int addr; + + for (addr = 1; addr < 32; addr++) { + int stat; + stat = ip3902_mdio_read(ndev, addr, MII_BMSR); + if ((stat != 0) && (stat != 0xffff)) + return addr; + } + printk(KERN_ERR DRVNAME ": could not locate PHY\n"); + return -EIO; +} + +static int ip3902_hw_init(struct net_device *ndev, struct ip3902_private *ip3902_priv) +{ + int ret = 0; + + /* Poweron hardware */ + ip3902_write_reg(ndev, POWERDOWN_REG, 0); + + /* Move low level out of reset (also initialize the registers)*/ + ip3902_write_reg(ndev, MAC1_REG, 0); + ip3902_write_reg(ndev, MAC2_REG, INITIAL_MAC2); + + ip3902_priv->mii.phy_id = ethernet_phy_get(ndev); + + if (ip3902_priv->mii.phy_id < 0) { + ret = ip3902_priv->mii.phy_id; + } else { + ip3902_eth_update_mac_address(ndev); + + /* "Initialize" command register (before resets - those routines + * use read-modify-write operations on that register */ + ip3902_write_reg(ndev, COMMAND_REG, COMMAND_ALLOW_SHORT); + + /* Reset and configure Rx and Tx */ + ip3902_reset_tx(ndev, ip3902_priv, 1); + ip3902_reset_rx(ndev, ip3902_priv, 1); + + /* Initialize Rx filtering */ + ip3902_do_set_rx_filter(ndev, ip3902_priv); + + /* Clear all interrupts, and enable interesting interrupts */ + ip3902_write_reg(ndev, INT_CLEAR_REG, 0xffffffff); + ip3902_write_reg(ndev, INT_CLEAR_REG, 0); + ip3902_write_reg(ndev, INT_ENABLE_REG, (TX_UNDERRUN_INT | RX_DONE_INT | RX_OVERRUN_INT)); + + /* Start Tx and Rx hardware */ + ip3902_start_tx(ndev); + ip3902_start_rx(ndev); + } + return 0; +} + +static int ip3902_open(struct net_device *ndev) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + int ret; + + dev_dbg(&ip3902_priv->ndev->dev, "%s: open\n", ndev->name); + + ret = request_irq(ndev->irq, ip3902_interrupt, 0, ndev->name, ndev); + if (ret) + return ret; + + ret = ip3902_hw_init(ndev, ip3902_priv); + + if (ret) + return ret; + + mii_check_media(&ip3902_priv->mii, netif_msg_link(ip3902_priv), 1); + set_duplex_mode(ndev, ip3902_priv->mii.full_duplex); + +#ifdef CONFIG_INET_LRO + init_timer(&ip3902_priv->lro_timer); + ip3902_priv->lro_timer.data = (unsigned long) ip3902_priv; + ip3902_priv->lro_timer.function = ip3902_lro_timeout; +#endif + + netif_start_queue(ndev); + +#ifdef IP3902_NAPI + napi_enable(&ip3902_priv->napi); +#endif + + ip3902_priv->running = 1; + + return 0; +} + +static int ip3902_close(struct net_device *ndev) +{ + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + + dev_dbg(&ip3902_priv->ndev->dev, "%s: close\n", ndev->name); + + ip3902_priv->running = 0; + wmb(); + +#ifdef CONFIG_INET_LRO + del_timer(&ip3902_priv->lro_timer); +#endif + +#ifdef IP3902_NAPI + napi_disable(&ip3902_priv->napi); +#endif + + ip3902_hw_deinit(ndev); + + netif_stop_queue(ndev); + + ip3902_eth_free_all_tx_descs(ndev, ip3902_priv); + + free_irq(ndev->irq, ndev); + return 0; +} + +static int parse_mac_address(struct net_device *ndev) +{ + int n = sscanf(mac_address, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &ndev->dev_addr[0], &ndev->dev_addr[1], + &ndev->dev_addr[2], &ndev->dev_addr[3], + &ndev->dev_addr[4], &ndev->dev_addr[5]); + + if (n == 6) + return 0; + + printk(KERN_WARNING DRVNAME": failed to parse mac address string \"%s\"\n", mac_address); + return -EINVAL; +} + +static void ip3902_hw_shutdown(struct net_device *ndev, struct ip3902_private *ip3902_priv) +{ + dma_free_coherent(NULL, sizeof(*(ip3902_priv->ds)), ip3902_priv->ds, ip3902_priv->ds_dma); +} + +static int ip3902_hw_startup(struct net_device *ndev, struct ip3902_private *ip3902_priv) +{ + ip3902_priv->ds = dma_alloc_coherent(NULL, sizeof(*(ip3902_priv->ds)), &ip3902_priv->ds_dma, GFP_KERNEL); + if (!ip3902_priv->ds) { + printk(KERN_ERR DRVNAME ": can't allocate DMA structure\n"); + ip3902_hw_shutdown(ndev, ip3902_priv); + return -ENOMEM; + } + + /* Poweron hardware */ + ip3902_write_reg(ndev, POWERDOWN_REG, 0); + + /* set mii clock */ + ip3902_write_reg(ndev, MCFG_REG, 0x1c); + + /* Move low level out of reset (also initialize the registers)*/ + ip3902_write_reg(ndev, MAC1_REG, 0); + ip3902_write_reg(ndev, MAC2_REG, INITIAL_MAC2); + + if (!mac_address || parse_mac_address(ndev) < 0) { + unsigned long val; + + val = ip3902_read_reg(ndev, SA0_REG); + ndev->dev_addr[5] = (val >> 8) & 255; + ndev->dev_addr[4] = val & 255; + val = ip3902_read_reg(ndev, SA1_REG); + ndev->dev_addr[3] = (val >> 8) & 255; + ndev->dev_addr[2] = val & 255; + val = ip3902_read_reg(ndev, SA2_REG); + ndev->dev_addr[1] = (val >> 8) & 255; + ndev->dev_addr[0] = val & 255; + } + + /* Put low-level hardware into reset, and high-level into poweroff */ + ip3902_write_reg(ndev, MAC1_REG, MAC1_SOFT_RESET); + ip3902_write_reg(ndev, POWERDOWN_REG, POWERDOWN_VALUE); + + return 0; +} + +static int ip3902_init_dev(struct net_device *ndev, struct ip3902_private *ip3902_priv) +{ + int ret; + + ret = ip3902_hw_startup(ndev, ip3902_priv); + + if (!ret) { + ndev->hard_start_xmit = ip3902_start_xmit; + ndev->set_mac_address = ip3902_eth_set_mac_address; + ndev->set_multicast_list = ip3902_set_rx_filter; + ndev->open = ip3902_open; + ndev->stop = ip3902_close; + ndev->do_ioctl = ip3902_ioctl; + ndev->features = 0; +#ifdef CONFIG_NET_POLL_CONTROLLER + ndev->poll_controller = ip3902_net_poll; +#endif + SET_ETHTOOL_OPS(ndev, &ip3902_ethtool_ops); + + ip3902_priv->msg_enable = NETIF_MSG_LINK; + ip3902_priv->mii.phy_id_mask = 0x1f; + ip3902_priv->mii.reg_num_mask = 0x1f; + ip3902_priv->mii.mdio_read = ip3902_mdio_read; + ip3902_priv->mii.mdio_write = ip3902_mdio_write; + ip3902_priv->mii.dev = ndev; + + spin_lock_init(&ip3902_priv->lock); + + ret = register_netdev(ndev); + + if (ret) + ip3902_hw_shutdown(ndev, ip3902_priv); + } + + return ret; +} + +#ifdef CONFIG_INET_LRO +static int ip3902_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph, u64 *hdr_flags, void *priv) +{ + unsigned int ip_len; + struct iphdr *iph; + + /* non tcp packet */ + skb_reset_network_header(skb); + iph = ip_hdr(skb); + if (iph->protocol != IPPROTO_TCP) + return -1; + + ip_len = ip_hdrlen(skb); + skb_set_transport_header(skb, ip_len); + *tcph = tcp_hdr(skb); + + /* check if ip header and tcp header are complete */ + if (iph->tot_len < ip_len + tcp_hdrlen(skb)) + return -1; + + *hdr_flags = LRO_IPV4 | LRO_TCP; + *iphdr = iph; + + return 0; +} +#endif + +static int ip3902_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + + iounmap(ip3902_priv->mem); + release_resource(ip3902_priv->bus); + kfree(ip3902_priv->bus); + + free_netdev(ndev); + + return 0; +} + +/* ip3902_probe + * + * This is the entry point when the platform device system uses to + * notify us of a new device to attach to. Allocate memory, find + * the resources and information passed, and map the necessary registers. +*/ + +static int ip3902_probe(struct platform_device *pdev) +{ + struct net_device *ndev; + struct ip3902_private *ip3902_priv; + struct resource *res; + size_t size; + int ret; + + ndev = alloc_etherdev(sizeof(struct ip3902_private)); + + if (ndev == NULL) + return -ENOMEM; + + ip3902_priv = netdev_priv(ndev); + + memset(ip3902_priv, 0, sizeof(struct ip3902_private)); + + spin_lock_init(&ip3902_priv->mii_lock); + + ip3902_priv->ndev = ndev; + ip3902_priv->pdev = pdev; + +#ifdef IP3902_NAPI + netif_napi_add(ndev, &ip3902_priv->napi, ip3902_poll, IP3902_NAPI_WEIGHT); +#endif + +#ifdef CONFIG_INET_LRO + ip3902_priv->use_lro = false; + ip3902_priv->lro_count = 0; + ip3902_priv->lro_mgr.max_aggr = IP3902_NAPI_WEIGHT; + ip3902_priv->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; + ip3902_priv->lro_mgr.lro_arr = ip3902_priv->lro_desc; + ip3902_priv->lro_mgr.get_skb_header = ip3902_get_skb_hdr; +#ifdef IP3902_NAPI + ip3902_priv->lro_mgr.features = LRO_F_NAPI; +#else + ip3902_priv->lro_mgr.features = 0; +#endif + ip3902_priv->lro_mgr.dev = ndev; + ip3902_priv->lro_mgr.ip_summed = 0; + ip3902_priv->lro_mgr.ip_summed_aggr = 0; +#endif + + platform_set_drvdata(pdev, ndev); + + /* find the platform resources */ + ndev->irq = platform_get_irq(pdev, 0); + if (ndev->irq < 0) { + dev_err(&pdev->dev, "no IRQ specified\n"); + ret = -ENXIO; + goto exit_mem; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no MEM specified\n"); + ret = -ENXIO; + goto exit_mem; + } + size = (res->end - res->start) + 1; + + ip3902_priv->bus = request_mem_region(res->start & 0x1fffffff, size, pdev->name); + if (ip3902_priv->bus == NULL) { + dev_err(&pdev->dev, "cannot reserve registers\n"); + ret = -ENXIO; + goto exit_mem; + } + + ip3902_priv->mem = ioremap(res->start & 0x1fffffff, size); + ndev->base_addr = (unsigned long)ip3902_priv->mem; + + if (ip3902_priv->mem == NULL) { + dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n", + (unsigned long long)res->start, + (unsigned long long)res->end); + + ret = -ENXIO; + goto exit_req; + } + + SET_NETDEV_DEV(ndev, &pdev->dev); + + /* got resources, now initialise and register device */ + ret = ip3902_init_dev(ndev, ip3902_priv); + if (!ret) { + printk(KERN_INFO "NXP ip3902 10/100 Ethernet platform driver irq %d base %08lx\n", ndev->irq, ndev->base_addr); + return 0; + } + +exit_req: + release_resource(ip3902_priv->bus); + kfree(ip3902_priv->bus); + +exit_mem: + free_netdev(ndev); + + return ret; +} + +/* suspend and resume */ + +#ifdef CONFIG_PM +static int ip3902_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + + ip3902_priv->resume_open = ip3902_priv->running; + + netif_device_detach(ndev); + ip3902_close(ndev); + + return 0; +} + +static int ip3902_resume(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct ip3902_private *ip3902_priv = netdev_priv(ndev); + + netif_device_attach(ndev); + + if (ip3902_priv->resume_open) + ip3902_open(ndev); + + return 0; +} + +#else + #define ip3902_suspend NULL + #define ip3902_resume NULL +#endif + +static struct platform_driver ip3902drv = { + .driver = { + .name = "ip3902-eth", + .owner = THIS_MODULE, + }, + .probe = ip3902_probe, + .remove = ip3902_remove, + .suspend = ip3902_suspend, + .resume = ip3902_resume, +}; + +static int __init ip3902drv_init(void) +{ + return platform_driver_register(&ip3902drv); +} + +static void __exit ip3902drv_exit(void) +{ + platform_driver_unregister(&ip3902drv); +} + +module_init(ip3902drv_init); +module_exit(ip3902drv_exit); + +MODULE_DESCRIPTION("NXP IP3902 10/100 Ethernet platform driver"); +MODULE_AUTHOR("Chris Steel, <chris.steel@xxxxxxx>"); +MODULE_LICENSE("GPL v2"); diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/net/Kconfig linux-2.6.26-rc4/drivers/net/Kconfig --- linux-2.6.26-rc4.orig/drivers/net/Kconfig 2008-06-03 10:56:55.000000000 +0100 +++ linux-2.6.26-rc4/drivers/net/Kconfig 2008-06-03 17:16:59.000000000 +0100 @@ -1884,6 +1884,15 @@ Say Y here if you want to use the NE2000 compatible controller on the Renesas H8/300 processor. +config IP3902 + tristate "NXP IP3902 ethernet hardware support" + depends on SOC_PNX8335 && NET_ETHERNET + select MII + select CRC32 + help + This is a driver for NXP IP3902 ethernet hardware found + in PNX8335 and probably other SOCs. + source "drivers/net/fec_8xx/Kconfig" source "drivers/net/fs_enet/Kconfig" diff -urN --exclude=.svn linux-2.6.26-rc4.orig/drivers/net/Makefile linux-2.6.26-rc4/drivers/net/Makefile --- linux-2.6.26-rc4.orig/drivers/net/Makefile 2008-06-03 10:56:55.000000000 +0100 +++ linux-2.6.26-rc4/drivers/net/Makefile 2008-06-03 17:17:11.000000000 +0100 @@ -122,6 +122,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_NE_H8300) += ne-h8300.o obj-$(CONFIG_AX88796) += ax88796.o +obj-$(CONFIG_IP3902) += ip3902.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/gpio.h linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/gpio.h --- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/gpio.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/gpio.h 2008-06-05 11:07:19.000000000 +0100 @@ -0,0 +1,171 @@ +/* + * gpio.h: GPIO Support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __ASM_MIPS_MACH_PNX833X_GPIO_H +#define __ASM_MIPS_MACH_PNX833X_GPIO_H + +/* BIG FAT WARNING: races danger! + No protections exist here. Current users are only early init code, + when locking is not needed because no cuncurency yet exists there, + and GPIO IRQ dispatcher, which does locking. + However, if many uses will ever happen, proper locking will be needed + - including locking between different uses +*/ + +#include "pnx833x.h" + +#define SET_REG_BIT(reg, bit) reg |= (1 << (bit)) +#define CLEAR_REG_BIT(reg, bit) reg &= ~(1 << (bit)) + +/* Initialize GPIO to a known state */ +static inline void gpio_init(void) +{ + PNX833X_PIO_DIR = 0; + PNX833X_PIO_DIR2 = 0; + PNX833X_PIO_SEL = 0; + PNX833X_PIO_SEL2 = 0; + PNX833X_PIO_INT_EDGE = 0; + PNX833X_PIO_INT_HI = 0; + PNX833X_PIO_INT_LO = 0; + + /* clear any GPIO interrupt requests */ + PNX833X_PIO_INT_CLEAR = 0xffff; + PNX833X_PIO_INT_CLEAR = 0; + PNX833X_PIO_INT_ENABLE = 0; +} + +/* Select GPIO direction for a pin */ +static inline void gpio_select_input(unsigned int pin) +{ + if (pin < 32) + CLEAR_REG_BIT(PNX833X_PIO_DIR, pin); + else + CLEAR_REG_BIT(PNX833X_PIO_DIR2, pin & 31); +} +static inline void gpio_select_output(unsigned int pin) +{ + if (pin < 32) + SET_REG_BIT(PNX833X_PIO_DIR, pin); + else + SET_REG_BIT(PNX833X_PIO_DIR2, pin & 31); +} + +/* Select GPIO or alternate function for a pin */ +static inline void gpio_select_function_io(unsigned int pin) +{ + if (pin < 32) + CLEAR_REG_BIT(PNX833X_PIO_SEL, pin); + else + CLEAR_REG_BIT(PNX833X_PIO_SEL2, pin & 31); +} +static inline void gpio_select_function_alt(unsigned int pin) +{ + if (pin < 32) + SET_REG_BIT(PNX833X_PIO_SEL, pin); + else + SET_REG_BIT(PNX833X_PIO_SEL2, pin & 31); +} + +/* Read GPIO pin */ +static inline int gpio_read(unsigned int pin) +{ + if (pin < 32) + return(PNX833X_PIO_IN >> pin) & 1; + else + return(PNX833X_PIO_IN2 >> (pin & 31)) & 1; +} + +/* Write GPIO pin */ +static inline void gpio_write(unsigned int val, unsigned int pin) +{ + if (pin < 32) { + if (val) + SET_REG_BIT(PNX833X_PIO_OUT, pin); + else + CLEAR_REG_BIT(PNX833X_PIO_OUT, pin); + } else { + if (val) + SET_REG_BIT(PNX833X_PIO_OUT2, pin & 31); + else + CLEAR_REG_BIT(PNX833X_PIO_OUT2, pin & 31); + } +} + +/* Configure GPIO interrupt */ +#define GPIO_INT_NONE 0 +#define GPIO_INT_LEVEL_LOW 1 +#define GPIO_INT_LEVEL_HIGH 2 +#define GPIO_INT_EDGE_RISING 3 +#define GPIO_INT_EDGE_FALLING 4 +#define GPIO_INT_EDGE_BOTH 5 +static inline void gpio_setup_irq(int when, unsigned int pin) +{ + switch (when) { + case GPIO_INT_LEVEL_LOW: + CLEAR_REG_BIT(PNX833X_PIO_INT_EDGE, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_HI, pin); + SET_REG_BIT(PNX833X_PIO_INT_LO, pin); + break; + case GPIO_INT_LEVEL_HIGH: + CLEAR_REG_BIT(PNX833X_PIO_INT_EDGE, pin); + SET_REG_BIT(PNX833X_PIO_INT_HI, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_LO, pin); + break; + case GPIO_INT_EDGE_RISING: + SET_REG_BIT(PNX833X_PIO_INT_EDGE, pin); + SET_REG_BIT(PNX833X_PIO_INT_HI, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_LO, pin); + break; + case GPIO_INT_EDGE_FALLING: + SET_REG_BIT(PNX833X_PIO_INT_EDGE, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_HI, pin); + SET_REG_BIT(PNX833X_PIO_INT_LO, pin); + break; + case GPIO_INT_EDGE_BOTH: + SET_REG_BIT(PNX833X_PIO_INT_EDGE, pin); + SET_REG_BIT(PNX833X_PIO_INT_HI, pin); + SET_REG_BIT(PNX833X_PIO_INT_LO, pin); + break; + default: + CLEAR_REG_BIT(PNX833X_PIO_INT_EDGE, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_HI, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_LO, pin); + break; + } +} + +/* Enable/disable GPIO interrupt */ +static inline void gpio_enable_irq(unsigned int pin) +{ + SET_REG_BIT(PNX833X_PIO_INT_ENABLE, pin); +} +static inline void gpio_disable_irq(unsigned int pin) +{ + CLEAR_REG_BIT(PNX833X_PIO_INT_ENABLE, pin); +} + +/* Clear GPIO interrupt request */ +static inline void gpio_clear_irq(unsigned int pin) +{ + SET_REG_BIT(PNX833X_PIO_INT_CLEAR, pin); + CLEAR_REG_BIT(PNX833X_PIO_INT_CLEAR, pin); +} + +#endif diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/irq.h linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/irq.h --- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/irq.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/irq.h 2008-06-05 10:28:19.000000000 +0100 @@ -0,0 +1,138 @@ +/* + * irq.h: IRQ mappings for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_MIPS_MACH_PNX833X_IRQ_H +#define __ASM_MIPS_MACH_PNX833X_IRQ_H +/* + * The "IRQ numbers" are completely virtual. + * + * In PNX8330/1, we have 48 interrupt lines, numbered from 1 to 48. + * Let's use numbers 1..48 for PIC interrupts, number 0 for timer interrupt, + * numbers 49..64 for (virtual) GPIO interrupts. + * + * In PNX8335, we have 57 interrupt lines, numbered from 1 to 57, + * connected to PIC, which uses core hardware interrupt 2, and also + * a timer interrupt through hardware interrupt 5. + * Let's use numbers 1..64 for PIC interrupts, number 0 for timer interrupt, + * numbers 65..80 for (virtual) GPIO interrupts. + * + */ + +#if defined(CONFIG_SOC_PNX8335) + #define PNX833X_PIC_NUM_IRQ 58 +#else + #define PNX833X_PIC_NUM_IRQ 37 +#endif + +#define MIPS_CPU_NUM_IRQ 8 +#define PNX833X_GPIO_NUM_IRQ 16 + +#define MIPS_CPU_IRQ_BASE 0 +#define PNX833X_PIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + MIPS_CPU_NUM_IRQ) +#define PNX833X_GPIO_IRQ_BASE (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ) +#define NR_IRQS (MIPS_CPU_NUM_IRQ + PNX833X_PIC_NUM_IRQ + PNX833X_GPIO_NUM_IRQ) + + +#define PNX833X_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) + +/* Interrupts supported by PIC */ +#define PNX833X_PIC_I2C0_INT (PNX833X_PIC_IRQ_BASE + 1) +#define PNX833X_PIC_I2C1_INT (PNX833X_PIC_IRQ_BASE + 2) +#define PNX833X_PIC_UART0_INT (PNX833X_PIC_IRQ_BASE + 3) +#define PNX833X_PIC_UART1_INT (PNX833X_PIC_IRQ_BASE + 4) +#define PNX833X_PIC_TS_IN0_DV_INT (PNX833X_PIC_IRQ_BASE + 5) +#define PNX833X_PIC_TS_IN0_DMA_INT (PNX833X_PIC_IRQ_BASE + 6) +#define PNX833X_PIC_GPIO_INT (PNX833X_PIC_IRQ_BASE + 7) +#define PNX833X_PIC_AUDIO_DEC_INT (PNX833X_PIC_IRQ_BASE + 8) +#define PNX833X_PIC_VIDEO_DEC_INT (PNX833X_PIC_IRQ_BASE + 9) +#define PNX833X_PIC_CONFIG_INT (PNX833X_PIC_IRQ_BASE + 10) +#define PNX833X_PIC_AOI_INT (PNX833X_PIC_IRQ_BASE + 11) +#define PNX833X_PIC_SYNC_INT (PNX833X_PIC_IRQ_BASE + 12) +#define PNX8330_PIC_SPU_INT (PNX833X_PIC_IRQ_BASE + 13) +#define PNX8335_PIC_SATA_INT (PNX833X_PIC_IRQ_BASE + 13) +#define PNX833X_PIC_OSD_INT (PNX833X_PIC_IRQ_BASE + 14) +#define PNX833X_PIC_DISP1_INT (PNX833X_PIC_IRQ_BASE + 15) +#define PNX833X_PIC_DEINTERLACER_INT (PNX833X_PIC_IRQ_BASE + 16) +#define PNX833X_PIC_DISPLAY2_INT (PNX833X_PIC_IRQ_BASE + 17) +#define PNX833X_PIC_VC_INT (PNX833X_PIC_IRQ_BASE + 18) +#define PNX833X_PIC_SC_INT (PNX833X_PIC_IRQ_BASE + 19) +#define PNX833X_PIC_IDE_INT (PNX833X_PIC_IRQ_BASE + 20) +#define PNX833X_PIC_IDE_DMA_INT (PNX833X_PIC_IRQ_BASE + 21) +#define PNX833X_PIC_TS_IN1_DV_INT (PNX833X_PIC_IRQ_BASE + 22) +#define PNX833X_PIC_TS_IN1_DMA_INT (PNX833X_PIC_IRQ_BASE + 23) +#define PNX833X_PIC_SGDX_DMA_INT (PNX833X_PIC_IRQ_BASE + 24) +#define PNX833X_PIC_TS_OUT_INT (PNX833X_PIC_IRQ_BASE + 25) +#define PNX833X_PIC_IR_INT (PNX833X_PIC_IRQ_BASE + 26) +#define PNX833X_PIC_VMSP1_INT (PNX833X_PIC_IRQ_BASE + 27) +#define PNX833X_PIC_VMSP2_INT (PNX833X_PIC_IRQ_BASE + 28) +#define PNX833X_PIC_PIBC_INT (PNX833X_PIC_IRQ_BASE + 29) +#define PNX833X_PIC_TS_IN0_TRD_INT (PNX833X_PIC_IRQ_BASE + 30) +#define PNX833X_PIC_SGDX_TPD_INT (PNX833X_PIC_IRQ_BASE + 31) +#define PNX833X_PIC_USB_INT (PNX833X_PIC_IRQ_BASE + 32) +#define PNX833X_PIC_TS_IN1_TRD_INT (PNX833X_PIC_IRQ_BASE + 33) +#define PNX833X_PIC_CLOCK_INT (PNX833X_PIC_IRQ_BASE + 34) +#define PNX833X_PIC_SGDX_PARSER_INT (PNX833X_PIC_IRQ_BASE + 35) +#define PNX833X_PIC_VMSP_DMA_INT (PNX833X_PIC_IRQ_BASE + 36) + +#if defined(CONFIG_SOC_PNX8335) +#define PNX8335_PIC_MIU_INT (PNX833X_PIC_IRQ_BASE + 37) +#define PNX8335_PIC_AVCHIP_IRQ_INT (PNX833X_PIC_IRQ_BASE + 38) +#define PNX8335_PIC_SYNC_HD_INT (PNX833X_PIC_IRQ_BASE + 39) +#define PNX8335_PIC_DISP_HD_INT (PNX833X_PIC_IRQ_BASE + 40) +#define PNX8335_PIC_DISP_SCALER_INT (PNX833X_PIC_IRQ_BASE + 41) +#define PNX8335_PIC_OSD_HD1_INT (PNX833X_PIC_IRQ_BASE + 42) +#define PNX8335_PIC_DTL_WRITER_Y_INT (PNX833X_PIC_IRQ_BASE + 43) +#define PNX8335_PIC_DTL_WRITER_C_INT (PNX833X_PIC_IRQ_BASE + 44) +#define PNX8335_PIC_DTL_EMULATOR_Y_IR_INT (PNX833X_PIC_IRQ_BASE + 45) +#define PNX8335_PIC_DTL_EMULATOR_C_IR_INT (PNX833X_PIC_IRQ_BASE + 46) +#define PNX8335_PIC_DENC_TTX_INT (PNX833X_PIC_IRQ_BASE + 47) +#define PNX8335_PIC_MMI_SIF0_INT (PNX833X_PIC_IRQ_BASE + 48) +#define PNX8335_PIC_MMI_SIF1_INT (PNX833X_PIC_IRQ_BASE + 49) +#define PNX8335_PIC_MMI_CDMMU_INT (PNX833X_PIC_IRQ_BASE + 50) +#define PNX8335_PIC_PIBCS_INT (PNX833X_PIC_IRQ_BASE + 51) +#define PNX8335_PIC_ETHERNET_INT (PNX833X_PIC_IRQ_BASE + 52) +#define PNX8335_PIC_VMSP1_0_INT (PNX833X_PIC_IRQ_BASE + 53) +#define PNX8335_PIC_VMSP1_1_INT (PNX833X_PIC_IRQ_BASE + 54) +#define PNX8335_PIC_VMSP1_DMA_INT (PNX833X_PIC_IRQ_BASE + 55) +#define PNX8335_PIC_TDGR_DE_INT (PNX833X_PIC_IRQ_BASE + 56) +#define PNX8335_PIC_IR1_IRQ_INT (PNX833X_PIC_IRQ_BASE + 57) +#endif + +/* GPIO interrupts */ +#define PNX833X_GPIO_0_INT (PNX833X_GPIO_IRQ_BASE + 0) +#define PNX833X_GPIO_1_INT (PNX833X_GPIO_IRQ_BASE + 1) +#define PNX833X_GPIO_2_INT (PNX833X_GPIO_IRQ_BASE + 2) +#define PNX833X_GPIO_3_INT (PNX833X_GPIO_IRQ_BASE + 3) +#define PNX833X_GPIO_4_INT (PNX833X_GPIO_IRQ_BASE + 4) +#define PNX833X_GPIO_5_INT (PNX833X_GPIO_IRQ_BASE + 5) +#define PNX833X_GPIO_6_INT (PNX833X_GPIO_IRQ_BASE + 6) +#define PNX833X_GPIO_7_INT (PNX833X_GPIO_IRQ_BASE + 7) +#define PNX833X_GPIO_8_INT (PNX833X_GPIO_IRQ_BASE + 8) +#define PNX833X_GPIO_9_INT (PNX833X_GPIO_IRQ_BASE + 9) +#define PNX833X_GPIO_10_INT (PNX833X_GPIO_IRQ_BASE + 10) +#define PNX833X_GPIO_11_INT (PNX833X_GPIO_IRQ_BASE + 11) +#define PNX833X_GPIO_12_INT (PNX833X_GPIO_IRQ_BASE + 12) +#define PNX833X_GPIO_13_INT (PNX833X_GPIO_IRQ_BASE + 13) +#define PNX833X_GPIO_14_INT (PNX833X_GPIO_IRQ_BASE + 14) +#define PNX833X_GPIO_15_INT (PNX833X_GPIO_IRQ_BASE + 15) + +#endif + diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/pnx833x.h linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/pnx833x.h --- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/pnx833x.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/pnx833x.h 2008-06-05 10:11:24.000000000 +0100 @@ -0,0 +1,194 @@ +/* + * pnx833x.h: Register mappings for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel <chris.steel@xxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __ASM_MIPS_MACH_PNX833X_PNX833X_H +#define __ASM_MIPS_MACH_PNX833X_PNX833X_H + +/* All regs are accessed in KSEG1 */ +#define PNX833X_BASE (0xa0000000ul + 0x17E00000ul) + +#define PNX833X_REG(offs) *((volatile unsigned long *)(PNX833X_BASE + offs)) + +/* Registers are named exactly as in PNX833X docs, just with PNX833X_ prefix */ + +/* Read access to multibit fields */ +#define PNX833X_BIT(val, reg, field) ((val) & PNX833X_##reg##_##field) +#define PNX833X_REGBIT(reg, field) PNX833X_BIT(PNX833X_##reg, reg, field) + +/* Use PNX833X_FIELD to extract a field from val */ +#define PNX_FIELD(cpu, val, reg, field) \ + (((val) & PNX##cpu##_##reg##_##field##_MASK) >> \ + PNX##cpu##_##reg##_##field##_SHIFT) +#define PNX833X_FIELD(val, reg, field) PNX_FIELD(833X, val, reg, field) +#define PNX8330_FIELD(val, reg, field) PNX_FIELD(8330, val, reg, field) +#define PNX8335_FIELD(val, reg, field) PNX_FIELD(8335, val, reg, field) + +/* Use PNX833X_REGFIELD to extract a field from a register */ +#define PNX833X_REGFIELD(reg, field) PNX833X_FIELD(PNX833X_##reg, reg, field) +#define PNX8330_REGFIELD(reg, field) PNX8330_FIELD(PNX8330_##reg, reg, field) +#define PNX8335_REGFIELD(reg, field) PNX8335_FIELD(PNX8335_##reg, reg, field) + + +#define PNX_WRITEFIELD(cpu, val, reg, field) \ + PNX##cpu##_##reg = (PNX##cpu##_##reg & ~(PNX##cpu##_##reg##_##field##_MASK)) | \ + ((val) << PNX##cpu##_##reg##_##field##_SHIFT) +#define PNX833X_WRITEFIELD(val, reg, field) \ + PNX_WRITEFIELD(833X, val, reg, field) +#define PNX8330_WRITEFIELD(val, reg, field) \ + PNX_WRITEFIELD(8330, val, reg, field) +#define PNX8335_WRITEFIELD(val, reg, field) \ + PNX_WRITEFIELD(8335, val, reg, field) + + +/* Macros to detect CPU type */ + +#define PNX833X_CONFIG_MODULE_ID PNX833X_REG(0x7FFC) +#define PNX833X_CONFIG_MODULE_ID_MAJREV_MASK 0x0000f000 +#define PNX833X_CONFIG_MODULE_ID_MAJREV_SHIFT 12 +#define PNX8330_CONFIG_MODULE_MAJREV 4 +#define PNX8335_CONFIG_MODULE_MAJREV 5 +#define CPU_IS_PNX8330 (PNX833X_REGFIELD(CONFIG_MODULE_ID, MAJREV) == \ + PNX8330_CONFIG_MODULE_MAJREV) +#define CPU_IS_PNX8335 (PNX833X_REGFIELD(CONFIG_MODULE_ID, MAJREV) == \ + PNX8335_CONFIG_MODULE_MAJREV) + + + +#define PNX833X_RESET_CONTROL PNX833X_REG(0x8004) +#define PNX833X_RESET_CONTROL_2 PNX833X_REG(0x8014) + +#define PNX833X_PIC_REG(offs) PNX833X_REG(0x01000 + (offs)) +#define PNX833X_PIC_INT_PRIORITY PNX833X_PIC_REG(0x0) +#define PNX833X_PIC_INT_SRC PNX833X_PIC_REG(0x4) +#define PNX833X_PIC_INT_SRC_INT_SRC_MASK 0x00000FF8ul /* bits 11:3 */ +#define PNX833X_PIC_INT_SRC_INT_SRC_SHIFT 3 +#define PNX833X_PIC_INT_REG(irq) PNX833X_PIC_REG(0x10 + 4*(irq)) + +#define PNX833X_CLOCK_CPUCP_CTL PNX833X_REG(0x9228) +#define PNX833X_CLOCK_CPUCP_CTL_EXIT_RESET 0x00000002ul /* bit 1 */ +#define PNX833X_CLOCK_CPUCP_CTL_DIV_CLOCK_MASK 0x00000018ul /* bits 4:3 */ +#define PNX833X_CLOCK_CPUCP_CTL_DIV_CLOCK_SHIFT 3 + +#define PNX8335_CLOCK_PLL_CPU_CTL PNX833X_REG(0x9020) +#define PNX8335_CLOCK_PLL_CPU_CTL_FREQ_MASK 0x1f +#define PNX8335_CLOCK_PLL_CPU_CTL_FREQ_SHIFT 0 + +#define PNX833X_CONFIG_MUX PNX833X_REG(0x7004) +#define PNX833X_CONFIG_MUX_IDE_MUX 0x00000080 /* bit 7 */ + +#define PNX8330_CONFIG_POLYFUSE_7 PNX833X_REG(0x7040) +#define PNX8330_CONFIG_POLYFUSE_7_BOOT_MODE_MASK 0x00180000 +#define PNX8330_CONFIG_POLYFUSE_7_BOOT_MODE_SHIFT 19 + +#define PNX833X_PIO_IN PNX833X_REG(0xF000) +#define PNX833X_PIO_OUT PNX833X_REG(0xF004) +#define PNX833X_PIO_DIR PNX833X_REG(0xF008) +#define PNX833X_PIO_SEL PNX833X_REG(0xF014) +#define PNX833X_PIO_INT_EDGE PNX833X_REG(0xF020) +#define PNX833X_PIO_INT_HI PNX833X_REG(0xF024) +#define PNX833X_PIO_INT_LO PNX833X_REG(0xF028) +#define PNX833X_PIO_INT_STATUS PNX833X_REG(0xFFE0) +#define PNX833X_PIO_INT_ENABLE PNX833X_REG(0xFFE4) +#define PNX833X_PIO_INT_CLEAR PNX833X_REG(0xFFE8) +#define PNX833X_PIO_IN2 PNX833X_REG(0xF05C) +#define PNX833X_PIO_OUT2 PNX833X_REG(0xF060) +#define PNX833X_PIO_DIR2 PNX833X_REG(0xF064) +#define PNX833X_PIO_SEL2 PNX833X_REG(0xF068) + +#define PNX833X_UART0_PORTS_START (PNX833X_BASE + 0xB000) +#define PNX833X_UART0_PORTS_END (PNX833X_BASE + 0xBFFF) +#define PNX833X_UART1_PORTS_START (PNX833X_BASE + 0xC000) +#define PNX833X_UART1_PORTS_END (PNX833X_BASE + 0xCFFF) + +#define PNX833X_USB_PORTS_START (PNX833X_BASE + 0x19000) +#define PNX833X_USB_PORTS_END (PNX833X_BASE + 0x19FFF) + +#define PNX833X_CONFIG_USB PNX833X_REG(0x7008) + +#define PNX833X_I2C0_PORTS_START (PNX833X_BASE + 0xD000) +#define PNX833X_I2C0_PORTS_END (PNX833X_BASE + 0xDFFF) +#define PNX833X_I2C1_PORTS_START (PNX833X_BASE + 0xE000) +#define PNX833X_I2C1_PORTS_END (PNX833X_BASE + 0xEFFF) + +#define PNX833X_IDE_PORTS_START (PNX833X_BASE + 0x1A000) +#define PNX833X_IDE_PORTS_END (PNX833X_BASE + 0x1AFFF) +#define PNX833X_IDE_MODULE_ID PNX833X_REG(0x1AFFC) + +#define PNX833X_IDE_MODULE_ID_MODULE_ID_MASK 0xFFFF0000 +#define PNX833X_IDE_MODULE_ID_MODULE_ID_SHIFT 16 +#define PNX833X_IDE_MODULE_ID_VALUE 0xA009 + + +#define PNX833X_MIU_SEL0 PNX833X_REG(0x2004) +#define PNX833X_MIU_SEL0_TIMING PNX833X_REG(0x2008) +#define PNX833X_MIU_SEL1 PNX833X_REG(0x200C) +#define PNX833X_MIU_SEL1_TIMING PNX833X_REG(0x2010) +#define PNX833X_MIU_SEL2 PNX833X_REG(0x2014) +#define PNX833X_MIU_SEL2_TIMING PNX833X_REG(0x2018) +#define PNX833X_MIU_SEL3 PNX833X_REG(0x201C) +#define PNX833X_MIU_SEL3_TIMING PNX833X_REG(0x2020) + +#define PNX833X_MIU_SEL0_SPI_MODE_ENABLE_MASK (1 << 14) +#define PNX833X_MIU_SEL0_SPI_MODE_ENABLE_SHIFT 14 + +#define PNX833X_MIU_SEL0_BURST_MODE_ENABLE_MASK (1 << 7) +#define PNX833X_MIU_SEL0_BURST_MODE_ENABLE_SHIFT 7 + +#define PNX833X_MIU_SEL0_BURST_PAGE_LEN_MASK (0xF << 9) +#define PNX833X_MIU_SEL0_BURST_PAGE_LEN_SHIFT 9 + +#define PNX833X_MIU_CONFIG_SPI PNX833X_REG(0x2000) + +#define PNX833X_MIU_CONFIG_SPI_OPCODE_MASK (0xFF << 3) +#define PNX833X_MIU_CONFIG_SPI_OPCODE_SHIFT 3 + +#define PNX833X_MIU_CONFIG_SPI_DATA_ENABLE_MASK (1 << 2) +#define PNX833X_MIU_CONFIG_SPI_DATA_ENABLE_SHIFT 2 + +#define PNX833X_MIU_CONFIG_SPI_ADDR_ENABLE_MASK (1 << 1) +#define PNX833X_MIU_CONFIG_SPI_ADDR_ENABLE_SHIFT 1 + +#define PNX833X_MIU_CONFIG_SPI_SYNC_MASK (1 << 0) +#define PNX833X_MIU_CONFIG_SPI_SYNC_SHIFT 0 + +#define PNX833X_WRITE_CONFIG_SPI(opcode, data_enable, addr_enable, sync) \ + PNX833X_MIU_CONFIG_SPI = \ + ((opcode) << PNX833X_MIU_CONFIG_SPI_OPCODE_SHIFT) | \ + ((data_enable) << PNX833X_MIU_CONFIG_SPI_DATA_ENABLE_SHIFT) | \ + ((addr_enable) << PNX833X_MIU_CONFIG_SPI_ADDR_ENABLE_SHIFT) | \ + ((sync) << PNX833X_MIU_CONFIG_SPI_SYNC_SHIFT) + +#define PNX8335_IP3902_PORTS_START (PNX833X_BASE + 0x2F000) +#define PNX8335_IP3902_PORTS_END (PNX833X_BASE + 0x2FFFF) +#define PNX8335_IP3902_MODULE_ID PNX833X_REG(0x2FFFC) + +#define PNX8335_IP3902_MODULE_ID_MODULE_ID_MASK 0xFFFF0000 +#define PNX8335_IP3902_MODULE_ID_MODULE_ID_SHIFT 16 +#define PNX8335_IP3902_MODULE_ID_VALUE 0x3902 + +#define PNX8335_SATA_PORTS_START (PNX833X_BASE + 0x2E000) +#define PNX8335_SATA_PORTS_END (PNX833X_BASE + 0x2EFFF) +#define PNX8335_SATA_MODULE_ID PNX833X_REG(0x2EFFC) + +#define PNX8335_SATA_MODULE_ID_MODULE_ID_MASK 0xFFFF0000 +#define PNX8335_SATA_MODULE_ID_MODULE_ID_SHIFT 16 +#define PNX8335_SATA_MODULE_ID_VALUE 0xA099 + +#endif diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/war.h linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/war.h --- linux-2.6.26-rc4.orig/include/asm-mips/mach-pnx833x/war.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/include/asm-mips/mach-pnx833x/war.h 2008-06-05 09:34:22.000000000 +0100 @@ -0,0 +1,25 @@ +/* + * 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. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@xxxxxxxxxxxxxx> + */ +#ifndef __ASM_MIPS_MACH_PNX833X_WAR_H +#define __ASM_MIPS_MACH_PNX833X_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */ diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/linux/i2c-id.h linux-2.6.26-rc4/include/linux/i2c-id.h --- linux-2.6.26-rc4.orig/include/linux/i2c-id.h 2008-06-05 11:41:44.000000000 +0100 +++ linux-2.6.26-rc4/include/linux/i2c-id.h 2008-06-04 09:33:51.000000000 +0100 @@ -129,6 +129,7 @@ /* --- PCA 9564 based algorithms */ #define I2C_HW_A_ISA 0x1a0000 /* generic ISA Bus interface card */ +#define I2C_HW_A_PNX0105 0x1a0001 /* NXP PNX833X SoC I2C */ /* --- PowerPC on-chip adapters */ #define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */ diff -urN --exclude=.svn linux-2.6.26-rc4.orig/include/linux/i2c-pnx0105.h linux-2.6.26-rc4/include/linux/i2c-pnx0105.h --- linux-2.6.26-rc4.orig/include/linux/i2c-pnx0105.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc4/include/linux/i2c-pnx0105.h 2008-06-05 09:32:31.000000000 +0100 @@ -0,0 +1,58 @@ +/* + * i2c-pnx0105.h: driver for PNX833X I2C (IP0105 Block) + * Copyright (C) 2006 Nikita Youshchenko <yoush@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef _LINUX_I2C_PNX0105_H +#define _LINUX_I2C_PNX0105_H + +#include <linux/i2c.h> +#include <linux/i2c-algo-pca.h> +#include <linux/wait.h> + +struct i2c_pnx0105_dev { + unsigned long base; + int irq; + unsigned char clock; /* value to write to freq bits of control reg */ + unsigned char bus_addr; /* bus address for slave mode; currently not supported */ + + int timeout; /* non-zero when timeout was detected */ + wait_queue_head_t wait; + + struct i2c_algo_pca_data algo_data; + struct i2c_adapter adap; +}; + +/* Register area size */ +#define I2C_PNX0105_IO_SIZE 0x1000 + +/* Register offsets */ +#define I2C_PNX0105_CONTROL 0x0000 +#define I2C_PNX0105_DAT 0x0004 +#define I2C_PNX0105_STATUS 0x0008 +#define I2C_PNX0105_ADDRESS 0x000C +#define I2C_PNX0105_STOP 0x0010 +#define I2C_PNX0105_PD 0x0014 +#define I2C_PNX0105_SET_PINS 0x0018 +#define I2C_PNX0105_OBS_PINS 0x001C +#define I2C_PNX0105_INT_STATUS 0x0FE0 +#define I2C_PNX0105_INT_ENABLE 0x0FE4 +#define I2C_PNX0105_INT_CLEAR 0x0FE8 +#define I2C_PNX0105_INT_SET 0x0FEC +#define I2C_PNX0105_POWER_DOWN 0x0FF4 +#define I2C_PNX0105_MODULE_ID 0x0FFC + +#endif