<sect1><title>Delaying, scheduling, and timer routines</title>
!Iinclude/linux/sched.h
-!Ekernel/sched.c
+!Ekernel/sched/core.c
+!Ikernel/sched/cpupri.c
+!Ikernel/sched/fair.c
!Iinclude/linux/completion.h
!Ekernel/timer.c
</sect1>
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
-!Iinclude/linux/serial_core.h
!Edrivers/tty/serial/serial_core.c
!Edrivers/tty/serial/8250.c
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Iarch/x86/include/asm/io.h
-!Elib/iomap.c
+!Elib/pci_iomap.c
</chapter>
</book>
6. List of managed interfaces
-----------------------------
+MEM
+ devm_kzalloc()
+ devm_kfree()
+
IO region
devm_request_region()
devm_request_mem_region()
convert to using pci_scan_root_bus() so they can supply a list of
bus resources when the bus is created.
Who: Bjorn Helgaas <bhelgaas@google.com>
+
+----------------------------
+
+What: The CAP9 SoC family will be removed
+When: 3.4
+Files: arch/arm/mach-at91/at91cap9.c
+ arch/arm/mach-at91/at91cap9_devices.c
+ arch/arm/mach-at91/include/mach/at91cap9.h
+ arch/arm/mach-at91/include/mach/at91cap9_matrix.h
+ arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
+ arch/arm/mach-at91/board-cap9adk.c
+Why: The code is not actively maintained and platforms are now hard to find.
+Who: Nicolas Ferre <nicolas.ferre@atmel.com>
+ Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
...
{
- .name "2bit"
+ .name = "2bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "4bit"
+ .name = "4bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "4bit"
+ .name = "4bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "8bit"
+ .name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
- .function = "mmc0",
.group = "mmc0_1_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "8bit"
+ .name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "8bit"
+ .name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_3_grp",
like this:
{
- .name "POWERMAP"
+ .name = "POWERMAP"
.ctrl_dev_name = "pinctrl-foo",
.function = "power_func",
.hog_on_boot = true,
foo_switch()
{
- struct pinmux pmx;
+ struct pinmux *pmx;
/* Enable on position A */
pmx = pinmux_get(&device, "spi0-pos-A");
because some problems only show up on a second attempt at suspending and
resuming the system.] Moreover, hibernating in the "reboot" and "shutdown"
modes causes the PM core to skip some platform-related callbacks which on ACPI
-systems might be necessary to make hibernation work. Thus, if you machine fails
+systems might be necessary to make hibernation work. Thus, if your machine fails
to hibernate or resume in the "reboot" mode, you should try the "platform" mode:
# echo platform > /sys/power/disk
freezing user threads I don't find really objectionable."
Still, there are kernel threads that may want to be freezable. For example, if
-a kernel that belongs to a device driver accesses the device directly, it in
-principle needs to know when the device is suspended, so that it doesn't try to
-access it at that time. However, if the kernel thread is freezable, it will be
-frozen before the driver's .suspend() callback is executed and it will be
+a kernel thread that belongs to a device driver accesses the device directly, it
+in principle needs to know when the device is suspended, so that it doesn't try
+to access it at that time. However, if the kernel thread is freezable, it will
+be frozen before the driver's .suspend() callback is executed and it will be
thawed after the driver's .resume() callback has run, so it won't be accessing
the device while it's suspended.
- Send the patch, after verifying that it follows the above rules, to
stable@vger.kernel.org. You must note the upstream commit ID in the
- changelog of your submission.
+ changelog of your submission, as well as the kernel version you wish
+ it to be applied to.
- To have the patch automatically included in the stable tree, add the tag
Cc: stable@vger.kernel.org
in the sign-off area. Once the patch is merged it will be applied to
The framework includes a simple notification mechanism, in the form of a
netlink event. Netlink socket initialization is done during the _init_
of the framework. Drivers which intend to use the notification mechanism
-just need to call generate_netlink_event() with two arguments viz
+just need to call thermal_generate_netlink_event() with two arguments viz
(originator, event). Typically the originator will be an integer assigned
to a thermal_zone_device when it registers itself with the framework. The
event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
- this file.
kvm/
- Kernel Virtual Machine. See also http://linux-kvm.org
-lguest/
- - Extremely simple hypervisor for experimental/educational use.
uml/
- User Mode Linux, builds/runs Linux kernel as a userspace program.
virtio.txt
S: Supported
F: fs/dlm/
+DMA BUFFER SHARING FRAMEWORK
+M: Sumit Semwal <sumit.semwal@linaro.org>
+S: Maintained
+L: linux-media@vger.kernel.org
+L: dri-devel@lists.freedesktop.org
+L: linaro-mm-sig@lists.linaro.org
+F: drivers/base/dma-buf*
+F: include/linux/dma-buf*
+F: Documentation/dma-buf-sharing.txt
+T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
+
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
M: Vinod Koul <vinod.koul@intel.com>
M: Dan Williams <dan.j.williams@intel.com>
DRM DRIVERS FOR EXYNOS
M: Inki Dae <inki.dae@samsung.com>
+M: Joonyoung Shim <jy0922.shim@samsung.com>
+M: Seung-Woo Kim <sw0312.kim@samsung.com>
+M: Kyungmin Park <kyungmin.park@samsung.com>
L: dri-devel@lists.freedesktop.org
S: Supported
F: drivers/gpu/drm/exynos
ECRYPT FILE SYSTEM
M: Tyler Hicks <tyhicks@canonical.com>
-M: Dustin Kirkland <kirkland@canonical.com>
+M: Dustin Kirkland <dustin.kirkland@gazzang.com>
L: ecryptfs@vger.kernel.org
W: https://launchpad.net/ecryptfs
S: Supported
M: Greg Kroah-Hartman <gregkh@suse.de>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
-F: drivers/tty/*
+F: drivers/tty/
F: drivers/tty/serial/serial_core.c
F: include/linux/serial_core.h
F: include/linux/serial.h
select ARCH_HAS_CPUFREQ
select CPU_FREQ
select GENERIC_CLOCKEVENTS
- select CLKDEV_LOOKUP
+ select HAVE_CLK
select HAVE_SCHED_CLOCK
select TICK_ONESHOT
select ARCH_REQUIRE_GPIOLIB
select HAVE_CLK
select CLKDEV_LOOKUP
select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C if I2C
select HAVE_S3C_RTC if RTC_CLASS
select HAVE_CLK
select CLKDEV_LOOKUP
select CLKSRC_MMIO
- select ARM_L1_CACHE_SHIFT_6
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK
machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
machine-$(CONFIG_ARCH_IMX_V4_V5) := imx
machine-$(CONFIG_ARCH_IMX_V6_V7) := imx
-machine-$(CONFIG_ARCH_MX5) := mx5
machine-$(CONFIG_ARCH_MXS) := mxs
machine-$(CONFIG_ARCH_NETX) := netx
machine-$(CONFIG_ARCH_NOMADIK) := nomadik
#include <asm/irq.h>
#include <asm/exception.h>
+#include <asm/smp_plat.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
unsigned int gic_irqs = gic->gic_irqs;
struct irq_domain *domain = &gic->domain;
void __iomem *base = gic_data_dist_base(gic);
- u32 cpu = 0;
-
-#ifdef CONFIG_SMP
- cpu = cpu_logical_map(smp_processor_id());
-#endif
+ u32 cpu = cpu_logical_map(smp_processor_id());
cpumask = 1 << cpu;
cpumask |= cpumask << 8;
--- /dev/null
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
+CONFIG_MACH_PCM037=y
+CONFIG_MACH_PCM037_EET=y
+CONFIG_MACH_MX31_3DS=y
+CONFIG_MACH_MX31MOBOARD=y
+CONFIG_MACH_QONG=y
+CONFIG_MACH_ARMADILLO5X0=y
+CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX35=y
+CONFIG_MACH_VPR200=y
+CONFIG_MACH_IMX51_DT=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_IMX53_DT=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_FEC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+++ /dev/null
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_MACH_MX31ADS_WM1133_EV1=y
-CONFIG_MACH_MX31LILLY=y
-CONFIG_MACH_MX31LITE=y
-CONFIG_MACH_PCM037=y
-CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31_3DS=y
-CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_QONG=y
-CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_KZM_ARM11_01=y
-CONFIG_MACH_PCM043=y
-CONFIG_MACH_MX35_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX35=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
-CONFIG_ARM_ERRATA_411920=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_VFP=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_MTD_UBI=y
-# CONFIG_BLK_DEV is not set
-CONFIG_MISC_DEVICES=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMSC911X=y
-CONFIG_DNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_IMX=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_IMX2_WDT=y
-CONFIG_MFD_WM8350_I2C=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_WM8350=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_SOC_CAMERA=y
-CONFIG_SOC_CAMERA_MT9M001=y
-CONFIG_SOC_CAMERA_MT9M111=y
-CONFIG_SOC_CAMERA_MT9T031=y
-CONFIG_SOC_CAMERA_MT9V022=y
-CONFIG_SOC_CAMERA_TW9910=y
-CONFIG_SOC_CAMERA_OV772X=y
-CONFIG_VIDEO_MX3=y
-# CONFIG_RADIO_ADAPTERS is not set
-CONFIG_FB=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_IMX_SOC=y
-CONFIG_SND_MXC_SOC_WM1133_EV1=y
-CONFIG_SND_SOC_PHYCORE_AC97=y
-CONFIG_SND_SOC_EUKREA_TLV320=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_GADGET=m
-CONFIG_USB_FSL_USB2=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_USB_ULPI=y
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_MXC=y
-CONFIG_DMADEVICES=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_UBIFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
+++ /dev/null
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_KERNEL_LZO=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX5=y
-CONFIG_MACH_MX51_BABBAGE=y
-CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
-CONFIG_MACH_EUKREA_CPUIMX51SD=y
-CONFIG_MACH_MX51_EFIKAMX=y
-CONFIG_MACH_MX51_EFIKASB=y
-CONFIG_MACH_MX53_EVK=y
-CONFIG_MACH_MX53_SMD=y
-CONFIG_MACH_MX53_LOCO=y
-CONFIG_MACH_MX53_ARD=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_VMSPLIT_2G=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM_DEBUG=y
-CONFIG_PM_TEST_SUSPEND=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=y
-CONFIG_PATA_IMX=y
-CONFIG_NETDEVICES=y
-CONFIG_MII=m
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_ICPLUS_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_NATIONAL_PHY=y
-CONFIG_STE10XP=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=m
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_MMA8450=y
-CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_SPI_IMX=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_MC13892=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_ESDHC_IMX=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_RTC_MXC=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_LZO=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_CCITT=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
*/
#ifdef CONFIG_THUMB2_KERNEL
- .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
+ .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
9999:
.if \inc == 1
\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
#else /* !CONFIG_THUMB2_KERNEL */
- .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
+ .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
.rept \rept
9999:
.if \inc == 1
* instructions (inline assembly)
*/
#ifdef CONFIG_CPU_USE_DOMAINS
-#define T(instr) #instr "t"
+#define TUSER(instr) #instr "t"
#else
-#define T(instr) #instr
+#define TUSER(instr) #instr
#endif
#else /* __ASSEMBLY__ */
* instructions
*/
#ifdef CONFIG_CPU_USE_DOMAINS
-#define T(instr) instr ## t
+#define TUSER(instr) instr ## t
#else
-#define T(instr) instr
+#define TUSER(instr) instr
#endif
#endif /* __ASSEMBLY__ */
#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
__asm__ __volatile__( \
- "1: " T(ldr) " %1, [%3]\n" \
+ "1: " TUSER(ldr) " %1, [%3]\n" \
" " insn "\n" \
- "2: " T(str) " %0, [%3]\n" \
+ "2: " TUSER(str) " %0, [%3]\n" \
" mov %0, #0\n" \
__futex_atomic_ex_table("%5") \
: "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
return -EFAULT;
__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
- "1: " T(ldr) " %1, [%4]\n"
+ "1: " TUSER(ldr) " %1, [%4]\n"
" teq %1, %2\n"
" it eq @ explicit IT needed for the 2b label\n"
- "2: " T(streq) " %3, [%4]\n"
+ "2: " TUSER(streq) " %3, [%4]\n"
__futex_atomic_ex_table("%5")
: "+r" (ret), "=&r" (val)
: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
*/
extern void platform_smp_prepare_cpus(unsigned int);
-/*
- * Logical CPU mapping.
- */
-extern int __cpu_logical_map[NR_CPUS];
-#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
-
/*
* Initial data for bringing up a secondary CPU.
*/
}
#endif
+/*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[];
+#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
+
#endif
#define __get_user_asm_byte(x,addr,err) \
__asm__ __volatile__( \
- "1: " T(ldrb) " %1,[%2],#0\n" \
+ "1: " TUSER(ldrb) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
#define __get_user_asm_word(x,addr,err) \
__asm__ __volatile__( \
- "1: " T(ldr) " %1,[%2],#0\n" \
+ "1: " TUSER(ldr) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
#define __put_user_asm_byte(x,__pu_addr,err) \
__asm__ __volatile__( \
- "1: " T(strb) " %1,[%2],#0\n" \
+ "1: " TUSER(strb) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
#define __put_user_asm_word(x,__pu_addr,err) \
__asm__ __volatile__( \
- "1: " T(str) " %1,[%2],#0\n" \
+ "1: " TUSER(str) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
#define __put_user_asm_dword(x,__pu_addr,err) \
__asm__ __volatile__( \
- ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \
- ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \
- THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \
- THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \
+ ARM( "1: " TUSER(str) " " __reg_oper1 ", [%1], #4\n" ) \
+ ARM( "2: " TUSER(str) " " __reg_oper0 ", [%1]\n" ) \
+ THUMB( "1: " TUSER(str) " " __reg_oper1 ", [%1]\n" ) \
+ THUMB( "2: " TUSER(str) " " __reg_oper0 ", [%1, #4]\n" ) \
"3:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
#endif
#endif
+.macro mcount_adjust_addr rd, rn
+ bic \rd, \rn, #1 @ clear the Thumb bit if present
+ sub \rd, \rd, #MCOUNT_INSN_SIZE
+.endm
+
.macro __mcount suffix
mcount_enter
ldr r0, =ftrace_trace_function
mcount_exit
1: mcount_get_lr r1 @ lr of instrumented func
- mov r0, lr @ instrumented function
- sub r0, r0, #MCOUNT_INSN_SIZE
+ mcount_adjust_addr r0, lr @ instrumented function
adr lr, BSYM(2f)
mov pc, r2
2: mcount_exit
mcount_enter
mcount_get_lr r1 @ lr of instrumented func
- mov r0, lr @ instrumented function
- sub r0, r0, #MCOUNT_INSN_SIZE
+ mcount_adjust_addr r0, lr @ instrumented function
.globl ftrace_call\suffix
ftrace_call\suffix:
#ifdef CONFIG_DYNAMIC_FTRACE
@ called from __ftrace_caller, saved in mcount_enter
ldr r1, [sp, #16] @ instrumented routine (func)
+ mcount_adjust_addr r1, r1
#else
@ called from __mcount, untouched in lr
- mov r1, lr @ instrumented routine (func)
+ mcount_adjust_addr r1, lr @ instrumented routine (func)
#endif
- sub r1, r1, #MCOUNT_INSN_SIZE
mov r2, fp @ frame pointer
bl prepare_ftrace_return
mcount_exit
#include <linux/init.h>
#include <linux/kexec.h>
#include <linux/of_fdt.h>
-#include <linux/crash_dump.h>
#include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
.flags = IORESOURCE_MEM
},
{
- .name = "Kernel text",
+ .name = "Kernel code",
.start = 0,
.end = 0,
.flags = IORESOURCE_MEM
: "r14");
}
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+ int i;
+ u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+ cpu_logical_map(0) = cpu;
+ for (i = 1; i < NR_CPUS; ++i)
+ cpu_logical_map(i) = i == cpu ? 0 : i;
+
+ printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
static void __init setup_processor(void)
{
struct proc_info_list *list;
}
#endif /* CONFIG_HOTPLUG_CPU */
-int __cpu_logical_map[NR_CPUS];
-
-void __init smp_setup_processor_id(void)
-{
- int i;
- u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
-
- cpu_logical_map(0) = cpu;
- for (i = 1; i < NR_CPUS; ++i)
- cpu_logical_map(i) = i == cpu ? 0 : i;
-
- printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
-}
-
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
static void ipi_timer(void)
{
struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
- irq_enter();
evt->event_handler(evt);
- irq_exit();
}
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
switch (ipinr) {
case IPI_TIMER:
+ irq_enter();
ipi_timer();
+ irq_exit();
break;
case IPI_RESCHEDULE:
break;
case IPI_CALL_FUNC:
+ irq_enter();
generic_smp_call_function_interrupt();
+ irq_exit();
break;
case IPI_CALL_FUNC_SINGLE:
+ irq_enter();
generic_smp_call_function_single_interrupt();
+ irq_exit();
break;
case IPI_CPU_STOP:
+ irq_enter();
ipi_cpu_stop(cpu);
+ irq_exit();
break;
default:
else
twd_calibrate_rate();
+ __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
+
clk->name = "local_timer";
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_C3STOP;
*/
#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
}
#endif
- PERCPU_SECTION(32)
+ PERCPU_SECTION(L1_CACHE_BYTES)
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
#endif
NOSAVE_DATA
- CACHELINE_ALIGNED_DATA(32)
- READ_MOSTLY_DATA(32)
+ CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
+ READ_MOSTLY_DATA(L1_CACHE_BYTES)
/*
* The exception fixup table (might need resorting at runtime)
*/
- . = ALIGN(32);
+ . = ALIGN(4);
__start___ex_table = .;
#ifdef CONFIG_MMU
*(__ex_table)
#include <asm/domain.h>
ENTRY(__get_user_1)
-1: T(ldrb) r2, [r0]
+1: TUSER(ldrb) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__get_user_1)
ENTRY(__get_user_2)
#ifdef CONFIG_THUMB2_KERNEL
-2: T(ldrb) r2, [r0]
-3: T(ldrb) r3, [r0, #1]
+2: TUSER(ldrb) r2, [r0]
+3: TUSER(ldrb) r3, [r0, #1]
#else
-2: T(ldrb) r2, [r0], #1
-3: T(ldrb) r3, [r0]
+2: TUSER(ldrb) r2, [r0], #1
+3: TUSER(ldrb) r3, [r0]
#endif
#ifndef __ARMEB__
orr r2, r2, r3, lsl #8
ENDPROC(__get_user_2)
ENTRY(__get_user_4)
-4: T(ldr) r2, [r0]
+4: TUSER(ldr) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__get_user_4)
#include <asm/domain.h>
ENTRY(__put_user_1)
-1: T(strb) r2, [r0]
+1: TUSER(strb) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__put_user_1)
mov ip, r2, lsr #8
#ifdef CONFIG_THUMB2_KERNEL
#ifndef __ARMEB__
-2: T(strb) r2, [r0]
-3: T(strb) ip, [r0, #1]
+2: TUSER(strb) r2, [r0]
+3: TUSER(strb) ip, [r0, #1]
#else
-2: T(strb) ip, [r0]
-3: T(strb) r2, [r0, #1]
+2: TUSER(strb) ip, [r0]
+3: TUSER(strb) r2, [r0, #1]
#endif
#else /* !CONFIG_THUMB2_KERNEL */
#ifndef __ARMEB__
-2: T(strb) r2, [r0], #1
-3: T(strb) ip, [r0]
+2: TUSER(strb) r2, [r0], #1
+3: TUSER(strb) ip, [r0]
#else
-2: T(strb) ip, [r0], #1
-3: T(strb) r2, [r0]
+2: TUSER(strb) ip, [r0], #1
+3: TUSER(strb) r2, [r0]
#endif
#endif /* CONFIG_THUMB2_KERNEL */
mov r0, #0
ENDPROC(__put_user_2)
ENTRY(__put_user_4)
-4: T(str) r2, [r0]
+4: TUSER(str) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__put_user_4)
ENTRY(__put_user_8)
#ifdef CONFIG_THUMB2_KERNEL
-5: T(str) r2, [r0]
-6: T(str) r3, [r0, #4]
+5: TUSER(str) r2, [r0]
+6: TUSER(str) r3, [r0, #4]
#else
-5: T(str) r2, [r0], #4
-6: T(str) r3, [r0]
+5: TUSER(str) r2, [r0], #4
+6: TUSER(str) r3, [r0]
#endif
mov r0, #0
mov pc, lr
rsb ip, ip, #4
cmp ip, #2
ldrb r3, [r1], #1
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
sub r2, r2, ip
b .Lc2u_dest_aligned
addmi ip, r2, #4
bmi .Lc2u_0nowords
ldr r3, [r1], #4
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4
ldrne r3, [r1], #4
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_0fupi
.Lc2u_0nowords: teq ip, #0
beq .Lc2u_finished
.Lc2u_nowords: cmp ip, #2
ldrb r3, [r1], #1
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
.Lc2u_not_enough:
mov r3, r7, pull #8
ldr r7, [r1], #4
orr r3, r3, r7, push #24
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
movne r3, r7, pull #8
ldrne r7, [r1], #4
orrne r3, r3, r7, push #24
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_1fupi
.Lc2u_1nowords: mov r3, r7, get_byte_1
teq ip, #0
beq .Lc2u_finished
cmp ip, #2
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_2
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
movgt r3, r7, get_byte_3
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
.Lc2u_2fupi: subs r2, r2, #4
mov r3, r7, pull #16
ldr r7, [r1], #4
orr r3, r3, r7, push #16
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
movne r3, r7, pull #16
ldrne r7, [r1], #4
orrne r3, r3, r7, push #16
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_2fupi
.Lc2u_2nowords: mov r3, r7, get_byte_2
teq ip, #0
beq .Lc2u_finished
cmp ip, #2
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_3
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
.Lc2u_3fupi: subs r2, r2, #4
mov r3, r7, pull #24
ldr r7, [r1], #4
orr r3, r3, r7, push #8
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
movne r3, r7, pull #24
ldrne r7, [r1], #4
orrne r3, r3, r7, push #8
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_3fupi
.Lc2u_3nowords: mov r3, r7, get_byte_3
teq ip, #0
beq .Lc2u_finished
cmp ip, #2
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
ENDPROC(__copy_to_user)
.Lcfu_dest_not_aligned:
rsb ip, ip, #4
cmp ip, #2
-USER( T(ldrb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1
-USER( T(ldrgeb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
sub r2, r2, ip
b .Lcfu_dest_aligned
.Lcfu_0fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .Lcfu_0nowords
-USER( T(ldr) r3, [r1], #4)
+USER( TUSER( ldr) r3, [r1], #4)
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0
ldmneia r1!, {r3 - r4} @ Shouldnt fault
stmneia r0!, {r3 - r4}
tst ip, #4
- T(ldrne) r3, [r1], #4 @ Shouldnt fault
+ TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault
strne r3, [r0], #4
ands ip, ip, #3
beq .Lcfu_0fupi
.Lcfu_0nowords: teq ip, #0
beq .Lcfu_finished
.Lcfu_nowords: cmp ip, #2
-USER( T(ldrb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1
-USER( T(ldrgeb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
b .Lcfu_finished
.Lcfu_src_not_aligned:
bic r1, r1, #3
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
cmp ip, #2
bgt .Lcfu_3fupi
beq .Lcfu_2fupi
addmi ip, r2, #4
bmi .Lcfu_1nowords
mov r3, r7, pull #8
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #24
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
stmneia r0!, {r3 - r4}
tst ip, #4
movne r3, r7, pull #8
-USER( T(ldrne) r7, [r1], #4) @ May fault
+USER( TUSER( ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #24
strne r3, [r0], #4
ands ip, ip, #3
addmi ip, r2, #4
bmi .Lcfu_2nowords
mov r3, r7, pull #16
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #16
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
stmneia r0!, {r3 - r4}
tst ip, #4
movne r3, r7, pull #16
-USER( T(ldrne) r7, [r1], #4) @ May fault
+USER( TUSER( ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #16
strne r3, [r0], #4
ands ip, ip, #3
strb r3, [r0], #1
movge r3, r7, get_byte_3
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #0) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault
strgtb r3, [r0], #1
b .Lcfu_finished
addmi ip, r2, #4
bmi .Lcfu_3nowords
mov r3, r7, pull #24
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #8
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
stmneia r0!, {r3 - r4}
tst ip, #4
movne r3, r7, pull #24
-USER( T(ldrne) r7, [r1], #4) @ May fault
+USER( TUSER( ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #8
strne r3, [r0], #4
ands ip, ip, #3
beq .Lcfu_finished
cmp ip, #2
strb r3, [r0], #1
-USER( T(ldrgeb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
b .Lcfu_finished
ENDPROC(__copy_from_user)
config HAVE_AT91_USART5
bool
+config AT91_SAM9_ALT_RESET
+ bool
+
+config AT91_SAM9G45_RESET
+ bool
+
menu "Atmel AT91 System-on-Chip"
choice
select HAVE_AT91_USART4
select HAVE_AT91_USART5
select HAVE_NET_MACB
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9261
bool "AT91SAM9261"
select GENERIC_CLOCKEVENTS
select HAVE_FB_ATMEL
select HAVE_AT91_DBGU0
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9G10
bool "AT91SAM9G10"
select GENERIC_CLOCKEVENTS
select HAVE_AT91_DBGU0
select HAVE_FB_ATMEL
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9263
bool "AT91SAM9263"
select HAVE_FB_ATMEL
select HAVE_NET_MACB
select HAVE_AT91_DBGU1
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9RL
bool "AT91SAM9RL"
select HAVE_AT91_USART3
select HAVE_FB_ATMEL
select HAVE_AT91_DBGU0
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9G20
bool "AT91SAM9G20"
select HAVE_AT91_USART4
select HAVE_AT91_USART5
select HAVE_NET_MACB
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9G45
bool "AT91SAM9G45"
select HAVE_FB_ATMEL
select HAVE_NET_MACB
select HAVE_AT91_DBGU1
+ select AT91_SAM9G45_RESET
config ARCH_AT91CAP9
bool "AT91CAP9"
select HAVE_FB_ATMEL
select HAVE_NET_MACB
select HAVE_AT91_DBGU1
+ select AT91_SAM9G45_RESET
config ARCH_AT91X40
bool "AT91x40"
obj- :=
obj-$(CONFIG_AT91_PMC_UNIT) += clock.o
+obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
+obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
# CPU-specific support
obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
#include <mach/cpu.h>
#include <mach/at91cap9.h>
#include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
#include "soc.h"
#include "generic.h"
}
};
-static void at91cap9_restart(char mode, const char *cmd)
-{
- at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
/* --------------------------------------------------------------------
* AT91CAP9 processor initialization
* -------------------------------------------------------------------- */
static void __init at91cap9_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91CAP9_BASE_SHDWC);
+ at91_ioremap_rstc(AT91CAP9_BASE_RSTC);
at91sam926x_ioremap_pit(AT91CAP9_BASE_PIT);
at91sam9_ioremap_smc(0, AT91CAP9_BASE_SMC);
}
static void __init at91cap9_initialize(void)
{
- arm_pm_restart = at91cap9_restart;
+ arm_pm_restart = at91sam9g45_restart;
at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
/* Register GPIO subsystem */
static void __init at91sam9260_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9260_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
}
static void __init at91sam9261_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9261_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
}
static void __init at91sam9263_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9263_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0);
at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1);
.globl at91sam9_alt_restart
at91sam9_alt_restart: ldr r0, .at91_va_base_sdramc @ preload constants
- ldr r1, .at91_va_base_rstc_cr
+ ldr r1, =at91_rstc_base
+ ldr r1, [r1]
mov r2, #1
mov r3, #AT91_SDRAMC_LPCB_POWER_DOWN
str r2, [r0, #AT91_SDRAMC_TR] @ disable SDRAM access
str r3, [r0, #AT91_SDRAMC_LPR] @ power down SDRAM
- str r4, [r1] @ reset processor
+ str r4, [r1, #AT91_RSTC_CR] @ reset processor
b .
.at91_va_base_sdramc:
.word AT91_VA_BASE_SYS + AT91_SDRAMC0
-.at91_va_base_rstc_cr:
- .word AT91_VA_BASE_SYS + AT91_RSTC_CR
#include <asm/mach/map.h>
#include <mach/at91sam9g45.h>
#include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
#include <mach/cpu.h>
#include "soc.h"
}
};
-static void at91sam9g45_restart(char mode, const char *cmd)
-{
- at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
/* --------------------------------------------------------------------
* AT91SAM9G45 processor initialization
* -------------------------------------------------------------------- */
static void __init at91sam9g45_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC);
}
--- /dev/null
+/*
+ * reset AT91SAM9G45 as per errata
+ *
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com>
+ *
+ * unless the SDRAM is cleanly shutdown before we hit the
+ * reset register it can be left driving the data bus and
+ * killing the chance of a subsequent boot from NAND
+ *
+ * GPLv2 Only
+ */
+
+#include <linux/linkage.h>
+#include <mach/hardware.h>
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/at91_rstc.h>
+
+ .arm
+
+ .globl at91sam9g45_restart
+
+at91sam9g45_restart:
+ ldr r0, .at91_va_base_sdramc0 @ preload constants
+ ldr r1, =at91_rstc_base
+ ldr r1, [r1]
+
+ mov r2, #1
+ mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN
+ ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
+
+ .balign 32 @ align to cache line
+
+ str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access
+ str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0
+ str r4, [r1, #AT91_RSTC_CR] @ reset processor
+
+ b .
+
+.at91_va_base_sdramc0:
+ .word AT91_VA_BASE_SYS + AT91_DDRSDRC0
static void __init at91sam9rl_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
}
extern void at91_irq_resume(void);
/* reset */
+extern void at91_ioremap_rstc(u32 base_addr);
extern void at91sam9_alt_restart(char, const char *);
+extern void at91sam9g45_restart(char, const char *);
/* shutdown */
extern void at91_ioremap_shdwc(u32 base_addr);
#ifndef AT91_RSTC_H
#define AT91_RSTC_H
-#define AT91_RSTC_CR (AT91_RSTC + 0x00) /* Reset Controller Control Register */
+#ifndef __ASSEMBLY__
+extern void __iomem *at91_rstc_base;
+
+#define at91_rstc_read(field) \
+ __raw_readl(at91_rstc_base + field)
+
+#define at91_rstc_write(field, value) \
+ __raw_writel(value, at91_rstc_base + field);
+#else
+.extern at91_rstc_base
+#endif
+
+#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
-#define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */
+#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
#define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */
#define AT91_RSTC_RSTTYP_GENERAL (0 << 8)
#define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */
#define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */
-#define AT91_RSTC_MR (AT91_RSTC + 0x08) /* Reset Controller Mode Register */
+#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */
#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */
#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */
#define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (cpu_is_at91cap9_revB() ? \
(0xfffffd50 - AT91_BASE_SYS) : \
(0xfffffd60 - AT91_BASE_SYS))
#define AT91CAP9_BASE_PIOB 0xfffff400
#define AT91CAP9_BASE_PIOC 0xfffff600
#define AT91CAP9_BASE_PIOD 0xfffff800
+#define AT91CAP9_BASE_RSTC 0xfffffd00
#define AT91CAP9_BASE_SHDWC 0xfffffd10
#define AT91CAP9_BASE_RTT 0xfffffd20
#define AT91CAP9_BASE_PIT 0xfffffd30
+++ /dev/null
-/*
- * arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
- *
- * (C) 2008 Andrew Victor
- *
- * DDR/SDR Controller (DDRSDRC) - System peripherals registers.
- * Based on AT91CAP9 datasheet revision B.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91CAP9_DDRSDR_H
-#define AT91CAP9_DDRSDR_H
-
-#define AT91_DDRSDRC_MR 0x00 /* Mode Register */
-#define AT91_DDRSDRC_MODE (0xf << 0) /* Command Mode */
-#define AT91_DDRSDRC_MODE_NORMAL 0
-#define AT91_DDRSDRC_MODE_NOP 1
-#define AT91_DDRSDRC_MODE_PRECHARGE 2
-#define AT91_DDRSDRC_MODE_LMR 3
-#define AT91_DDRSDRC_MODE_REFRESH 4
-#define AT91_DDRSDRC_MODE_EXT_LMR 5
-#define AT91_DDRSDRC_MODE_DEEP 6
-
-#define AT91_DDRSDRC_RTR 0x04 /* Refresh Timer Register */
-#define AT91_DDRSDRC_COUNT (0xfff << 0) /* Refresh Timer Counter */
-
-#define AT91_DDRSDRC_CR 0x08 /* Configuration Register */
-#define AT91_DDRSDRC_NC (3 << 0) /* Number of Column Bits */
-#define AT91_DDRSDRC_NC_SDR8 (0 << 0)
-#define AT91_DDRSDRC_NC_SDR9 (1 << 0)
-#define AT91_DDRSDRC_NC_SDR10 (2 << 0)
-#define AT91_DDRSDRC_NC_SDR11 (3 << 0)
-#define AT91_DDRSDRC_NC_DDR9 (0 << 0)
-#define AT91_DDRSDRC_NC_DDR10 (1 << 0)
-#define AT91_DDRSDRC_NC_DDR11 (2 << 0)
-#define AT91_DDRSDRC_NC_DDR12 (3 << 0)
-#define AT91_DDRSDRC_NR (3 << 2) /* Number of Row Bits */
-#define AT91_DDRSDRC_NR_11 (0 << 2)
-#define AT91_DDRSDRC_NR_12 (1 << 2)
-#define AT91_DDRSDRC_NR_13 (2 << 2)
-#define AT91_DDRSDRC_CAS (7 << 4) /* CAS Latency */
-#define AT91_DDRSDRC_CAS_2 (2 << 4)
-#define AT91_DDRSDRC_CAS_3 (3 << 4)
-#define AT91_DDRSDRC_CAS_25 (6 << 4)
-#define AT91_DDRSDRC_DLL (1 << 7) /* Reset DLL */
-#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */
-
-#define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */
-#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */
-#define AT91_DDRSDRC_TRCD (0xf << 4) /* Row to Column delay */
-#define AT91_DDRSDRC_TWR (0xf << 8) /* Write recovery delay */
-#define AT91_DDRSDRC_TRC (0xf << 12) /* Row cycle delay */
-#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */
-#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */
-#define AT91_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */
-#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */
-
-#define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */
-#define AT91_DDRSDRC_TRFC (0x1f << 0) /* Row Cycle Delay */
-#define AT91_DDRSDRC_TXSNR (0xff << 8) /* Exit self-refresh to non-read */
-#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */
-#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */
-
-#define AT91_DDRSDRC_LPR 0x18 /* Low Power Register */
-#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */
-#define AT91_DDRSDRC_LPCB_DISABLE 0
-#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1
-#define AT91_DDRSDRC_LPCB_POWER_DOWN 2
-#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3
-#define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */
-#define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */
-#define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */
-#define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */
-#define AT91_DDRSDRC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */
-#define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES (0 << 12)
-#define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES (1 << 12)
-#define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES (2 << 12)
-
-#define AT91_DDRSDRC_MDR 0x1C /* Memory Device Register */
-#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */
-#define AT91_DDRSDRC_MD_SDR 0
-#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
-#define AT91_DDRSDRC_MD_DDR 2
-#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
-
-#define AT91_DDRSDRC_DLLR 0x20 /* DLL Information Register */
-#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */
-#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */
-#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */
-#define AT91_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */
-#define AT91_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */
-#define AT91_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */
-#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */
-#define AT91_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */
-#define AT91_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */
-
-/* Register access macros */
-#define at91_ramc_read(num, reg) \
- at91_sys_read(AT91_DDRSDRC##num + reg)
-#define at91_ramc_write(num, reg, value) \
- at91_sys_write(AT91_DDRSDRC##num + reg, value)
-
-
-#endif
#define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
#define AT91SAM9260_BASE_ECC 0xffffe800
#define AT91SAM9260_BASE_PIOA 0xfffff400
#define AT91SAM9260_BASE_PIOB 0xfffff600
#define AT91SAM9260_BASE_PIOC 0xfffff800
+#define AT91SAM9260_BASE_RSTC 0xfffffd00
#define AT91SAM9260_BASE_SHDWC 0xfffffd10
#define AT91SAM9260_BASE_RTT 0xfffffd20
#define AT91SAM9260_BASE_PIT 0xfffffd30
#define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
#define AT91SAM9261_BASE_SMC 0xffffec00
#define AT91SAM9261_BASE_PIOA 0xfffff400
#define AT91SAM9261_BASE_PIOB 0xfffff600
#define AT91SAM9261_BASE_PIOC 0xfffff800
+#define AT91SAM9261_BASE_RSTC 0xfffffd00
#define AT91SAM9261_BASE_SHDWC 0xfffffd10
#define AT91SAM9261_BASE_RTT 0xfffffd20
#define AT91SAM9261_BASE_PIT 0xfffffd30
#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91SAM9263_BASE_ECC0 0xffffe000
#define AT91SAM9263_BASE_PIOC 0xfffff600
#define AT91SAM9263_BASE_PIOD 0xfffff800
#define AT91SAM9263_BASE_PIOE 0xfffffa00
+#define AT91SAM9263_BASE_RSTC 0xfffffd00
#define AT91SAM9263_BASE_SHDWC 0xfffffd10
#define AT91SAM9263_BASE_RTT0 0xfffffd20
#define AT91SAM9263_BASE_PIT 0xfffffd30
#define AT91_DDRSDRC_CAS_25 (6 << 4)
#define AT91_DDRSDRC_RST_DLL (1 << 7) /* Reset DLL */
#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */
-#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL */
-#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver */
-#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared */
-#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y */
+#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL [SAM9 Only] */
+#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver [SAM9 Only] */
+#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared [SAM9 Only] */
+#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */
#define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */
#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */
#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */
#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */
#define AT91_DDRSDRC_TWTR (0x7 << 24) /* Internal Write to Read delay */
-#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay */
+#define AT91CAP9_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */
+#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay [SAM9 Only] */
#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */
#define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */
#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */
#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */
-#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register */
+#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register [SAM9 Only] */
#define AT91_DDRSDRC_TXARD (0xf << 0) /* Exit active power down delay to read command in mode "Fast Exit" */
#define AT91_DDRSDRC_TXARDS (0xf << 4) /* Exit active power down delay to read command in mode "Slow Exit" */
#define AT91_DDRSDRC_TRPA (0xf << 8) /* Row Precharge All delay */
#define AT91_DDRSDRC_TRTP (0x7 << 12) /* Read to Precharge delay */
#define AT91_DDRSDRC_LPR 0x1C /* Low Power Register */
+#define AT91CAP9_DDRSDRC_LPR 0x18 /* Low Power Register */
#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */
#define AT91_DDRSDRC_LPCB_DISABLE 0
#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1
#define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */
#define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */
+#define AT91CAP9_DDRSDRC_MDR 0x1C /* Memory Device Register */
#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */
#define AT91_DDRSDRC_MD_SDR 0
#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
+#define AT91CAP9_DDRSDRC_MD_DDR 2
#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
-#define AT91_DDRSDRC_MD_DDR2 6
+#define AT91_DDRSDRC_MD_DDR2 6 /* [SAM9 Only] */
#define AT91_DDRSDRC_DBW (1 << 4) /* Data Bus Width */
#define AT91_DDRSDRC_DBW_32BITS (0 << 4)
#define AT91_DDRSDRC_DBW_16BITS (1 << 4)
#define AT91_DDRSDRC_DLL 0x24 /* DLL Information Register */
+#define AT91CAP9_DDRSDRC_DLL 0x20 /* DLL Information Register */
#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */
#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */
#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */
+#define AT91CAP9_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */
+#define AT91CAP9_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */
+#define AT91CAP9_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */
#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */
+#define AT91CAP9_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */
+#define AT91CAP9_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */
-#define AT91_DDRSDRC_HS 0x2C /* High Speed Register */
+#define AT91_DDRSDRC_HS 0x2C /* High Speed Register [SAM9 Only] */
#define AT91_DDRSDRC_DIS_ATCP_RD (1 << 2) /* Anticip read access is disabled */
#define AT91_DDRSDRC_DELAY(n) (0x30 + (0x4 * (n))) /* Delay I/O Register n */
-#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register */
+#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register [SAM9 Only] */
#define AT91_DDRSDRC_WP (1 << 0) /* Write protect enable */
#define AT91_DDRSDRC_WPKEY (0xffffff << 8) /* Write protect key */
#define AT91_DDRSDRC_KEY (0x444452 << 8) /* Write protect key = "DDR" */
-#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register */
+#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register [SAM9 Only] */
#define AT91_DDRSDRC_WPVS (1 << 0) /* Write protect violation status */
#define AT91_DDRSDRC_WPVSRC (0xffff << 8) /* Write protect violation source */
#define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91SAM9G45_BASE_ECC 0xffffe200
#define AT91SAM9G45_BASE_PIOC 0xfffff600
#define AT91SAM9G45_BASE_PIOD 0xfffff800
#define AT91SAM9G45_BASE_PIOE 0xfffffa00
+#define AT91SAM9G45_BASE_RSTC 0xfffffd00
#define AT91SAM9G45_BASE_SHDWC 0xfffffd10
#define AT91SAM9G45_BASE_RTT 0xfffffd20
#define AT91SAM9G45_BASE_PIT 0xfffffd30
#define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SCKCR (0xfffffd50 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91SAM9RL_BASE_PIOB 0xfffff600
#define AT91SAM9RL_BASE_PIOC 0xfffff800
#define AT91SAM9RL_BASE_PIOD 0xfffffa00
+#define AT91SAM9RL_BASE_RSTC 0xfffffd00
#define AT91SAM9RL_BASE_SHDWC 0xfffffd10
#define AT91SAM9RL_BASE_RTT 0xfffffd20
#define AT91SAM9RL_BASE_PIT 0xfffffd30
struct at91_usbh_data {
u8 ports; /* number of ports on root hub */
int vbus_pin[2]; /* port power-control pin */
- u8 vbus_pin_inverted;
+ u8 vbus_pin_active_low[2];
u8 overcurrent_supported;
int overcurrent_pin[2];
u8 overcurrent_status[2];
/*
* Show the reason for the previous system reset.
*/
-#if defined(AT91_RSTC)
#include <mach/at91_rstc.h>
#include <mach/at91_shdwc.h>
char *reason, *r2 = reset;
u32 reset_type, wake_type;
- if (!at91_shdwc_base)
+ if (!at91_shdwc_base || !at91_rstc_base)
return;
- reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
+ reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
wake_type = at91_shdwc_read(AT91_SHDW_SR);
switch (reset_type) {
}
pr_info("AT91: Starting after %s %s\n", reason, r2);
}
-#else
-static void __init show_reset_status(void) {}
-#endif
-
static int at91_pm_valid_state(suspend_state_t state)
{
: : "r" (0))
#elif defined(CONFIG_ARCH_AT91CAP9)
-#include <mach/at91cap9_ddrsdr.h>
+#include <mach/at91sam9_ddrsdr.h>
static inline u32 sdram_selfrefresh_enable(void)
{
u32 saved_lpr, lpr;
- saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+ saved_lpr = at91_ramc_read(0, AT91CAP9_DDRSDRC_LPR);
lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
- at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
+ at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
return saved_lpr;
}
-#define sdram_selfrefresh_disable(saved_lpr) at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr)
+#define sdram_selfrefresh_disable(saved_lpr) at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, saved_lpr)
#define wait_for_interrupt_enable() cpu_do_idle()
#elif defined(CONFIG_ARCH_AT91SAM9G45)
#if defined(CONFIG_ARCH_AT91RM9200)
#include <mach/at91rm9200_mc.h>
-#elif defined(CONFIG_ARCH_AT91CAP9)
-#include <mach/at91cap9_ddrsdr.h>
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
+#elif defined(CONFIG_ARCH_AT91CAP9) \
+ || defined(CONFIG_ARCH_AT91SAM9G45)
#include <mach/at91sam9_ddrsdr.h>
#else
#include <mach/at91sam9_sdramc.h>
void __init at91rm9200_set_type(int type)
{
if (type == ARCH_REVISON_9200_PQFP)
- at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
- else
at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP;
+ else
+ at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
+
+ pr_info("AT91: filled in soc subtype: %s\n",
+ at91_get_soc_subtype(&at91_soc_initdata));
}
void __init at91_init_irq_default(void)
pm_power_off = at91sam9_poweroff;
}
+void __iomem *at91_rstc_base;
+
+void __init at91_ioremap_rstc(u32 base_addr)
+{
+ at91_rstc_base = ioremap(base_addr, 16);
+ if (!at91_rstc_base)
+ panic("Impossible to ioremap at91_rstc_base\n");
+}
+
void __init at91_initialize(unsigned long main_clock)
{
at91_boot_soc.ioremap_registers();
#include <linux/io.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <mach/regs-pmu.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/timer-sp.h>
void highbank_set_cpu_jump(int cpu, void *jump_addr)
{
-#ifdef CONFIG_SMP
cpu = cpu_logical_map(cpu);
-#endif
writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu));
__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
config MACH_MX27
bool
+config ARCH_MX5
+ bool
+
+config ARCH_MX50
+ bool
+
+config ARCH_MX51
+ bool
+
+config ARCH_MX53
+ bool
+
config SOC_IMX1
bool
select ARCH_MX1
select MXC_AVIC
select SMP_ON_UP if SMP
+config SOC_IMX5
+ select CPU_V7
+ select MXC_TZIC
+ select ARCH_MXC_IOMUX_V3
+ select ARCH_MXC_AUDMUX_V2
+ select ARCH_HAS_CPUFREQ
+ select ARCH_MX5
+ bool
+
+config SOC_IMX50
+ bool
+ select SOC_IMX5
+ select ARCH_MX50
+
+config SOC_IMX51
+ bool
+ select SOC_IMX5
+ select ARCH_MX5
+ select ARCH_MX51
+
+config SOC_IMX53
+ bool
+ select SOC_IMX5
+ select ARCH_MX5
+ select ARCH_MX53
if ARCH_IMX_V4_V5
Include support for VPR200 platform. This includes specific
configurations for the board and its peripherals.
+comment "i.MX5 platforms:"
+
+config MACH_MX50_RDP
+ bool "Support MX50 reference design platform"
+ depends on BROKEN
+ select SOC_IMX50
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ help
+ Include support for MX50 reference design platform (RDP) board. This
+ includes specific configurations for the board and its peripherals.
+
+comment "i.MX51 machines:"
+
+config MACH_IMX51_DT
+ bool "Support i.MX51 platforms from device tree"
+ select SOC_IMX51
+ select USE_OF
+ select MACH_MX51_BABBAGE
+ help
+ Include support for Freescale i.MX51 based platforms
+ using the device tree for discovery
+
+config MACH_MX51_BABBAGE
+ bool "Support MX51 BABBAGE platforms"
+ select SOC_IMX51
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ help
+ Include support for MX51 Babbage platform, also known as MX51EVK in
+ u-boot. This includes specific configurations for the board and its
+ peripherals.
+
+config MACH_MX51_3DS
+ bool "Support MX51PDK (3DS)"
+ select SOC_IMX51
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_KEYPAD
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select MXC_DEBUG_BOARD
+ help
+ Include support for MX51PDK (3DS) platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_EUKREA_CPUIMX51
+ bool "Support Eukrea CPUIMX51 module"
+ select SOC_IMX51
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ help
+ Include support for Eukrea CPUIMX51 platform. This includes
+ specific configurations for the module and its peripherals.
+
+choice
+ prompt "Baseboard"
+ depends on MACH_EUKREA_CPUIMX51
+ default MACH_EUKREA_MBIMX51_BASEBOARD
+
+config MACH_EUKREA_MBIMX51_BASEBOARD
+ prompt "Eukrea MBIMX51 development board"
+ bool
+ select IMX_HAVE_PLATFORM_IMX_KEYPAD
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select LEDS_GPIO_REGISTER
+ help
+ This adds board specific devices that can be found on Eukrea's
+ MBIMX51 evaluation board.
+
+endchoice
+
+config MACH_EUKREA_CPUIMX51SD
+ bool "Support Eukrea CPUIMX51SD module"
+ select SOC_IMX51
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ help
+ Include support for Eukrea CPUIMX51SD platform. This includes
+ specific configurations for the module and its peripherals.
+
+choice
+ prompt "Baseboard"
+ depends on MACH_EUKREA_CPUIMX51SD
+ default MACH_EUKREA_MBIMXSD51_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD51_BASEBOARD
+ prompt "Eukrea MBIMXSD development board"
+ bool
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select LEDS_GPIO_REGISTER
+ help
+ This adds board specific devices that can be found on Eukrea's
+ MBIMXSD evaluation board.
+
+endchoice
+
+config MX51_EFIKA_COMMON
+ bool
+ select SOC_IMX51
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_PATA_IMX
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select MXC_ULPI if USB_ULPI
+
+config MACH_MX51_EFIKAMX
+ bool "Support MX51 Genesi Efika MX nettop"
+ select LEDS_GPIO_REGISTER
+ select MX51_EFIKA_COMMON
+ help
+ Include support for Genesi Efika MX nettop. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX51_EFIKASB
+ bool "Support MX51 Genesi Efika Smartbook"
+ select LEDS_GPIO_REGISTER
+ select MX51_EFIKA_COMMON
+ help
+ Include support for Genesi Efika Smartbook. This includes specific
+ configurations for the board and its peripherals.
+
+comment "i.MX53 machines:"
+
+config MACH_IMX53_DT
+ bool "Support i.MX53 platforms from device tree"
+ select SOC_IMX53
+ select USE_OF
+ select MACH_MX53_ARD
+ select MACH_MX53_EVK
+ select MACH_MX53_LOCO
+ select MACH_MX53_SMD
+ help
+ Include support for Freescale i.MX53 based platforms
+ using the device tree for discovery
+
+config MACH_MX53_EVK
+ bool "Support MX53 EVK platforms"
+ select SOC_IMX53
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select LEDS_GPIO_REGISTER
+ help
+ Include support for MX53 EVK platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX53_SMD
+ bool "Support MX53 SMD platforms"
+ select SOC_IMX53
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ help
+ Include support for MX53 SMD platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX53_LOCO
+ bool "Support MX53 LOCO platforms"
+ select SOC_IMX53
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_GPIO_KEYS
+ select LEDS_GPIO_REGISTER
+ help
+ Include support for MX53 LOCO platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX53_ARD
+ bool "Support MX53 ARD platforms"
+ select SOC_IMX53
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_GPIO_KEYS
+ help
+ Include support for MX53 ARD platform. This includes specific
+ configurations for the board and its peripherals.
+
comment "i.MX6 family:"
config SOC_IMX6Q
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+
# Support for CMOS sensor interface
obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
endif
+
+# i.MX5 based machines
+obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
+obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o
+obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o
+obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o
+obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o
+obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += mach-cpuimx51.o
+obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
+obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o
+obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o
+obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
params_phys-$(CONFIG_SOC_IMX35) := 0x80000100
initrd_phys-$(CONFIG_SOC_IMX35) := 0x80800000
+zreladdr-$(CONFIG_SOC_IMX50) += 0x70008000
+params_phys-$(CONFIG_SOC_IMX50) := 0x70000100
+initrd_phys-$(CONFIG_SOC_IMX50) := 0x70800000
+
+zreladdr-$(CONFIG_SOC_IMX51) += 0x90008000
+params_phys-$(CONFIG_SOC_IMX51) := 0x90000100
+initrd_phys-$(CONFIG_SOC_IMX51) := 0x90800000
+
+zreladdr-$(CONFIG_SOC_IMX53) += 0x70008000
+params_phys-$(CONFIG_SOC_IMX53) := 0x70000100
+initrd_phys-$(CONFIG_SOC_IMX53) := 0x70800000
+
zreladdr-$(CONFIG_SOC_IMX6Q) += 0x10008000
params_phys-$(CONFIG_SOC_IMX6Q) := 0x10000100
initrd_phys-$(CONFIG_SOC_IMX6Q) := 0x10800000
DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+static unsigned long twd_clk_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk twd_clk = {
+ .parent = &arm_clk,
+ .get_rate = twd_clk_get_rate,
+};
+
static unsigned long pll2_200m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
_REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
_REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
_REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+ _REGISTER_CLOCK("smp_twd", NULL, twd_clk),
_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
_REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
_REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
--- /dev/null
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+
+#include <asm/div64.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "crm-regs-imx5.h"
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+
+static struct clk osc_clk;
+static struct clk pll1_main_clk;
+static struct clk pll1_sw_clk;
+static struct clk pll2_sw_clk;
+static struct clk pll3_sw_clk;
+static struct clk mx53_pll4_sw_clk;
+static struct clk lp_apm_clk;
+static struct clk periph_apm_clk;
+static struct clk ahb_clk;
+static struct clk ipg_clk;
+static struct clk usboh3_clk;
+static struct clk emi_fast_clk;
+static struct clk ipu_clk;
+static struct clk mipi_hsc1_clk;
+static struct clk esdhc1_clk;
+static struct clk esdhc2_clk;
+static struct clk esdhc3_mx53_clk;
+
+#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
+
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+ u32 max_pre, u32 max_post)
+{
+ if (div >= max_pre * max_post) {
+ *pre = max_pre;
+ *post = max_post;
+ } else if (div >= max_pre) {
+ u32 min_pre, temp_pre, old_err, err;
+ min_pre = DIV_ROUND_UP(div, max_post);
+ old_err = max_pre;
+ for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+ err = div % temp_pre;
+ if (err == 0) {
+ *pre = temp_pre;
+ break;
+ }
+ err = temp_pre - err;
+ if (err < old_err) {
+ old_err = err;
+ *pre = temp_pre;
+ }
+ }
+ *post = DIV_ROUND_UP(div, *pre);
+ } else {
+ *pre = div;
+ *post = 1;
+ }
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+ u32 reg = __raw_readl(clk->enable_reg);
+
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= mode << clk->enable_shift;
+
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_ccgr_enable(struct clk *clk)
+{
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
+ return 0;
+}
+
+static void _clk_ccgr_disable(struct clk *clk)
+{
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
+
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+ return 0;
+}
+
+static void _clk_ccgr_disable_inwait(struct clk *clk)
+{
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+ struct clk *m1, struct clk *m2, struct clk *m3)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else
+ BUG();
+
+ return -EINVAL;
+}
+
+static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
+{
+ if (pll == &pll1_main_clk)
+ return MX51_DPLL1_BASE;
+ else if (pll == &pll2_sw_clk)
+ return MX51_DPLL2_BASE;
+ else if (pll == &pll3_sw_clk)
+ return MX51_DPLL3_BASE;
+ else
+ BUG();
+
+ return NULL;
+}
+
+static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
+{
+ if (pll == &pll1_main_clk)
+ return MX53_DPLL1_BASE;
+ else if (pll == &pll2_sw_clk)
+ return MX53_DPLL2_BASE;
+ else if (pll == &pll3_sw_clk)
+ return MX53_DPLL3_BASE;
+ else if (pll == &mx53_pll4_sw_clk)
+ return MX53_DPLL4_BASE;
+ else
+ BUG();
+
+ return NULL;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+ if (cpu_is_mx51())
+ return _mx51_get_pll_base(pll);
+ else
+ return _mx53_get_pll_base(pll);
+}
+
+static unsigned long clk_pll_get_rate(struct clk *clk)
+{
+ long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+ unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+ void __iomem *pllbase;
+ s64 temp;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ pllbase = _get_pll_base(clk);
+
+ dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+ dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+ if (pll_hfsm == 0) {
+ dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+ dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+ dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+ } else {
+ dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+ dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+ dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+ }
+ pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+ mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+ mfi = (mfi <= 5) ? 5 : mfi;
+ mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+ mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+ /* Sign extend to 32-bits */
+ if (mfn >= 0x04000000) {
+ mfn |= 0xFC000000;
+ mfn_abs = -mfn;
+ }
+
+ ref_clk = 2 * parent_rate;
+ if (dbl != 0)
+ ref_clk *= 2;
+
+ ref_clk /= (pdf + 1);
+ temp = (u64) ref_clk * mfn_abs;
+ do_div(temp, mfd + 1);
+ if (mfn < 0)
+ temp = -temp;
+ temp = (ref_clk * mfi) + temp;
+
+ return temp;
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ void __iomem *pllbase;
+
+ long mfi, pdf, mfn, mfd = 999999;
+ s64 temp64;
+ unsigned long quad_parent_rate;
+ unsigned long pll_hfsm, dp_ctl;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ pllbase = _get_pll_base(clk);
+
+ quad_parent_rate = 4 * parent_rate;
+ pdf = mfi = -1;
+ while (++pdf < 16 && mfi < 5)
+ mfi = rate * (pdf+1) / quad_parent_rate;
+ if (mfi > 15)
+ return -EINVAL;
+ pdf--;
+
+ temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
+ do_div(temp64, quad_parent_rate/1000000);
+ mfn = (long)temp64;
+
+ dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ /* use dpdck0_2 */
+ __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+ pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+ if (pll_hfsm == 0) {
+ reg = mfi << 4 | pdf;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+ __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+ __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+ } else {
+ reg = mfi << 4 | pdf;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+ __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+ __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+ }
+
+ return 0;
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+ u32 reg;
+ void __iomem *pllbase;
+ int i = 0;
+
+ pllbase = _get_pll_base(clk);
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ if (reg & MXC_PLL_DP_CTL_UPEN)
+ return 0;
+
+ reg |= MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+ /* Wait for lock */
+ do {
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ if (reg & MXC_PLL_DP_CTL_LRF)
+ break;
+
+ udelay(1);
+ } while (++i < MAX_DPLL_WAIT_TRIES);
+
+ if (i == MAX_DPLL_WAIT_TRIES) {
+ pr_err("MX5: pll locking failed\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+ u32 reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, step;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ /* When switching from pll_main_clk to a bypass clock, first select a
+ * multiplexed clock in 'step_sel', then shift the glitchless mux
+ * 'pll1_sw_clk_sel'.
+ *
+ * When switching back, do it in reverse order
+ */
+ if (parent == &pll1_main_clk) {
+ /* Switch to pll1_main_clk */
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* step_clk mux switched to lp_apm, to save power. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+ reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
+ MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ } else {
+ if (parent == &lp_apm_clk) {
+ step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
+ } else if (parent == &pll2_sw_clk) {
+ step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
+ } else if (parent == &pll3_sw_clk) {
+ step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
+ } else
+ return -EINVAL;
+
+ reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+ reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Switch to step_clk */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ }
+ __raw_writel(reg, MXC_CCM_CCSR);
+ return 0;
+}
+
+static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (clk->parent == &pll2_sw_clk) {
+ div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+ MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+ } else if (clk->parent == &pll3_sw_clk) {
+ div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+ MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+ } else
+ div = 1;
+ return parent_rate / div;
+}
+
+static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll2_sw_clk)
+ reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+ else
+ reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+
+ __raw_writel(reg, MXC_CCM_CCSR);
+ return 0;
+}
+
+static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ if (parent == &osc_clk)
+ reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+ else
+ return -EINVAL;
+
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ return 0;
+}
+
+static unsigned long clk_cpu_get_rate(struct clk *clk)
+{
+ u32 cacrr, div;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+
+ return parent_rate / div;
+}
+
+static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, cpu_podf;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+ cpu_podf = parent_rate / rate - 1;
+ /* use post divider to change freq */
+ reg = __raw_readl(MXC_CCM_CACRR);
+ reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
+ reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CACRR);
+
+ return 0;
+}
+
+static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ int i = 0;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+
+ reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ /* Wait for lock */
+ do {
+ reg = __raw_readl(MXC_CCM_CDHIPR);
+ if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
+ break;
+
+ udelay(1);
+ } while (++i < MAX_DPLL_WAIT_TRIES);
+
+ if (i == MAX_DPLL_WAIT_TRIES) {
+ pr_err("MX5: Set parent for periph_apm clock failed\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+
+ if (parent == &pll2_sw_clk)
+ reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ else if (parent == &periph_apm_clk)
+ reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ else
+ return -EINVAL;
+
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ return 0;
+}
+
+static struct clk main_bus_clk = {
+ .parent = &pll2_sw_clk,
+ .set_parent = _clk_main_bus_set_parent,
+};
+
+static unsigned long clk_ahb_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+ MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+ return parent_rate / div;
+}
+
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ unsigned long parent_rate;
+ int i = 0;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div > 8 || div < 1 || ((parent_rate / div) != rate))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* Wait for lock */
+ do {
+ reg = __raw_readl(MXC_CCM_CDHIPR);
+ if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
+ break;
+
+ udelay(1);
+ } while (++i < MAX_DPLL_WAIT_TRIES);
+
+ if (i == MAX_DPLL_WAIT_TRIES) {
+ pr_err("MX5: clk_ahb_set_rate failed\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+ return parent_rate / div;
+}
+
+
+static int _clk_max_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_ccgr_enable(clk);
+
+ /* Handshake with MAX when LPM is entered. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ if (cpu_is_mx51())
+ reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ else if (cpu_is_mx53())
+ reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static void _clk_max_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_ccgr_disable_inwait(clk);
+
+ /* No Handshake with MAX when LPM is entered as its disabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ if (cpu_is_mx51())
+ reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ else if (cpu_is_mx53())
+ reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static unsigned long clk_ipg_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+ MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+ return parent_rate / div;
+}
+
+static unsigned long clk_ipg_per_get_rate(struct clk *clk)
+{
+ u32 reg, prediv1, prediv2, podf;
+ unsigned long parent_rate;
+
+ parent_rate = clk_get_rate(clk->parent);
+
+ if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+ /* the main_bus_clk is the one before the DVFS engine */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
+ prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
+ return parent_rate / (prediv1 * prediv2 * podf);
+ } else if (clk->parent == &ipg_clk)
+ return parent_rate;
+ else
+ BUG();
+}
+
+static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+
+ reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+ reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+
+ if (parent == &ipg_clk)
+ reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+ else if (parent == &lp_apm_clk)
+ reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+ else if (parent != &main_bus_clk)
+ return -EINVAL;
+
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+#define clk_nfc_set_parent NULL
+
+static unsigned long clk_nfc_get_rate(struct clk *clk)
+{
+ unsigned long rate;
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+ MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+ rate = clk_get_rate(clk->parent) / div;
+ WARN_ON(rate == 0);
+ return rate;
+}
+
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+
+ if (!rate)
+ return -EINVAL;
+
+ div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ if (div > 8)
+ return -EINVAL;
+
+ return parent_rate / div;
+
+}
+
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+
+ div = clk_get_rate(clk->parent) / rate;
+ if (div == 0)
+ div++;
+ if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+ }
+
+ return 0;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+ return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+ return external_low_reference;
+}
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+ return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+ return ckih2_reference;
+}
+
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+ MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
+{
+ unsigned long rate;
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
+ MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
+ rate = clk_get_rate(clk->parent) / div;
+
+ return rate;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+ .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk pll1_main_clk = {
+ .parent = &osc_clk,
+ .get_rate = clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+/* Clock tree block diagram (WIP):
+ * CCM: Clock Controller Module
+ *
+ * PLL output -> |
+ * | CCM Switcher -> CCM_CLK_ROOT_GEN ->
+ * PLL bypass -> |
+ *
+ */
+
+/* PLL1 SW supplies to ARM core */
+static struct clk pll1_sw_clk = {
+ .parent = &pll1_main_clk,
+ .set_parent = _clk_pll1_sw_set_parent,
+ .get_rate = clk_pll1_sw_get_rate,
+};
+
+/* PLL2 SW supplies to AXI/AHB/IP buses */
+static struct clk pll2_sw_clk = {
+ .parent = &osc_clk,
+ .get_rate = clk_pll_get_rate,
+ .set_rate = _clk_pll_set_rate,
+ .set_parent = _clk_pll2_sw_set_parent,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
+static struct clk pll3_sw_clk = {
+ .parent = &osc_clk,
+ .set_rate = _clk_pll_set_rate,
+ .get_rate = clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
+static struct clk mx53_pll4_sw_clk = {
+ .parent = &osc_clk,
+ .set_rate = _clk_pll_set_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+};
+
+/* Low-power Audio Playback Mode clock */
+static struct clk lp_apm_clk = {
+ .parent = &osc_clk,
+ .set_parent = _clk_lp_apm_set_parent,
+};
+
+static struct clk periph_apm_clk = {
+ .parent = &pll1_sw_clk,
+ .set_parent = _clk_periph_apm_set_parent,
+};
+
+static struct clk cpu_clk = {
+ .parent = &pll1_sw_clk,
+ .get_rate = clk_cpu_get_rate,
+ .set_rate = clk_cpu_set_rate,
+};
+
+static struct clk ahb_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = clk_ahb_get_rate,
+ .set_rate = _clk_ahb_set_rate,
+ .round_rate = _clk_ahb_round_rate,
+};
+
+static struct clk iim_clk = {
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+};
+
+/* Main IP interface clock for access to registers */
+static struct clk ipg_clk = {
+ .parent = &ahb_clk,
+ .get_rate = clk_ipg_get_rate,
+};
+
+static struct clk ipg_perclk = {
+ .parent = &lp_apm_clk,
+ .get_rate = clk_ipg_per_get_rate,
+ .set_parent = _clk_ipg_per_set_parent,
+};
+
+static struct clk ahb_max_clk = {
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+};
+
+static struct clk aips_tz1_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk aips_tz2_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk gpc_dvfs_clk = {
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable,
+};
+
+static struct clk gpt_32k_clk = {
+ .id = 0,
+ .parent = &ckil_clk,
+};
+
+static struct clk dummy_clk = {
+ .id = 0,
+};
+
+static struct clk emi_slow_clk = {
+ .parent = &pll2_sw_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable_inwait,
+ .get_rate = clk_emi_slow_get_rate,
+};
+
+static int clk_ipu_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_ccgr_enable(clk);
+
+ /* Enable handshake with IPU when certain clock rates are changed */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ /* Enable handshake with IPU when LPM is entered */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static void clk_ipu_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_ccgr_disable(clk);
+
+ /* Disable handshake with IPU whe dividers are changed */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg |= MXC_CCM_CCDR_IPU_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ /* Disable handshake with IPU when LPM is entered */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk ahbmux1_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk ipu_sec_clk = {
+ .parent = &emi_fast_clk,
+ .secondary = &ahbmux1_clk,
+};
+
+static struct clk ddr_hf_clk = {
+ .parent = &pll1_sw_clk,
+ .get_rate = _clk_ddr_hf_get_rate,
+};
+
+static struct clk ddr_clk = {
+ .parent = &ddr_hf_clk,
+};
+
+/* clock definitions for MIPI HSC unit which has been removed
+ * from documentation, but not from hardware
+ */
+static int _clk_hsc_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_ccgr_enable(clk);
+ /* Handshake with IPU when certain clock rates are changed. */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static void _clk_hsc_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_ccgr_disable(clk);
+ /* No handshake with HSC as its not enabled. */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk mipi_hsp_clk = {
+ .parent = &ipu_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_hsc_enable,
+ .disable = _clk_hsc_disable,
+ .secondary = &mipi_hsc1_clk,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = pfx##_get_rate, \
+ .set_rate = pfx##_set_rate, \
+ .round_rate = pfx##_round_rate, \
+ .set_parent = pfx##_set_parent, \
+ .enable = _clk_ccgr_enable, \
+ .disable = _clk_ccgr_disable, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = pfx##_get_rate, \
+ .set_rate = pfx##_set_rate, \
+ .set_parent = pfx##_set_parent, \
+ .enable = _clk_max_enable, \
+ .disable = _clk_max_disable, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+#define CLK_GET_RATE(name, nr, bitsname) \
+static unsigned long clk_##name##_get_rate(struct clk *clk) \
+{ \
+ u32 reg, pred, podf; \
+ \
+ reg = __raw_readl(MXC_CCM_CSCDR##nr); \
+ pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
+ >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
+ podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
+ >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
+ \
+ return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
+ (pred + 1) * (podf + 1)); \
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname) \
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
+{ \
+ u32 reg, mux; \
+ \
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
+ &pll3_sw_clk, &lp_apm_clk); \
+ reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
+ ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
+ reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
+ __raw_writel(reg, MXC_CCM_CSCMR##nr); \
+ \
+ return 0; \
+}
+
+#define CLK_SET_RATE(name, nr, bitsname) \
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
+{ \
+ u32 reg, div, parent_rate; \
+ u32 pre = 0, post = 0; \
+ \
+ parent_rate = clk_get_rate(clk->parent); \
+ div = parent_rate / rate; \
+ \
+ if ((parent_rate / div) != rate) \
+ return -EINVAL; \
+ \
+ __calc_pre_post_dividers(div, &pre, &post, \
+ (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
+ (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+ \
+ /* Set sdhc1 clock divider */ \
+ reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
+ ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
+ | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
+ reg |= (post - 1) << \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
+ reg |= (pre - 1) << \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
+ __raw_writel(reg, MXC_CCM_CSCDR##nr); \
+ \
+ return 0; \
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+ .parent = &pll2_sw_clk,
+ .get_rate = clk_uart_get_rate,
+ .set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+ .parent = &pll2_sw_clk,
+ .get_rate = clk_usboh3_get_rate,
+ .set_parent = clk_usboh3_set_parent,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+};
+
+static struct clk usb_ahb_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+};
+
+static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+
+ if (parent == &pll3_sw_clk)
+ reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk usb_phy1_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = clk_usb_phy1_set_parent,
+ .enable = _clk_ccgr_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_ccgr_disable,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+ .parent = &pll3_sw_clk,
+ .get_rate = clk_ecspi_get_rate,
+ .set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+/* mx51 specific */
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk)
+ reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+ else if (parent == &esdhc2_clk)
+ reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+ else
+ return -EINVAL;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk)
+ reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else if (parent == &esdhc2_clk)
+ reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else
+ return -EINVAL;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+/* mx53 specific */
+static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk)
+ reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+ else if (parent == &esdhc3_mx53_clk)
+ reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+ else
+ return -EINVAL;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+
+static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk)
+ reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else if (parent == &esdhc3_mx53_clk)
+ reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else
+ return -EINVAL;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = gr, \
+ .set_rate = sr, \
+ .enable = e, \
+ .disable = d, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
+ DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
+
+/* Shared peripheral bus arbiter */
+DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+
+/* UART */
+DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
+ NULL, NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
+ NULL, NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart4_ipg_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart5_ipg_clk);
+
+/* GPT */
+DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &ipg_clk, &gpt_ipg_clk);
+
+DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
+ NULL, NULL, &ipg_perclk, NULL);
+
+/* I2C */
+DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
+ NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, &ipg_perclk, NULL);
+
+/* FEC */
+DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+ clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
+ NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+ &ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+ NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+ &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+ NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+ NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+ NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+ clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+
+/* mx51 specific */
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+ clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc3_clk = {
+ .id = 2,
+ .parent = &esdhc1_clk,
+ .set_parent = clk_esdhc3_set_parent,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+ .secondary = &esdhc3_ipg_clk,
+};
+static struct clk esdhc4_clk = {
+ .id = 3,
+ .parent = &esdhc1_clk,
+ .set_parent = clk_esdhc4_set_parent,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+ .secondary = &esdhc4_ipg_clk,
+};
+
+/* mx53 specific */
+static struct clk esdhc2_mx53_clk = {
+ .id = 2,
+ .parent = &esdhc1_clk,
+ .set_parent = clk_esdhc2_mx53_set_parent,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+ .secondary = &esdhc3_ipg_clk,
+};
+
+DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
+ clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc4_mx53_clk = {
+ .id = 3,
+ .parent = &esdhc1_clk,
+ .set_parent = clk_esdhc4_mx53_set_parent,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+ .secondary = &esdhc4_ipg_clk,
+};
+
+static struct clk sata_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_max_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+ .parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+ .parent = &ahb_clk,
+};
+
+DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
+
+/* IPU */
+DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
+ NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
+
+DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
+ NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
+ &ddr_clk, NULL);
+
+DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
+ NULL, NULL, &pll3_sw_clk, NULL);
+DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, &pll3_sw_clk, NULL);
+
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ },
+
+static struct clk_lookup mx51_lookups[] = {
+ /* i.mx51 has the i.mx21 type uart */
+ _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+ _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+ _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+ /* i.mx51 has the i.mx27 type fec */
+ _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
+ _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
+ _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
+ _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+ _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
+ _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
+ _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
+ _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
+ _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
+ _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
+ _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
+ _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
+ _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
+ _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
+ _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+ _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+ _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+ _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+ _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+ /* i.mx51 has the i.mx35 type sdma */
+ _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+ _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+ _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+ _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+ _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+ /* i.mx51 has the i.mx35 type cspi */
+ _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
+ _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+ _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+ _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+ _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
+ _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
+ _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
+ _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+ _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+};
+
+static struct clk_lookup mx53_lookups[] = {
+ /* i.mx53 has the i.mx21 type uart */
+ _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+ _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+ _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+ _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+ _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+ /* i.mx53 has the i.mx25 type fec */
+ _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+ _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
+ /* i.mx53 has the i.mx51 type ecspi */
+ _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+ _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+ /* i.mx53 has the i.mx25 type cspi */
+ _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
+ _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+ _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+ /* i.mx53 has the i.mx35 type sdma */
+ _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+ _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+ _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+ _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+ _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+ _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+ _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+ _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
+};
+
+static void clk_tree_init(void)
+{
+ u32 reg;
+
+ ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+
+ /*
+ * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+ * 8MHz, its derived from lp_apm.
+ *
+ * FIXME: Verify if true for all boards
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+ reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+}
+
+int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
+ unsigned long ckih1, unsigned long ckih2)
+{
+ int i;
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ ckih2_reference = ckih2;
+ oscillator_reference = osc;
+
+ for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
+ clkdev_add(&mx51_lookups[i]);
+
+ clk_tree_init();
+
+ clk_enable(&cpu_clk);
+ clk_enable(&main_bus_clk);
+
+ clk_enable(&iim_clk);
+ imx_print_silicon_rev("i.MX51", mx51_revision());
+ clk_disable(&iim_clk);
+
+ /* move usb_phy_clk to 24MHz */
+ clk_set_parent(&usb_phy1_clk, &osc_clk);
+
+ /* set the usboh3_clk parent to pll2_sw_clk */
+ clk_set_parent(&usboh3_clk, &pll2_sw_clk);
+
+ /* Set SDHC parents to be PLL2 */
+ clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+ clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+ /* set SDHC root clock as 166.25MHZ*/
+ clk_set_rate(&esdhc1_clk, 166250000);
+ clk_set_rate(&esdhc2_clk, 166250000);
+
+ /* System timer */
+ mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+ MX51_INT_GPT);
+ return 0;
+}
+
+int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
+ unsigned long ckih1, unsigned long ckih2)
+{
+ int i;
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ ckih2_reference = ckih2;
+ oscillator_reference = osc;
+
+ for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
+ clkdev_add(&mx53_lookups[i]);
+
+ clk_tree_init();
+
+ clk_set_parent(&uart_root_clk, &pll3_sw_clk);
+ clk_enable(&cpu_clk);
+ clk_enable(&main_bus_clk);
+
+ clk_enable(&iim_clk);
+ imx_print_silicon_rev("i.MX53", mx53_revision());
+ clk_disable(&iim_clk);
+
+ /* Set SDHC parents to be PLL2 */
+ clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+ clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
+
+ /* set SDHC root clock as 200MHZ*/
+ clk_set_rate(&esdhc1_clk, 200000000);
+ clk_set_rate(&esdhc3_mx53_clk, 200000000);
+
+ /* System timer */
+ mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+ MX53_INT_GPT);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+ unsigned long *ckih1, unsigned long *ckih2)
+{
+ struct device_node *np;
+
+ /* retrieve the freqency of fixed clocks from device tree */
+ for_each_compatible_node(np, NULL, "fixed-clock") {
+ u32 rate;
+ if (of_property_read_u32(np, "clock-frequency", &rate))
+ continue;
+
+ if (of_device_is_compatible(np, "fsl,imx-ckil"))
+ *ckil = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-osc"))
+ *osc = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+ *ckih1 = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+ *ckih2 = rate;
+ }
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+ unsigned long ckil, osc, ckih1, ckih2;
+
+ clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+ return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+ unsigned long ckil, osc, ckih1, ckih2;
+
+ clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+ return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
+#endif
--- /dev/null
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * This file contains the CPU initialization code.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+static int mx5_cpu_rev = -1;
+
+#define IIM_SREV 0x24
+#define MX50_HW_ADADIG_DIGPROG 0xB0
+
+static int get_mx51_srev(void)
+{
+ void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
+ u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+ switch (rev) {
+ case 0x0:
+ return IMX_CHIP_REVISION_2_0;
+ case 0x10:
+ return IMX_CHIP_REVISION_3_0;
+ default:
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
+}
+
+/*
+ * Returns:
+ * the silicon revision of the cpu
+ * -EINVAL - not a mx51
+ */
+int mx51_revision(void)
+{
+ if (!cpu_is_mx51())
+ return -EINVAL;
+
+ if (mx5_cpu_rev == -1)
+ mx5_cpu_rev = get_mx51_srev();
+
+ return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx51_revision);
+
+#ifdef CONFIG_NEON
+
+/*
+ * All versions of the silicon before Rev. 3 have broken NEON implementations.
+ * Dependent on link order - so the assumption is that vfp_init is called
+ * before us.
+ */
+static int __init mx51_neon_fixup(void)
+{
+ if (!cpu_is_mx51())
+ return 0;
+
+ if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
+ (elf_hwcap & HWCAP_NEON)) {
+ elf_hwcap &= ~HWCAP_NEON;
+ pr_info("Turning off NEON support, detected broken NEON implementation\n");
+ }
+ return 0;
+}
+
+late_initcall(mx51_neon_fixup);
+#endif
+
+static int get_mx53_srev(void)
+{
+ void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
+ u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+ switch (rev) {
+ case 0x0:
+ return IMX_CHIP_REVISION_1_0;
+ case 0x2:
+ return IMX_CHIP_REVISION_2_0;
+ case 0x3:
+ return IMX_CHIP_REVISION_2_1;
+ default:
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
+}
+
+/*
+ * Returns:
+ * the silicon revision of the cpu
+ * -EINVAL - not a mx53
+ */
+int mx53_revision(void)
+{
+ if (!cpu_is_mx53())
+ return -EINVAL;
+
+ if (mx5_cpu_rev == -1)
+ mx5_cpu_rev = get_mx53_srev();
+
+ return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx53_revision);
+
+static int get_mx50_srev(void)
+{
+ void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
+ u32 rev;
+
+ if (!anatop) {
+ mx5_cpu_rev = -EINVAL;
+ return 0;
+ }
+
+ rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
+ rev &= 0xff;
+
+ iounmap(anatop);
+ if (rev == 0x0)
+ return IMX_CHIP_REVISION_1_0;
+ else if (rev == 0x1)
+ return IMX_CHIP_REVISION_1_1;
+ return 0;
+}
+
+/*
+ * Returns:
+ * the silicon revision of the cpu
+ * -EINVAL - not a mx50
+ */
+int mx50_revision(void)
+{
+ if (!cpu_is_mx50())
+ return -EINVAL;
+
+ if (mx5_cpu_rev == -1)
+ mx5_cpu_rev = get_mx50_srev();
+
+ return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx50_revision);
+
+static int __init post_cpu_init(void)
+{
+ unsigned int reg;
+ void __iomem *base;
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ if (cpu_is_mx51())
+ base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
+ else
+ base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
+
+ __raw_writel(0x0, base + 0x40);
+ __raw_writel(0x0, base + 0x44);
+ __raw_writel(0x0, base + 0x48);
+ __raw_writel(0x0, base + 0x4C);
+ reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+ __raw_writel(reg, base + 0x50);
+
+ if (cpu_is_mx51())
+ base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
+ else
+ base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
+
+ __raw_writel(0x0, base + 0x40);
+ __raw_writel(0x0, base + 0x44);
+ __raw_writel(0x0, base + 0x48);
+ __raw_writel(0x0, base + 0x4C);
+ reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+ __raw_writel(reg, base + 0x50);
+ }
+
+ return 0;
+}
+
+postcore_initcall(post_cpu_init);
--- /dev/null
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/types.h>
+#include <mach/hardware.h>
+#include <linux/kernel.h>
+
+static struct cpu_op mx51_cpu_op[] = {
+ {
+ .cpu_rate = 160000000,},
+ {
+ .cpu_rate = 800000000,},
+};
+
+struct cpu_op *mx51_get_cpu_op(int *op)
+{
+ *op = ARRAY_SIZE(mx51_cpu_op);
+ return mx51_cpu_op;
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+extern struct cpu_op *mx51_get_cpu_op(int *op);
--- /dev/null
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+
+#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
+#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
+#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
+#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
+#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
+#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
+
+/*MX53*/
+#define MX53_CCM_BASE MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
+#define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
+#define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
+#define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+
+/* PLL Register Offsets */
+#define MXC_PLL_DP_CTL 0x00
+#define MXC_PLL_DP_CONFIG 0x04
+#define MXC_PLL_DP_OP 0x08
+#define MXC_PLL_DP_MFD 0x0C
+#define MXC_PLL_DP_MFN 0x10
+#define MXC_PLL_DP_MFNMINUS 0x14
+#define MXC_PLL_DP_MFNPLUS 0x18
+#define MXC_PLL_DP_HFS_OP 0x1C
+#define MXC_PLL_DP_HFS_MFD 0x20
+#define MXC_PLL_DP_HFS_MFN 0x24
+#define MXC_PLL_DP_MFN_TOGC 0x28
+#define MXC_PLL_DP_DESTAT 0x2c
+
+/* PLL Register Bit definitions */
+#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000
+#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000
+#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12
+#define MXC_PLL_DP_CTL_ADE 0x800
+#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8)
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8
+#define MXC_PLL_DP_CTL_HFSM 0x80
+#define MXC_PLL_DP_CTL_PRE 0x40
+#define MXC_PLL_DP_CTL_UPEN 0x20
+#define MXC_PLL_DP_CTL_RST 0x10
+#define MXC_PLL_DP_CTL_RCP 0x8
+#define MXC_PLL_DP_CTL_PLM 0x4
+#define MXC_PLL_DP_CTL_BRM0 0x2
+#define MXC_PLL_DP_CTL_LRF 0x1
+
+#define MXC_PLL_DP_CONFIG_BIST 0x8
+#define MXC_PLL_DP_CONFIG_SJC_CE 0x4
+#define MXC_PLL_DP_CONFIG_AREN 0x2
+#define MXC_PLL_DP_CONFIG_LDREQ 0x1
+
+#define MXC_PLL_DP_OP_MFI_OFFSET 4
+#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4)
+#define MXC_PLL_DP_OP_PDF_OFFSET 0
+#define MXC_PLL_DP_OP_PDF_MASK 0xF
+
+#define MXC_PLL_DP_MFD_OFFSET 0
+#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_OFFSET 0x0
+#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17)
+#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16)
+#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0
+#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF
+
+#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31)
+#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF
+
+/* Register addresses of CCM*/
+#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00)
+#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04)
+#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08)
+#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C)
+#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10)
+#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14)
+#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18)
+#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C)
+#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20)
+#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24)
+#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28)
+#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C)
+#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30)
+#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34)
+#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38)
+#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C)
+#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40)
+#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44)
+#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48)
+#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C)
+#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50)
+#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54)
+#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58)
+#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C)
+#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60)
+#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64)
+#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68)
+#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C)
+#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70)
+#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74)
+#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78)
+#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C)
+#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84)
+
+#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84)
+
+/* Define the bits in register CCR */
+#define MXC_CCM_CCR_COSC_EN (1 << 12)
+#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11)
+#define MXC_CCM_CCR_CAMP2_EN (1 << 10)
+#define MXC_CCM_CCR_CAMP1_EN (1 << 9)
+#define MXC_CCM_CCR_FPM_EN (1 << 8)
+#define MXC_CCM_CCR_OSCNT_OFFSET (0)
+#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
+
+/* Define the bits in register CCDR */
+#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18)
+#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
+#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16)
+
+/* Define the bits in register CSR */
+#define MXC_CCM_CSR_COSR_READY (1 << 5)
+#define MXC_CCM_CSR_LVS_VALUE (1 << 4)
+#define MXC_CCM_CSR_CAMP2_READY (1 << 3)
+#define MXC_CCM_CSR_CAMP1_READY (1 << 2)
+#define MXC_CCM_CSR_FPM_READY (1 << 1)
+#define MXC_CCM_CSR_REF_EN_B (1 << 0)
+
+/* Define the bits in register CCSR */
+#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9)
+#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7)
+#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7)
+#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0
+#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */
+#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
+#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
+#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5)
+#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5)
+#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3)
+#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3)
+#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk,
+ 1: step_clk */
+#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1)
+#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0)
+
+/* Define the bits in register CACRR */
+#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0)
+#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7)
+
+/* Define the bits in register CBCDR */
+#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26)
+#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
+#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30)
+#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30)
+#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27)
+#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27)
+#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22)
+#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22)
+#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19)
+#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16)
+#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16)
+#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13)
+#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13)
+#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10)
+#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
+#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8)
+#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3)
+#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0)
+#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7)
+
+/* Define the bits in register CBCMR */
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1)
+#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0)
+
+/* Define the bits in register CSCMR1 */
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30)
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20)
+#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL (0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11)
+#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8)
+#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7)
+#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2)
+#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1)
+#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1)
+
+/* Define the bits in register CSCMR2 */
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3)
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3))
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24)
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10)
+#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6)
+#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5)
+#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3)
+
+/* Define the bits in register CSCDR1 */
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7)
+
+/* Define the bits in register CS1CDR and CS2CDR */
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F)
+
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F)
+
+/* Define the bits in register CDCDR */
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28)
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7)
+
+/* Define the bits in register CHSCCDR */
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7)
+
+/* Define the bits in register CSCDR2 */
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9)
+#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F)
+
+/* Define the bits in register CSCDR3 */
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F)
+
+/* Define the bits in register CSCDR4 */
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F)
+
+/* Define the bits in register CDHIPR */
+#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
+#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8)
+#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7)
+#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6)
+#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5)
+#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4)
+#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3)
+#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2)
+#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1)
+#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0)
+
+/* Define the bits in register CDCR */
+#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3)
+
+/* Define the bits in register CLPCR */
+#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23)
+#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22)
+#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21)
+#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25)
+#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20)
+#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19)
+#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
+#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17)
+#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16)
+#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11)
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9)
+#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
+#define MXC_CCM_CLPCR_VSTBY (0x1 << 8)
+#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7)
+#define MXC_CCM_CLPCR_SBYOS (0x1 << 6)
+#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
+#define MXC_CCM_CLPCR_LPM_OFFSET (0)
+#define MXC_CCM_CLPCR_LPM_MASK (0x3)
+
+/* Define the bits in register CISR */
+#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25)
+#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
+#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20)
+#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19)
+#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18)
+#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17)
+#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16)
+#define MXC_CCM_CISR_COSC_READY (0x1 << 6)
+#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5)
+#define MXC_CCM_CISR_CKIH_READY (0x1 << 4)
+#define MXC_CCM_CISR_FPM_READY (0x1 << 3)
+#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2)
+#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1)
+#define MXC_CCM_CISR_LRF_PLL1 (0x1)
+
+/* Define the bits in register CIMR */
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25)
+#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
+#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20)
+#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19)
+#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18)
+#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17)
+#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16)
+#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5)
+#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4)
+#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3)
+#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2)
+#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1)
+#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1)
+
+/* Define the bits in register CCOSR */
+#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24)
+#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21)
+#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21)
+#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16)
+#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16)
+#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7)
+#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4)
+#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4)
+#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0)
+#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF)
+
+/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4)
+#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7)
+
+/* Define the bits in registers CCGRx */
+#define MXC_CCM_CCGRx_CG_MASK 0x3
+#define MXC_CCM_CCGRx_MOD_OFF 0x0
+#define MXC_CCM_CCGRx_MOD_ON 0x3
+#define MXC_CCM_CCGRx_MOD_IDLE 0x1
+
+#define MXC_CCM_CCGRx_CG15_MASK (0x3 << 30)
+#define MXC_CCM_CCGRx_CG14_MASK (0x3 << 28)
+#define MXC_CCM_CCGRx_CG13_MASK (0x3 << 26)
+#define MXC_CCM_CCGRx_CG12_MASK (0x3 << 24)
+#define MXC_CCM_CCGRx_CG11_MASK (0x3 << 22)
+#define MXC_CCM_CCGRx_CG10_MASK (0x3 << 20)
+#define MXC_CCM_CCGRx_CG9_MASK (0x3 << 18)
+#define MXC_CCM_CCGRx_CG8_MASK (0x3 << 16)
+#define MXC_CCM_CCGRx_CG5_MASK (0x3 << 10)
+#define MXC_CCM_CCGRx_CG4_MASK (0x3 << 8)
+#define MXC_CCM_CCGRx_CG3_MASK (0x3 << 6)
+#define MXC_CCM_CCGRx_CG2_MASK (0x3 << 4)
+#define MXC_CCM_CCGRx_CG1_MASK (0x3 << 2)
+#define MXC_CCM_CCGRx_CG0_MASK (0x3 << 0)
+
+#define MXC_CCM_CCGRx_CG15_OFFSET 30
+#define MXC_CCM_CCGRx_CG14_OFFSET 28
+#define MXC_CCM_CCGRx_CG13_OFFSET 26
+#define MXC_CCM_CCGRx_CG12_OFFSET 24
+#define MXC_CCM_CCGRx_CG11_OFFSET 22
+#define MXC_CCM_CCGRx_CG10_OFFSET 20
+#define MXC_CCM_CCGRx_CG9_OFFSET 18
+#define MXC_CCM_CCGRx_CG8_OFFSET 16
+#define MXC_CCM_CCGRx_CG7_OFFSET 14
+#define MXC_CCM_CCGRx_CG6_OFFSET 12
+#define MXC_CCM_CCGRx_CG5_OFFSET 10
+#define MXC_CCM_CCGRx_CG4_OFFSET 8
+#define MXC_CCM_CCGRx_CG3_OFFSET 6
+#define MXC_CCM_CCGRx_CG2_OFFSET 4
+#define MXC_CCM_CCGRx_CG1_OFFSET 2
+#define MXC_CCM_CCGRx_CG0_OFFSET 0
+
+#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80)
+#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100)
+#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180)
+#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0)
+#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220)
+#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240)
+#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260)
+#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280)
+#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0)
+#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0)
+#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0)
+#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0)
+#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300)
+
+/* CORTEXA8 platform */
+#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0)
+#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4)
+#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8)
+#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC)
+#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10)
+#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14)
+#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18)
+#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20)
+#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24)
+
+/* DVFS CORE */
+#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00)
+#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04)
+#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08)
+#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C)
+#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10)
+#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14)
+#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18)
+#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C)
+#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20)
+#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24)
+#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28)
+#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C)
+#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30)
+#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34)
+#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38)
+#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C)
+#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40)
+
+/* GPC */
+#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0)
+#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4)
+#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8)
+#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC)
+#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10)
+#define MXC_GPC_PGR_ARMPG_OFFSET 8
+#define MXC_GPC_PGR_ARMPG_MASK (3 << 8)
+
+/* PGC */
+#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0)
+#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC)
+#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0)
+#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC)
+#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0)
+#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC)
+
+#define MXC_PGCR_PCR 1
+#define MXC_SRPGCR_PCR 1
+#define MXC_EMPGCR_PCR 1
+#define MXC_PGSR_PSR 1
+
+
+#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0)
+#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1)
+
+/* SRPG */
+#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0)
+#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4)
+#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8)
+
+#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0)
+#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4)
+#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0)
+#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4)
+#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0)
+#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4)
+#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8)
+
+#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0)
+#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4)
+#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8)
+
+#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0)
+#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4)
+#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8)
+
+#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
--- /dev/null
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <mach/mx50.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
+#define imx50_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
+
+extern const struct imx_fec_data imx50_fec_data;
+#define imx50_add_fec(pdata) \
+ imx_add_fec(&imx50_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
+#define imx50_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
--- /dev/null
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx51_fec_data;
+#define imx51_add_fec(pdata) \
+ imx_add_fec(&imx51_fec_data, pdata)
+
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata) \
+ imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
+#define imx51_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata) \
+ imx51_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
+#define imx51_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
+#define imx51_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata) \
+ imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata) \
+ imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
+#define imx51_add_mxc_nand(pdata) \
+ imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
+#define imx51_add_sdhci_esdhc_imx(id, pdata) \
+ imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data;
+#define imx51_add_cspi(pdata) \
+ imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[];
+#define imx51_add_ecspi(id, pdata) \
+ imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
+#define imx51_add_imx2_wdt(id, pdata) \
+ imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
+
+extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
+#define imx51_add_mxc_pwm(id) \
+ imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
+
+extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
+#define imx51_add_imx_keypad(pdata) \
+ imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+ imx_add_pata_imx(&imx51_pata_imx_data)
--- /dev/null
+/*
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx53.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx53_fec_data;
+#define imx53_add_fec(pdata) \
+ imx_add_fec(&imx53_fec_data, pdata)
+
+extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
+#define imx53_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
+
+
+extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
+#define imx53_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
+#define imx53_add_sdhci_esdhc_imx(id, pdata) \
+ imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx53_ecspi_data[];
+#define imx53_add_ecspi(id, pdata) \
+ imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
+#define imx53_add_imx2_wdt(id, pdata) \
+ imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
+
+extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
+#define imx53_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
+#define imx53_add_imx_keypad(pdata) \
+ imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+ imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
--- /dev/null
+#ifndef _EFIKA_H
+#define _EFIKA_H
+
+#define EFIKA_WLAN_EN IMX_GPIO_NR(2, 16)
+#define EFIKA_WLAN_RESET IMX_GPIO_NR(2, 10)
+#define EFIKA_USB_PHY_RESET IMX_GPIO_NR(2, 9)
+
+void __init efika_board_common_init(void);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define MXC_OTG_OFFSET 0
+#define MXC_H1_OFFSET 0x200
+#define MXC_H2_OFFSET 0x400
+
+/* USB_CTRL */
+#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */
+#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */
+#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */
+#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */
+#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */
+
+/* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */
+
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT (1 << 4)
+
+#define MXC_USBCMD_OFFSET 0x140
+
+/* USBCMD */
+#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
+
+int mx51_initialize_usb_hw(int port, unsigned int flags)
+{
+ unsigned int v;
+ void __iomem *usb_base;
+ void __iomem *usbotg_base;
+ void __iomem *usbother_base;
+ int ret = 0;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base) {
+ printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ switch (port) {
+ case 0: /* OTG port */
+ usbotg_base = usb_base + MXC_OTG_OFFSET;
+ break;
+ case 1: /* Host 1 port */
+ usbotg_base = usb_base + MXC_H1_OFFSET;
+ break;
+ case 2: /* Host 2 port */
+ usbotg_base = usb_base + MXC_H2_OFFSET;
+ break;
+ default:
+ printk(KERN_ERR"%s no such port %d\n", __func__, port);
+ ret = -ENOENT;
+ goto error;
+ }
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ switch (port) {
+ case 0: /*OTG port */
+ if (flags & MXC_EHCI_INTERNAL_PHY) {
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+ if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+ /* OC/USBPWR is not used */
+ v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+ } else {
+ /* OC/USBPWR is used */
+ v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+ }
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+ v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+ if (flags & MXC_EHCI_WAKEUP_ENABLED)
+ v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
+ else
+ v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+ if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+ v |= MXC_OTG_UCTRL_OPM_BIT;
+ else
+ v &= ~MXC_OTG_UCTRL_OPM_BIT;
+ __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+ }
+ break;
+ case 1: /* Host 1 */
+ /*Host ULPI */
+ v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+ if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+ /* HOST1 wakeup/ULPI intr enable */
+ v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+ } else {
+ /* HOST1 wakeup/ULPI intr disable */
+ v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+ }
+
+ if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+ v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+ else
+ v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+ __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+ if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+ v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
+ else
+ v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+ v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
+ if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
+ /* Interrupt Threshold Control:Immediate (no threshold) */
+ v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
+ __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
+ break;
+ case 2: /* Host 2 ULPI */
+ v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+ if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+ /* HOST1 wakeup/ULPI intr enable */
+ v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+ } else {
+ /* HOST1 wakeup/ULPI intr disable */
+ v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+ }
+
+ if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+ v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+ else
+ v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+ __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+ break;
+ }
+
+error:
+ iounmap(usb_base);
+ return ret;
+}
+
--- /dev/null
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/leds.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/mach/arch.h>
+
+#include "devices-imx51.h"
+
+#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30)
+#define MBIMX51_LED0 IMX_GPIO_NR(3, 5)
+#define MBIMX51_LED1 IMX_GPIO_NR(3, 6)
+#define MBIMX51_LED2 IMX_GPIO_NR(3, 7)
+#define MBIMX51_LED3 IMX_GPIO_NR(3, 8)
+
+static const struct gpio_led mbimx51_leds[] __initconst = {
+ {
+ .name = "led0",
+ .default_trigger = "heartbeat",
+ .active_low = 1,
+ .gpio = MBIMX51_LED0,
+ },
+ {
+ .name = "led1",
+ .default_trigger = "nand-disk",
+ .active_low = 1,
+ .gpio = MBIMX51_LED1,
+ },
+ {
+ .name = "led2",
+ .default_trigger = "mmc0",
+ .active_low = 1,
+ .gpio = MBIMX51_LED2,
+ },
+ {
+ .name = "led3",
+ .default_trigger = "default-on",
+ .active_low = 1,
+ .gpio = MBIMX51_LED3,
+ },
+};
+
+static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
+ .leds = mbimx51_leds,
+ .num_leds = ARRAY_SIZE(mbimx51_leds),
+};
+
+static iomux_v3_cfg_t mbimx51_pads[] = {
+ /* UART2 */
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+
+ /* UART3 */
+ MX51_PAD_UART3_RXD__UART3_RXD,
+ MX51_PAD_UART3_TXD__UART3_TXD,
+ MX51_PAD_KEY_COL4__UART3_RTS,
+ MX51_PAD_KEY_COL5__UART3_CTS,
+
+ /* TSC2007 IRQ */
+ MX51_PAD_NANDF_D10__GPIO3_30,
+
+ /* LEDS */
+ MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
+ MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
+ MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
+ MX51_PAD_DISPB2_SER_RS__GPIO3_8,
+
+ /* KPP */
+ MX51_PAD_KEY_ROW0__KEY_ROW0,
+ MX51_PAD_KEY_ROW1__KEY_ROW1,
+ MX51_PAD_KEY_ROW2__KEY_ROW2,
+ MX51_PAD_KEY_ROW3__KEY_ROW3,
+ MX51_PAD_KEY_COL0__KEY_COL0,
+ MX51_PAD_KEY_COL1__KEY_COL1,
+ MX51_PAD_KEY_COL2__KEY_COL2,
+ MX51_PAD_KEY_COL3__KEY_COL3,
+
+ /* SD 1 */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+ /* SD 2 */
+ MX51_PAD_SD2_CMD__SD2_CMD,
+ MX51_PAD_SD2_CLK__SD2_CLK,
+ MX51_PAD_SD2_DATA0__SD2_DATA0,
+ MX51_PAD_SD2_DATA1__SD2_DATA1,
+ MX51_PAD_SD2_DATA2__SD2_DATA2,
+ MX51_PAD_SD2_DATA3__SD2_DATA3,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mbimx51_keymap[] = {
+ KEY(0, 0, KEY_1),
+ KEY(0, 1, KEY_2),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_UP),
+
+ KEY(1, 0, KEY_4),
+ KEY(1, 1, KEY_5),
+ KEY(1, 2, KEY_6),
+ KEY(1, 3, KEY_LEFT),
+
+ KEY(2, 0, KEY_7),
+ KEY(2, 1, KEY_8),
+ KEY(2, 2, KEY_9),
+ KEY(2, 3, KEY_RIGHT),
+
+ KEY(3, 0, KEY_0),
+ KEY(3, 1, KEY_DOWN),
+ KEY(3, 2, KEY_ESC),
+ KEY(3, 3, KEY_ENTER),
+};
+
+static const struct matrix_keymap_data mbimx51_map_data __initconst = {
+ .keymap = mbimx51_keymap,
+ .keymap_size = ARRAY_SIZE(mbimx51_keymap),
+};
+
+static int tsc2007_get_pendown_state(void)
+{
+ return !gpio_get_value(MBIMX51_TSC2007_GPIO);
+}
+
+struct tsc2007_platform_data tsc2007_data = {
+ .model = 2007,
+ .x_plate_ohms = 180,
+ .get_pendown_state = tsc2007_get_pendown_state,
+};
+
+static struct i2c_board_info mbimx51_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("tsc2007", 0x49),
+ .irq = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
+ .platform_data = &tsc2007_data,
+ }, {
+ I2C_BOARD_INFO("tlv320aic23", 0x1a),
+ },
+};
+
+/*
+ * baseboard initialization.
+ */
+void __init eukrea_mbimx51_baseboard_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
+ ARRAY_SIZE(mbimx51_pads));
+
+ imx51_add_imx_uart(1, NULL);
+ imx51_add_imx_uart(2, &uart_pdata);
+
+ gpio_request(MBIMX51_LED0, "LED0");
+ gpio_direction_output(MBIMX51_LED0, 1);
+ gpio_free(MBIMX51_LED0);
+ gpio_request(MBIMX51_LED1, "LED1");
+ gpio_direction_output(MBIMX51_LED1, 1);
+ gpio_free(MBIMX51_LED1);
+ gpio_request(MBIMX51_LED2, "LED2");
+ gpio_direction_output(MBIMX51_LED2, 1);
+ gpio_free(MBIMX51_LED2);
+ gpio_request(MBIMX51_LED3, "LED3");
+ gpio_direction_output(MBIMX51_LED3, 1);
+ gpio_free(MBIMX51_LED3);
+
+ gpio_led_register_device(-1, &mbimx51_leds_info);
+
+ imx51_add_imx_keypad(&mbimx51_map_data);
+
+ gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
+ gpio_direction_input(MBIMX51_TSC2007_GPIO);
+ irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
+ IRQF_TRIGGER_FALLING);
+ i2c_register_board_info(1, mbimx51_i2c_devices,
+ ARRAY_SIZE(mbimx51_i2c_devices));
+
+ imx51_add_sdhci_esdhc_imx(0, NULL);
+ imx51_add_sdhci_esdhc_imx(1, NULL);
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx51.h>
+#include <mach/audmux.h>
+
+#include "devices-imx51.h"
+
+static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
+ /* LED */
+ MX51_PAD_NANDF_D10__GPIO3_30,
+ /* SWITCH */
+ NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
+ PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+ PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+ /* UART2 */
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+ /* UART 3 */
+ MX51_PAD_UART3_RXD__UART3_RXD,
+ MX51_PAD_UART3_TXD__UART3_TXD,
+ MX51_PAD_KEY_COL4__UART3_RTS,
+ MX51_PAD_KEY_COL5__UART3_CTS,
+ /* SD */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+ /* SD1 CD */
+ NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
+ PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+ PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+};
+
+#define GPIO_LED1 IMX_GPIO_NR(3, 30)
+#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31)
+
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
+ {
+ .name = "led1",
+ .default_trigger = "heartbeat",
+ .active_low = 1,
+ .gpio = GPIO_LED1,
+ },
+};
+
+static const struct gpio_led_platform_data
+ eukrea_mbimxsd_led_info __initconst = {
+ .leds = eukrea_mbimxsd_leds,
+ .num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+ {
+ .gpio = GPIO_SWITCH1,
+ .code = BTN_0,
+ .desc = "BP1",
+ .active_low = 1,
+ .wakeup = 1,
+ },
+};
+
+static const struct gpio_keys_platform_data
+ eukrea_mbimxsd_button_data __initconst = {
+ .buttons = eukrea_mbimxsd_gpio_buttons,
+ .nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("tlv320aic23", 0x1a),
+ },
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx51sd init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd51_baseboard_init(void)
+{
+ if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+ ARRAY_SIZE(eukrea_mbimxsd_pads)))
+ printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+ imx51_add_imx_uart(1, NULL);
+ imx51_add_imx_uart(2, &uart_pdata);
+
+ imx51_add_sdhci_esdhc_imx(0, NULL);
+
+ gpio_request(GPIO_LED1, "LED1");
+ gpio_direction_output(GPIO_LED1, 1);
+ gpio_free(GPIO_LED1);
+
+ gpio_request(GPIO_SWITCH1, "SWITCH1");
+ gpio_direction_input(GPIO_SWITCH1);
+ gpio_free(GPIO_SWITCH1);
+
+ i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+ ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+ gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
+ imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
+}
--- /dev/null
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+ { /* sentinel */ }
+};
+
+static int __init imx51_tzic_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ irq_domain_add_simple(np, 0);
+ return 0;
+}
+
+static int __init imx51_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+ gpio_irq_base -= 32;
+ irq_domain_add_simple(np, gpio_irq_base);
+
+ return 0;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+ { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+ { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+ { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+ { /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ void (*func)(void);
+
+ of_irq_init(imx51_irq_match);
+
+ node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+ if (node) {
+ of_id = of_match_node(imx51_iomuxc_of_match, node);
+ func = of_id->data;
+ func();
+ of_node_put(node);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+ mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+ .init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+ "fsl,imx51-babbage",
+ NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &imx51_timer,
+ .init_machine = imx51_dt_init,
+ .dt_compat = imx51_dt_board_compat,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+ { /* sentinel */ }
+};
+
+static int __init imx53_tzic_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ irq_domain_add_simple(np, 0);
+ return 0;
+}
+
+static int __init imx53_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+ gpio_irq_base -= 32;
+ irq_domain_add_simple(np, gpio_irq_base);
+
+ return 0;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+ { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+ { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+ { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+ { /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ void (*func)(void);
+
+ of_irq_init(imx53_irq_match);
+
+ node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+ if (node) {
+ of_id = of_match_node(imx53_iomuxc_of_match, node);
+ func = of_id->data;
+ func();
+ of_node_put(node);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+ mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+ .init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+ "fsl,imx53-ard",
+ "fsl,imx53-evk",
+ "fsl,imx53-qsb",
+ "fsl,imx53-smd",
+ NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &imx53_timer,
+ .init_machine = imx53_dt_init,
+ .dt_compat = imx53_dt_board_compat,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+
+#define CPUIMX51_USBH1_STP IMX_GPIO_NR(1, 27)
+#define CPUIMX51_QUARTA_GPIO IMX_GPIO_NR(3, 28)
+#define CPUIMX51_QUARTB_GPIO IMX_GPIO_NR(3, 25)
+#define CPUIMX51_QUARTC_GPIO IMX_GPIO_NR(3, 26)
+#define CPUIMX51_QUARTD_GPIO IMX_GPIO_NR(3, 27)
+#define CPUIMX51_QUART_XTAL 14745600
+#define CPUIMX51_QUART_REGSHIFT 17
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET 0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
+
+#define MX51_USB_PLLDIV_12_MHZ 0x00
+#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
+#define MX51_USB_PLL_DIV_24_MHZ 0x02
+
+static struct plat_serial8250_port serial_platform_data[] = {
+ {
+ .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
+ .irqflags = IRQF_TRIGGER_HIGH,
+ .uartclk = CPUIMX51_QUART_XTAL,
+ .regshift = CPUIMX51_QUART_REGSHIFT,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+ }, {
+ .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
+ .irqflags = IRQF_TRIGGER_HIGH,
+ .uartclk = CPUIMX51_QUART_XTAL,
+ .regshift = CPUIMX51_QUART_REGSHIFT,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+ }, {
+ .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
+ .irqflags = IRQF_TRIGGER_HIGH,
+ .uartclk = CPUIMX51_QUART_XTAL,
+ .regshift = CPUIMX51_QUART_REGSHIFT,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+ }, {
+ .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
+ .irqflags = IRQF_TRIGGER_HIGH,
+ .uartclk = CPUIMX51_QUART_XTAL,
+ .regshift = CPUIMX51_QUART_REGSHIFT,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+ }, {
+ }
+};
+
+static struct platform_device serial_device = {
+ .name = "serial8250",
+ .id = 0,
+ .dev = {
+ .platform_data = serial_platform_data,
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &serial_device,
+};
+
+static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+
+ /* I2C2 */
+ MX51_PAD_GPIO1_2__I2C2_SCL,
+ MX51_PAD_GPIO1_3__I2C2_SDA,
+ MX51_PAD_NANDF_D10__GPIO3_30,
+
+ /* QUART IRQ */
+ MX51_PAD_NANDF_D15__GPIO3_25,
+ MX51_PAD_NANDF_D14__GPIO3_26,
+ MX51_PAD_NANDF_D13__GPIO3_27,
+ MX51_PAD_NANDF_D12__GPIO3_28,
+
+ /* USB HOST1 */
+ MX51_PAD_USBH1_CLK__USBH1_CLK,
+ MX51_PAD_USBH1_DIR__USBH1_DIR,
+ MX51_PAD_USBH1_NXT__USBH1_NXT,
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+ MX51_PAD_USBH1_STP__USBH1_STP,
+};
+
+static const struct mxc_nand_platform_data
+ eukrea_cpuimx51_nand_board_info __initconst = {
+ .width = 1,
+ .hw_ecc = 1,
+ .flash_bbt = 1,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const
+struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("pcf8563", 0x51),
+ },
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* Set the PHY clock to 19.2MHz */
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ v |= MX51_USB_PLL_DIV_19_2_MHZ;
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* The clock for the USBH1 ULPI port will come externally from the PHY. */
+ v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+ __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+ MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+ .init = initialize_otg_port,
+ .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+ .init = initialize_usbh1_port,
+ .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51_otg_mode(char *options)
+{
+ if (!strcmp(options, "host"))
+ otg_mode_host = 1;
+ else if (!strcmp(options, "device"))
+ otg_mode_host = 0;
+ else
+ pr_info("otg_mode neither \"host\" nor \"device\". "
+ "Defaulting to device\n");
+ return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
+
+/*
+ * Board specific initialization.
+ */
+static void __init eukrea_cpuimx51_init(void)
+{
+ imx51_soc_init();
+
+ mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
+ ARRAY_SIZE(eukrea_cpuimx51_pads));
+
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
+
+ gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
+ gpio_direction_input(CPUIMX51_QUARTA_GPIO);
+ gpio_free(CPUIMX51_QUARTA_GPIO);
+ gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
+ gpio_direction_input(CPUIMX51_QUARTB_GPIO);
+ gpio_free(CPUIMX51_QUARTB_GPIO);
+ gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
+ gpio_direction_input(CPUIMX51_QUARTC_GPIO);
+ gpio_free(CPUIMX51_QUARTC_GPIO);
+ gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
+ gpio_direction_input(CPUIMX51_QUARTD_GPIO);
+ gpio_free(CPUIMX51_QUARTD_GPIO);
+
+ imx51_add_fec(NULL);
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
+ i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
+ ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
+
+ if (otg_mode_host)
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
+ else {
+ initialize_otg_port(NULL);
+ imx51_add_fsl_usb2_udc(&usb_pdata);
+ }
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
+ eukrea_mbimx51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = eukrea_cpuimx51_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
+ /* Maintainer: Eric Bénard <eric@eukrea.com> */
+ .atag_offset = 0x100,
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &mxc_timer,
+ .init_machine = eukrea_cpuimx51_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "cpu_op-mx51.h"
+
+#define USBH1_RST IMX_GPIO_NR(2, 28)
+#define ETH_RST IMX_GPIO_NR(2, 31)
+#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 12)
+#define CAN_IRQGPIO IMX_GPIO_NR(1, 1)
+#define CAN_RST IMX_GPIO_NR(4, 15)
+#define CAN_NCS IMX_GPIO_NR(4, 24)
+#define CAN_RXOBF IMX_GPIO_NR(1, 4)
+#define CAN_RX1BF IMX_GPIO_NR(1, 6)
+#define CAN_TXORTS IMX_GPIO_NR(1, 7)
+#define CAN_TX1RTS IMX_GPIO_NR(1, 8)
+#define CAN_TX2RTS IMX_GPIO_NR(1, 9)
+#define I2C_SCL IMX_GPIO_NR(4, 16)
+#define I2C_SDA IMX_GPIO_NR(4, 17)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET 0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
+
+#define MX51_USB_PLLDIV_12_MHZ 0x00
+#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
+#define MX51_USB_PLL_DIV_24_MHZ 0x02
+
+static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+
+ /* USB HOST1 */
+ MX51_PAD_USBH1_CLK__USBH1_CLK,
+ MX51_PAD_USBH1_DIR__USBH1_DIR,
+ MX51_PAD_USBH1_NXT__USBH1_NXT,
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+ MX51_PAD_USBH1_STP__USBH1_STP,
+ MX51_PAD_EIM_CS3__GPIO2_28, /* PHY nRESET */
+
+ /* FEC */
+ MX51_PAD_EIM_DTACK__GPIO2_31, /* PHY nRESET */
+
+ /* HSI2C */
+ MX51_PAD_I2C1_CLK__GPIO4_16,
+ MX51_PAD_I2C1_DAT__GPIO4_17,
+
+ /* CAN */
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+ MX51_PAD_CSPI1_SS0__GPIO4_24, /* nCS */
+ MX51_PAD_CSI2_PIXCLK__GPIO4_15, /* nReset */
+ MX51_PAD_GPIO1_1__GPIO1_1, /* IRQ */
+ MX51_PAD_GPIO1_4__GPIO1_4, /* Control signals */
+ MX51_PAD_GPIO1_6__GPIO1_6,
+ MX51_PAD_GPIO1_7__GPIO1_7,
+ MX51_PAD_GPIO1_8__GPIO1_8,
+ MX51_PAD_GPIO1_9__GPIO1_9,
+
+ /* Touchscreen */
+ /* IRQ */
+ NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
+ PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+ PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct tsc2007_platform_data tsc2007_info = {
+ .model = 2007,
+ .x_plate_ohms = 180,
+};
+
+static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("pcf8563", 0x51),
+ }, {
+ I2C_BOARD_INFO("tsc2007", 0x49),
+ .type = "tsc2007",
+ .platform_data = &tsc2007_info,
+ .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
+ },
+};
+
+static const struct mxc_nand_platform_data
+ eukrea_cpuimx51sd_nand_board_info __initconst = {
+ .width = 1,
+ .hw_ecc = 1,
+ .flash_bbt = 1,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* Set the PHY clock to 19.2MHz */
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ v |= MX51_USB_PLL_DIV_19_2_MHZ;
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* The clock for the USBH1 ULPI port will come from the PHY. */
+ v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+ __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+ usbother_base + MX51_USB_CTRL_1_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+ MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+ .init = initialize_otg_port,
+ .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+ .init = initialize_usbh1_port,
+ .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51sd_otg_mode(char *options)
+{
+ if (!strcmp(options, "host"))
+ otg_mode_host = 1;
+ else if (!strcmp(options, "device"))
+ otg_mode_host = 0;
+ else
+ pr_info("otg_mode neither \"host\" nor \"device\". "
+ "Defaulting to device\n");
+ return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
+
+static struct i2c_gpio_platform_data pdata = {
+ .sda_pin = I2C_SDA,
+ .sda_is_open_drain = 0,
+ .scl_pin = I2C_SCL,
+ .scl_is_open_drain = 0,
+ .udelay = 2,
+};
+
+static struct platform_device hsi2c_gpio_device = {
+ .name = "i2c-gpio",
+ .id = 0,
+ .dev.platform_data = &pdata,
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+ .oscillator_frequency = 24E6,
+};
+
+static struct spi_board_info cpuimx51sd_spi_device[] = {
+ {
+ .modalias = "mcp2515",
+ .max_speed_hz = 10000000,
+ .bus_num = 0,
+ .mode = SPI_MODE_0,
+ .chip_select = 0,
+ .platform_data = &mcp251x_info,
+ .irq = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
+ },
+};
+
+static int cpuimx51sd_spi1_cs[] = {
+ CAN_NCS,
+};
+
+static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
+ .chipselect = cpuimx51sd_spi1_cs,
+ .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+ &hsi2c_gpio_device,
+};
+
+static void __init eukrea_cpuimx51sd_init(void)
+{
+ imx51_soc_init();
+
+ mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
+ ARRAY_SIZE(eukrea_cpuimx51sd_pads));
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+ get_cpu_op = mx51_get_cpu_op;
+#endif
+
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+
+ gpio_request(ETH_RST, "eth_rst");
+ gpio_set_value(ETH_RST, 1);
+ imx51_add_fec(NULL);
+
+ gpio_request(CAN_IRQGPIO, "can_irq");
+ gpio_direction_input(CAN_IRQGPIO);
+ gpio_free(CAN_IRQGPIO);
+ gpio_request(CAN_NCS, "can_ncs");
+ gpio_direction_output(CAN_NCS, 1);
+ gpio_free(CAN_NCS);
+ gpio_request(CAN_RST, "can_rst");
+ gpio_direction_output(CAN_RST, 0);
+ msleep(20);
+ gpio_set_value(CAN_RST, 1);
+ imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+ spi_register_board_info(cpuimx51sd_spi_device,
+ ARRAY_SIZE(cpuimx51sd_spi_device));
+
+ gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
+ gpio_direction_input(TSC2007_IRQGPIO);
+ gpio_free(TSC2007_IRQGPIO);
+
+ i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
+ ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+ if (otg_mode_host)
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
+ else {
+ initialize_otg_port(NULL);
+ imx51_add_fsl_usb2_udc(&usb_pdata);
+ }
+
+ gpio_request(USBH1_RST, "usb_rst");
+ gpio_direction_output(USBH1_RST, 0);
+ msleep(20);
+ gpio_set_value(USBH1_RST, 1);
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
+ eukrea_mbimxsd51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51sd_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = eukrea_cpuimx51sd_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
+ /* Maintainer: Eric Bénard <eric@eukrea.com> */
+ .atag_offset = 0x100,
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &mxc_timer,
+ .init_machine = eukrea_cpuimx51sd_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx50.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx50.h"
+
+#define FEC_EN IMX_GPIO_NR(6, 23)
+#define FEC_RESET_B IMX_GPIO_NR(4, 12)
+
+static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
+ /* SD1 */
+ MX50_PAD_ECSPI2_SS0__GPIO_4_19,
+ MX50_PAD_EIM_CRE__GPIO_1_27,
+ MX50_PAD_SD1_CMD__SD1_CMD,
+
+ MX50_PAD_SD1_CLK__SD1_CLK,
+ MX50_PAD_SD1_D0__SD1_D0,
+ MX50_PAD_SD1_D1__SD1_D1,
+ MX50_PAD_SD1_D2__SD1_D2,
+ MX50_PAD_SD1_D3__SD1_D3,
+
+ /* SD2 */
+ MX50_PAD_SD2_CD__GPIO_5_17,
+ MX50_PAD_SD2_WP__GPIO_5_16,
+ MX50_PAD_SD2_CMD__SD2_CMD,
+ MX50_PAD_SD2_CLK__SD2_CLK,
+ MX50_PAD_SD2_D0__SD2_D0,
+ MX50_PAD_SD2_D1__SD2_D1,
+ MX50_PAD_SD2_D2__SD2_D2,
+ MX50_PAD_SD2_D3__SD2_D3,
+ MX50_PAD_SD2_D4__SD2_D4,
+ MX50_PAD_SD2_D5__SD2_D5,
+ MX50_PAD_SD2_D6__SD2_D6,
+ MX50_PAD_SD2_D7__SD2_D7,
+
+ /* SD3 */
+ MX50_PAD_SD3_CMD__SD3_CMD,
+ MX50_PAD_SD3_CLK__SD3_CLK,
+ MX50_PAD_SD3_D0__SD3_D0,
+ MX50_PAD_SD3_D1__SD3_D1,
+ MX50_PAD_SD3_D2__SD3_D2,
+ MX50_PAD_SD3_D3__SD3_D3,
+ MX50_PAD_SD3_D4__SD3_D4,
+ MX50_PAD_SD3_D5__SD3_D5,
+ MX50_PAD_SD3_D6__SD3_D6,
+ MX50_PAD_SD3_D7__SD3_D7,
+
+ /* PWR_INT */
+ MX50_PAD_ECSPI2_MISO__GPIO_4_18,
+
+ /* UART pad setting */
+ MX50_PAD_UART1_TXD__UART1_TXD,
+ MX50_PAD_UART1_RXD__UART1_RXD,
+ MX50_PAD_UART1_RTS__UART1_RTS,
+ MX50_PAD_UART2_TXD__UART2_TXD,
+ MX50_PAD_UART2_RXD__UART2_RXD,
+ MX50_PAD_UART2_CTS__UART2_CTS,
+ MX50_PAD_UART2_RTS__UART2_RTS,
+
+ MX50_PAD_I2C1_SCL__I2C1_SCL,
+ MX50_PAD_I2C1_SDA__I2C1_SDA,
+ MX50_PAD_I2C2_SCL__I2C2_SCL,
+ MX50_PAD_I2C2_SDA__I2C2_SDA,
+
+ MX50_PAD_EPITO__USBH1_PWR,
+ /* Need to comment below line if
+ * one needs to debug owire.
+ */
+ MX50_PAD_OWIRE__USBH1_OC,
+ /* using gpio to control otg pwr */
+ MX50_PAD_PWM2__GPIO_6_25,
+ MX50_PAD_I2C3_SCL__USBOTG_OC,
+
+ MX50_PAD_SSI_RXC__FEC_MDIO,
+ MX50_PAD_SSI_RXFS__FEC_MDC,
+ MX50_PAD_DISP_D0__FEC_TXCLK,
+ MX50_PAD_DISP_D1__FEC_RX_ER,
+ MX50_PAD_DISP_D2__FEC_RX_DV,
+ MX50_PAD_DISP_D3__FEC_RXD1,
+ MX50_PAD_DISP_D4__FEC_RXD0,
+ MX50_PAD_DISP_D5__FEC_TX_EN,
+ MX50_PAD_DISP_D6__FEC_TXD1,
+ MX50_PAD_DISP_D7__FEC_TXD0,
+ MX50_PAD_I2C3_SDA__GPIO_6_23,
+ MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
+
+ MX50_PAD_CSPI_SS0__CSPI_SS0,
+ MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
+ MX50_PAD_CSPI_MOSI__CSPI_MOSI,
+ MX50_PAD_CSPI_MISO__CSPI_MISO,
+
+ /* SGTL500_OSC_EN */
+ MX50_PAD_UART1_CTS__GPIO_6_8,
+
+ /* SGTL_AMP_SHDN */
+ MX50_PAD_UART3_RXD__GPIO_6_15,
+
+ /* Keypad */
+ MX50_PAD_KEY_COL0__KEY_COL0,
+ MX50_PAD_KEY_ROW0__KEY_ROW0,
+ MX50_PAD_KEY_COL1__KEY_COL1,
+ MX50_PAD_KEY_ROW1__KEY_ROW1,
+ MX50_PAD_KEY_COL2__KEY_COL2,
+ MX50_PAD_KEY_ROW2__KEY_ROW2,
+ MX50_PAD_KEY_COL3__KEY_COL3,
+ MX50_PAD_KEY_ROW3__KEY_ROW3,
+ MX50_PAD_EIM_DA0__KEY_COL4,
+ MX50_PAD_EIM_DA1__KEY_ROW4,
+ MX50_PAD_EIM_DA2__KEY_COL5,
+ MX50_PAD_EIM_DA3__KEY_ROW5,
+ MX50_PAD_EIM_DA4__KEY_COL6,
+ MX50_PAD_EIM_DA5__KEY_ROW6,
+ MX50_PAD_EIM_DA6__KEY_COL7,
+ MX50_PAD_EIM_DA7__KEY_ROW7,
+ /*EIM pads */
+ MX50_PAD_EIM_DA8__GPIO_1_8,
+ MX50_PAD_EIM_DA9__GPIO_1_9,
+ MX50_PAD_EIM_DA10__GPIO_1_10,
+ MX50_PAD_EIM_DA11__GPIO_1_11,
+ MX50_PAD_EIM_DA12__GPIO_1_12,
+ MX50_PAD_EIM_DA13__GPIO_1_13,
+ MX50_PAD_EIM_DA14__GPIO_1_14,
+ MX50_PAD_EIM_DA15__GPIO_1_15,
+ MX50_PAD_EIM_CS2__GPIO_1_16,
+ MX50_PAD_EIM_CS1__GPIO_1_17,
+ MX50_PAD_EIM_CS0__GPIO_1_18,
+ MX50_PAD_EIM_EB0__GPIO_1_19,
+ MX50_PAD_EIM_EB1__GPIO_1_20,
+ MX50_PAD_EIM_WAIT__GPIO_1_21,
+ MX50_PAD_EIM_BCLK__GPIO_1_22,
+ MX50_PAD_EIM_RDY__GPIO_1_23,
+ MX50_PAD_EIM_OE__GPIO_1_24,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct fec_platform_data fec_data __initconst = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static inline void mx50_rdp_fec_reset(void)
+{
+ gpio_request(FEC_EN, "fec-en");
+ gpio_direction_output(FEC_EN, 0);
+ gpio_request(FEC_RESET_B, "fec-reset_b");
+ gpio_direction_output(FEC_RESET_B, 0);
+ msleep(1);
+ gpio_set_value(FEC_RESET_B, 1);
+}
+
+static const struct imxi2c_platform_data i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx50_rdp_board_init(void)
+{
+ imx50_soc_init();
+
+ mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
+ ARRAY_SIZE(mx50_rdp_pads));
+
+ imx50_add_imx_uart(0, &uart_pdata);
+ imx50_add_imx_uart(1, &uart_pdata);
+ mx50_rdp_fec_reset();
+ imx50_add_fec(&fec_data);
+ imx50_add_imx_i2c(0, &i2c_data);
+ imx50_add_imx_i2c(1, &i2c_data);
+ imx50_add_imx_i2c(2, &i2c_data);
+}
+
+static void __init mx50_rdp_timer_init(void)
+{
+ mx50_clocks_init(32768, 24000000, 22579200);
+}
+
+static struct sys_timer mx50_rdp_timer = {
+ .init = mx50_rdp_timer_init,
+};
+
+MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
+ .map_io = mx50_map_io,
+ .init_early = imx50_init_early,
+ .init_irq = mx50_init_irq,
+ .handle_irq = imx50_handle_irq,
+ .timer = &mx50_rdp_timer,
+ .init_machine = mx50_rdp_board_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx51.h>
+#include <mach/3ds_debugboard.h>
+
+#include "devices-imx51.h"
+
+#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6))
+#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28)
+
+static iomux_v3_cfg_t mx51_3ds_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+
+ /* UART2 */
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+ MX51_PAD_EIM_D25__UART2_CTS,
+ MX51_PAD_EIM_D26__UART2_RTS,
+
+ /* UART3 */
+ MX51_PAD_UART3_RXD__UART3_RXD,
+ MX51_PAD_UART3_TXD__UART3_TXD,
+ MX51_PAD_EIM_D24__UART3_CTS,
+ MX51_PAD_EIM_D27__UART3_RTS,
+
+ /* CPLD PARENT IRQ PIN */
+ MX51_PAD_GPIO1_6__GPIO1_6,
+
+ /* KPP */
+ MX51_PAD_KEY_ROW0__KEY_ROW0,
+ MX51_PAD_KEY_ROW1__KEY_ROW1,
+ MX51_PAD_KEY_ROW2__KEY_ROW2,
+ MX51_PAD_KEY_ROW3__KEY_ROW3,
+ MX51_PAD_KEY_COL0__KEY_COL0,
+ MX51_PAD_KEY_COL1__KEY_COL1,
+ MX51_PAD_KEY_COL2__KEY_COL2,
+ MX51_PAD_KEY_COL3__KEY_COL3,
+ MX51_PAD_KEY_COL4__KEY_COL4,
+ MX51_PAD_KEY_COL5__KEY_COL5,
+
+ /* eCSPI2 */
+ MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
+ MX51_PAD_NANDF_RB3__ECSPI2_MISO,
+ MX51_PAD_NANDF_D15__ECSPI2_MOSI,
+ MX51_PAD_NANDF_D12__GPIO3_28,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mx51_3ds_board_keymap[] = {
+ KEY(0, 0, KEY_1),
+ KEY(0, 1, KEY_2),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F1),
+ KEY(0, 4, KEY_UP),
+ KEY(0, 5, KEY_F2),
+
+ KEY(1, 0, KEY_4),
+ KEY(1, 1, KEY_5),
+ KEY(1, 2, KEY_6),
+ KEY(1, 3, KEY_LEFT),
+ KEY(1, 4, KEY_SELECT),
+ KEY(1, 5, KEY_RIGHT),
+
+ KEY(2, 0, KEY_7),
+ KEY(2, 1, KEY_8),
+ KEY(2, 2, KEY_9),
+ KEY(2, 3, KEY_F3),
+ KEY(2, 4, KEY_DOWN),
+ KEY(2, 5, KEY_F4),
+
+ KEY(3, 0, KEY_0),
+ KEY(3, 1, KEY_OK),
+ KEY(3, 2, KEY_ESC),
+ KEY(3, 3, KEY_ENTER),
+ KEY(3, 4, KEY_MENU),
+ KEY(3, 5, KEY_BACK)
+};
+
+static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
+ .keymap = mx51_3ds_board_keymap,
+ .keymap_size = ARRAY_SIZE(mx51_3ds_board_keymap),
+};
+
+static int mx51_3ds_spi2_cs[] = {
+ MXC_SPI_CS(0),
+ MX51_3DS_ECSPI2_CS,
+};
+
+static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
+ .chipselect = mx51_3ds_spi2_cs,
+ .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs),
+};
+
+static struct spi_board_info mx51_3ds_spi_nor_device[] = {
+ {
+ .modalias = "m25p80",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,},
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx51_3ds_init(void)
+{
+ imx51_soc_init();
+
+ mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
+ ARRAY_SIZE(mx51_3ds_pads));
+
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_imx_uart(1, &uart_pdata);
+ imx51_add_imx_uart(2, &uart_pdata);
+
+ imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
+ spi_register_board_info(mx51_3ds_spi_nor_device,
+ ARRAY_SIZE(mx51_3ds_spi_nor_device));
+
+ if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+ printk(KERN_WARNING "Init of the debugboard failed, all "
+ "devices on the board are unusable.\n");
+
+ imx51_add_sdhci_esdhc_imx(0, NULL);
+ imx51_add_imx_keypad(&mx51_3ds_map_data);
+ imx51_add_imx2_wdt(0, NULL);
+}
+
+static void __init mx51_3ds_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx51_3ds_timer = {
+ .init = mx51_3ds_timer_init,
+};
+
+MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .atag_offset = 0x100,
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &mx51_3ds_timer,
+ .init_machine = mx51_3ds_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "cpu_op-mx51.h"
+
+#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7)
+#define BABBAGE_USBH1_STP IMX_GPIO_NR(1, 27)
+#define BABBAGE_USB_PHY_RESET IMX_GPIO_NR(2, 5)
+#define BABBAGE_FEC_PHY_RESET IMX_GPIO_NR(2, 14)
+#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
+#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
+#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
+#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
+#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET 0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
+
+#define MX51_USB_PLLDIV_12_MHZ 0x00
+#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
+#define MX51_USB_PLL_DIV_24_MHZ 0x02
+
+static struct gpio_keys_button babbage_buttons[] = {
+ {
+ .gpio = BABBAGE_POWER_KEY,
+ .code = BTN_0,
+ .desc = "PWR",
+ .active_low = 1,
+ .wakeup = 1,
+ },
+};
+
+static const struct gpio_keys_platform_data imx_button_data __initconst = {
+ .buttons = babbage_buttons,
+ .nbuttons = ARRAY_SIZE(babbage_buttons),
+};
+
+static iomux_v3_cfg_t mx51babbage_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+
+ /* UART2 */
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+
+ /* UART3 */
+ MX51_PAD_EIM_D25__UART3_RXD,
+ MX51_PAD_EIM_D26__UART3_TXD,
+ MX51_PAD_EIM_D27__UART3_RTS,
+ MX51_PAD_EIM_D24__UART3_CTS,
+
+ /* I2C1 */
+ MX51_PAD_EIM_D16__I2C1_SDA,
+ MX51_PAD_EIM_D19__I2C1_SCL,
+
+ /* I2C2 */
+ MX51_PAD_KEY_COL4__I2C2_SCL,
+ MX51_PAD_KEY_COL5__I2C2_SDA,
+
+ /* HSI2C */
+ MX51_PAD_I2C1_CLK__I2C1_CLK,
+ MX51_PAD_I2C1_DAT__I2C1_DAT,
+
+ /* USB HOST1 */
+ MX51_PAD_USBH1_CLK__USBH1_CLK,
+ MX51_PAD_USBH1_DIR__USBH1_DIR,
+ MX51_PAD_USBH1_NXT__USBH1_NXT,
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+ /* USB HUB reset line*/
+ MX51_PAD_GPIO1_7__GPIO1_7,
+
+ /* USB PHY reset line */
+ MX51_PAD_EIM_D21__GPIO2_5,
+
+ /* FEC */
+ MX51_PAD_EIM_EB2__FEC_MDIO,
+ MX51_PAD_EIM_EB3__FEC_RDATA1,
+ MX51_PAD_EIM_CS2__FEC_RDATA2,
+ MX51_PAD_EIM_CS3__FEC_RDATA3,
+ MX51_PAD_EIM_CS4__FEC_RX_ER,
+ MX51_PAD_EIM_CS5__FEC_CRS,
+ MX51_PAD_NANDF_RB2__FEC_COL,
+ MX51_PAD_NANDF_RB3__FEC_RX_CLK,
+ MX51_PAD_NANDF_D9__FEC_RDATA0,
+ MX51_PAD_NANDF_D8__FEC_TDATA0,
+ MX51_PAD_NANDF_CS2__FEC_TX_ER,
+ MX51_PAD_NANDF_CS3__FEC_MDC,
+ MX51_PAD_NANDF_CS4__FEC_TDATA1,
+ MX51_PAD_NANDF_CS5__FEC_TDATA2,
+ MX51_PAD_NANDF_CS6__FEC_TDATA3,
+ MX51_PAD_NANDF_CS7__FEC_TX_EN,
+ MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+ /* FEC PHY reset line */
+ MX51_PAD_EIM_A20__GPIO2_14,
+
+ /* SD 1 */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+ /* CD/WP from controller */
+ MX51_PAD_GPIO1_0__SD1_CD,
+ MX51_PAD_GPIO1_1__SD1_WP,
+
+ /* SD 2 */
+ MX51_PAD_SD2_CMD__SD2_CMD,
+ MX51_PAD_SD2_CLK__SD2_CLK,
+ MX51_PAD_SD2_DATA0__SD2_DATA0,
+ MX51_PAD_SD2_DATA1__SD2_DATA1,
+ MX51_PAD_SD2_DATA2__SD2_DATA2,
+ MX51_PAD_SD2_DATA3__SD2_DATA3,
+ /* CD/WP gpio */
+ MX51_PAD_GPIO1_6__GPIO1_6,
+ MX51_PAD_GPIO1_5__GPIO1_5,
+
+ /* eCSPI1 */
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+ MX51_PAD_CSPI1_SS0__GPIO4_24,
+ MX51_PAD_CSPI1_SS1__GPIO4_25,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
+ .bitrate = 400000,
+};
+
+static struct gpio mx51_babbage_usbh1_gpios[] = {
+ { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
+ { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
+};
+
+static int gpio_usbh1_active(void)
+{
+ iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+ int ret;
+
+ /* Set USBH1_STP to GPIO and toggle it */
+ mxc_iomux_v3_setup_pad(usbh1stp_gpio);
+ ret = gpio_request_array(mx51_babbage_usbh1_gpios,
+ ARRAY_SIZE(mx51_babbage_usbh1_gpios));
+
+ if (ret) {
+ pr_debug("failed to get USBH1 pins: %d\n", ret);
+ return ret;
+ }
+
+ msleep(100);
+ gpio_set_value(BABBAGE_USBH1_STP, 1);
+ gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
+ gpio_free_array(mx51_babbage_usbh1_gpios,
+ ARRAY_SIZE(mx51_babbage_usbh1_gpios));
+ return 0;
+}
+
+static inline void babbage_usbhub_reset(void)
+{
+ int ret;
+
+ /* Reset USB hub */
+ ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
+ GPIOF_OUT_INIT_LOW, "GPIO1_7");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
+ return;
+ }
+
+ msleep(2);
+ /* Deassert reset */
+ gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
+}
+
+static inline void babbage_fec_reset(void)
+{
+ int ret;
+
+ /* reset FEC PHY */
+ ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
+ GPIOF_OUT_INIT_LOW, "fec-phy-reset");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+ return;
+ }
+ msleep(1);
+ gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+}
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* Set the PHY clock to 19.2MHz */
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ v |= MX51_USB_PLL_DIV_19_2_MHZ;
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* The clock for the USBH1 ULPI port will come externally from the PHY. */
+ v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+ __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+ MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+ .init = initialize_otg_port,
+ .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+ .init = initialize_usbh1_port,
+ .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init babbage_otg_mode(char *options)
+{
+ if (!strcmp(options, "host"))
+ otg_mode_host = 1;
+ else if (!strcmp(options, "device"))
+ otg_mode_host = 0;
+ else
+ pr_info("otg_mode neither \"host\" nor \"device\". "
+ "Defaulting to device\n");
+ return 0;
+}
+__setup("otg_mode=", babbage_otg_mode);
+
+static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
+ {
+ .modalias = "mtd_dataflash",
+ .max_speed_hz = 25000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ },
+};
+
+static int mx51_babbage_spi_cs[] = {
+ BABBAGE_ECSPI1_CS0,
+ BABBAGE_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
+ .chipselect = mx51_babbage_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
+ .cd_gpio = BABBAGE_SD2_CD,
+ .wp_gpio = BABBAGE_SD2_WP,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_GPIO,
+};
+
+void __init imx51_babbage_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+ ARRAY_SIZE(mx51babbage_pads));
+}
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx51_babbage_init(void)
+{
+ iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+ iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+ PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
+
+ imx51_soc_init();
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+ get_cpu_op = mx51_get_cpu_op;
+#endif
+ imx51_babbage_common_init();
+
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_imx_uart(1, NULL);
+ imx51_add_imx_uart(2, &uart_pdata);
+
+ babbage_fec_reset();
+ imx51_add_fec(NULL);
+
+ /* Set the PAD settings for the pwr key. */
+ mxc_iomux_v3_setup_pad(power_key);
+ imx_add_gpio_keys(&imx_button_data);
+
+ imx51_add_imx_i2c(0, &babbage_i2c_data);
+ imx51_add_imx_i2c(1, &babbage_i2c_data);
+ imx51_add_hsi2c(&babbage_hsi2c_data);
+
+ if (otg_mode_host)
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
+ else {
+ initialize_otg_port(NULL);
+ imx51_add_fsl_usb2_udc(&usb_pdata);
+ }
+
+ gpio_usbh1_active();
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
+ /* setback USBH1_STP to be function */
+ mxc_iomux_v3_setup_pad(usbh1stp);
+ babbage_usbhub_reset();
+
+ imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
+ imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
+
+ spi_register_board_info(mx51_babbage_spi_board_info,
+ ARRAY_SIZE(mx51_babbage_spi_board_info));
+ imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
+ imx51_add_imx2_wdt(0, NULL);
+}
+
+static void __init mx51_babbage_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx51_babbage_timer = {
+ .init = mx51_babbage_timer_init,
+};
+
+MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
+ /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
+ .atag_offset = 0x100,
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &mx51_babbage_timer,
+ .init_machine = mx51_babbage_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) 2010 Linaro Limited
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+
+#define EFIKAMX_PCBID0 IMX_GPIO_NR(3, 16)
+#define EFIKAMX_PCBID1 IMX_GPIO_NR(3, 17)
+#define EFIKAMX_PCBID2 IMX_GPIO_NR(3, 11)
+
+#define EFIKAMX_BLUE_LED IMX_GPIO_NR(3, 13)
+#define EFIKAMX_GREEN_LED IMX_GPIO_NR(3, 14)
+#define EFIKAMX_RED_LED IMX_GPIO_NR(3, 15)
+
+#define EFIKAMX_POWER_KEY IMX_GPIO_NR(2, 31)
+
+/* board 1.1 doesn't have same reset gpio */
+#define EFIKAMX_RESET1_1 IMX_GPIO_NR(3, 2)
+#define EFIKAMX_RESET IMX_GPIO_NR(1, 4)
+
+#define EFIKAMX_POWEROFF IMX_GPIO_NR(4, 13)
+
+#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6)
+
+/* the pci ids pin have pull up. they're driven low according to board id */
+#define MX51_PAD_PCBID0 IOMUX_PAD(0x518, 0x130, 3, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID1 IOMUX_PAD(0x51C, 0x134, 3, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID2 IOMUX_PAD(0x504, 0x128, 3, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+
+static iomux_v3_cfg_t mx51efikamx_pads[] = {
+ /* board id */
+ MX51_PAD_PCBID0,
+ MX51_PAD_PCBID1,
+ MX51_PAD_PCBID2,
+
+ /* leds */
+ MX51_PAD_CSI1_D9__GPIO3_13,
+ MX51_PAD_CSI1_VSYNC__GPIO3_14,
+ MX51_PAD_CSI1_HSYNC__GPIO3_15,
+
+ /* power key */
+ MX51_PAD_PWRKEY,
+
+ /* reset */
+ MX51_PAD_DI1_PIN13__GPIO3_2,
+ MX51_PAD_GPIO1_4__GPIO1_4,
+
+ /* power off */
+ MX51_PAD_CSI2_VSYNC__GPIO4_13,
+};
+
+/* PCBID2 PCBID1 PCBID0 STATE
+ 1 1 1 ER1:rev1.1
+ 1 1 0 ER2:rev1.2
+ 1 0 1 ER3:rev1.3
+ 1 0 0 ER4:rev1.4
+*/
+static void __init mx51_efikamx_board_id(void)
+{
+ int id;
+
+ /* things are taking time to settle */
+ msleep(150);
+
+ gpio_request(EFIKAMX_PCBID0, "pcbid0");
+ gpio_direction_input(EFIKAMX_PCBID0);
+ gpio_request(EFIKAMX_PCBID1, "pcbid1");
+ gpio_direction_input(EFIKAMX_PCBID1);
+ gpio_request(EFIKAMX_PCBID2, "pcbid2");
+ gpio_direction_input(EFIKAMX_PCBID2);
+
+ id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
+ id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
+ id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
+
+ switch (id) {
+ case 7:
+ system_rev = 0x11;
+ break;
+ case 6:
+ system_rev = 0x12;
+ break;
+ case 5:
+ system_rev = 0x13;
+ break;
+ case 4:
+ system_rev = 0x14;
+ break;
+ default:
+ system_rev = 0x10;
+ break;
+ }
+
+ if ((system_rev == 0x10)
+ || (system_rev == 0x12)
+ || (system_rev == 0x14)) {
+ printk(KERN_WARNING
+ "EfikaMX: Unsupported board revision 1.%u!\n",
+ system_rev & 0xf);
+ }
+}
+
+static struct gpio_led mx51_efikamx_leds[] __initdata = {
+ {
+ .name = "efikamx:green",
+ .default_trigger = "default-on",
+ .gpio = EFIKAMX_GREEN_LED,
+ },
+ {
+ .name = "efikamx:red",
+ .default_trigger = "ide-disk",
+ .gpio = EFIKAMX_RED_LED,
+ },
+ {
+ .name = "efikamx:blue",
+ .default_trigger = "mmc0",
+ .gpio = EFIKAMX_BLUE_LED,
+ },
+};
+
+static const struct gpio_led_platform_data
+ mx51_efikamx_leds_data __initconst = {
+ .leds = mx51_efikamx_leds,
+ .num_leds = ARRAY_SIZE(mx51_efikamx_leds),
+};
+
+static struct esdhc_platform_data sd_pdata = {
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct gpio_keys_button mx51_efikamx_powerkey[] = {
+ {
+ .code = KEY_POWER,
+ .gpio = EFIKAMX_POWER_KEY,
+ .type = EV_PWR,
+ .desc = "Power Button (CM)",
+ .wakeup = 1,
+ .debounce_interval = 10, /* ms */
+ },
+};
+
+static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
+ .buttons = mx51_efikamx_powerkey,
+ .nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
+};
+
+static void mx51_efikamx_restart(char mode, const char *cmd)
+{
+ if (system_rev == 0x11)
+ gpio_direction_output(EFIKAMX_RESET1_1, 0);
+ else
+ gpio_direction_output(EFIKAMX_RESET, 0);
+}
+
+static struct regulator *pwgt1, *pwgt2, *coincell;
+
+static void mx51_efikamx_power_off(void)
+{
+ if (!IS_ERR(coincell))
+ regulator_disable(coincell);
+
+ if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+ regulator_disable(pwgt2);
+ regulator_disable(pwgt1);
+ }
+ gpio_direction_output(EFIKAMX_POWEROFF, 1);
+}
+
+static int __init mx51_efikamx_power_init(void)
+{
+ if (machine_is_mx51_efikamx()) {
+ pwgt1 = regulator_get(NULL, "pwgt1");
+ pwgt2 = regulator_get(NULL, "pwgt2");
+ if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+ regulator_enable(pwgt1);
+ regulator_enable(pwgt2);
+ }
+ gpio_request(EFIKAMX_POWEROFF, "poweroff");
+ pm_power_off = mx51_efikamx_power_off;
+
+ /* enable coincell charger. maybe need a small power driver ? */
+ coincell = regulator_get(NULL, "coincell");
+ if (!IS_ERR(coincell)) {
+ regulator_set_voltage(coincell, 3000000, 3000000);
+ regulator_enable(coincell);
+ }
+
+ regulator_has_full_constraints();
+ }
+
+ return 0;
+}
+late_initcall(mx51_efikamx_power_init);
+
+static void __init mx51_efikamx_init(void)
+{
+ imx51_soc_init();
+
+ mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
+ ARRAY_SIZE(mx51efikamx_pads));
+ efika_board_common_init();
+
+ mx51_efikamx_board_id();
+
+ /* on < 1.2 boards both SD controllers are used */
+ if (system_rev < 0x12) {
+ imx51_add_sdhci_esdhc_imx(0, NULL);
+ imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
+ mx51_efikamx_leds[2].default_trigger = "mmc1";
+ } else
+ imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
+
+ gpio_led_register_device(-1, &mx51_efikamx_leds_data);
+ imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
+
+ if (system_rev == 0x11) {
+ gpio_request(EFIKAMX_RESET1_1, "reset");
+ gpio_direction_output(EFIKAMX_RESET1_1, 1);
+ } else {
+ gpio_request(EFIKAMX_RESET, "reset");
+ gpio_direction_output(EFIKAMX_RESET, 1);
+ }
+
+ /*
+ * enable wifi by default only on mx
+ * sb and mx have same wlan pin but the value to enable it are
+ * different :/
+ */
+ gpio_request(EFIKA_WLAN_EN, "wlan_en");
+ gpio_direction_output(EFIKA_WLAN_EN, 0);
+ msleep(10);
+
+ gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
+ gpio_direction_output(EFIKA_WLAN_RESET, 0);
+ msleep(10);
+ gpio_set_value(EFIKA_WLAN_RESET, 1);
+}
+
+static void __init mx51_efikamx_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikamx_timer = {
+ .init = mx51_efikamx_timer_init,
+};
+
+MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
+ /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
+ .atag_offset = 0x100,
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &mx51_efikamx_timer,
+ .init_machine = mx51_efikamx_init,
+ .restart = mx51_efikamx_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+
+#define EFIKASB_USBH2_STP IMX_GPIO_NR(2, 20)
+#define EFIKASB_GREEN_LED IMX_GPIO_NR(1, 3)
+#define EFIKASB_WHITE_LED IMX_GPIO_NR(2, 25)
+#define EFIKASB_PCBID0 IMX_GPIO_NR(2, 28)
+#define EFIKASB_PCBID1 IMX_GPIO_NR(2, 29)
+#define EFIKASB_PWRKEY IMX_GPIO_NR(2, 31)
+#define EFIKASB_LID IMX_GPIO_NR(3, 14)
+#define EFIKASB_POWEROFF IMX_GPIO_NR(4, 13)
+#define EFIKASB_RFKILL IMX_GPIO_NR(3, 1)
+
+#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+#define MX51_PAD_SD1_CD IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+
+static iomux_v3_cfg_t mx51efikasb_pads[] = {
+ /* USB HOST2 */
+ MX51_PAD_EIM_D16__USBH2_DATA0,
+ MX51_PAD_EIM_D17__USBH2_DATA1,
+ MX51_PAD_EIM_D18__USBH2_DATA2,
+ MX51_PAD_EIM_D19__USBH2_DATA3,
+ MX51_PAD_EIM_D20__USBH2_DATA4,
+ MX51_PAD_EIM_D21__USBH2_DATA5,
+ MX51_PAD_EIM_D22__USBH2_DATA6,
+ MX51_PAD_EIM_D23__USBH2_DATA7,
+ MX51_PAD_EIM_A24__USBH2_CLK,
+ MX51_PAD_EIM_A25__USBH2_DIR,
+ MX51_PAD_EIM_A26__USBH2_STP,
+ MX51_PAD_EIM_A27__USBH2_NXT,
+
+ /* leds */
+ MX51_PAD_EIM_CS0__GPIO2_25,
+ MX51_PAD_GPIO1_3__GPIO1_3,
+
+ /* pcb id */
+ MX51_PAD_EIM_CS3__GPIO2_28,
+ MX51_PAD_EIM_CS4__GPIO2_29,
+
+ /* lid */
+ MX51_PAD_CSI1_VSYNC__GPIO3_14,
+
+ /* power key*/
+ MX51_PAD_PWRKEY,
+
+ /* wifi/bt button */
+ MX51_PAD_DI1_PIN12__GPIO3_1,
+
+ /* power off */
+ MX51_PAD_CSI2_VSYNC__GPIO4_13,
+
+ /* wdog reset */
+ MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
+
+ /* BT */
+ MX51_PAD_EIM_A17__GPIO2_11,
+
+ MX51_PAD_SD1_CD,
+};
+
+static int initialize_usbh2_port(struct platform_device *pdev)
+{
+ iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
+ iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
+
+ mxc_iomux_v3_setup_pad(usbh2gpio);
+ gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
+ gpio_direction_output(EFIKASB_USBH2_STP, 0);
+ msleep(1);
+ gpio_set_value(EFIKASB_USBH2_STP, 1);
+ msleep(1);
+
+ gpio_free(EFIKASB_USBH2_STP);
+ mxc_iomux_v3_setup_pad(usbh2stp);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
+ .init = initialize_usbh2_port,
+ .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void __init mx51_efikasb_usb(void)
+{
+ usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+ ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+ if (usbh2_config.otg)
+ imx51_add_mxc_ehci_hs(2, &usbh2_config);
+}
+
+static const struct gpio_led mx51_efikasb_leds[] __initconst = {
+ {
+ .name = "efikasb:green",
+ .default_trigger = "default-on",
+ .gpio = EFIKASB_GREEN_LED,
+ .active_low = 1,
+ },
+ {
+ .name = "efikasb:white",
+ .default_trigger = "caps",
+ .gpio = EFIKASB_WHITE_LED,
+ },
+};
+
+static const struct gpio_led_platform_data
+ mx51_efikasb_leds_data __initconst = {
+ .leds = mx51_efikasb_leds,
+ .num_leds = ARRAY_SIZE(mx51_efikasb_leds),
+};
+
+static struct gpio_keys_button mx51_efikasb_keys[] = {
+ {
+ .code = KEY_POWER,
+ .gpio = EFIKASB_PWRKEY,
+ .type = EV_KEY,
+ .desc = "Power Button",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+ {
+ .code = SW_LID,
+ .gpio = EFIKASB_LID,
+ .type = EV_SW,
+ .desc = "Lid Switch",
+ .active_low = 1,
+ },
+ {
+ .code = KEY_RFKILL,
+ .gpio = EFIKASB_RFKILL,
+ .type = EV_KEY,
+ .desc = "rfkill",
+ .active_low = 1,
+ },
+};
+
+static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
+ .buttons = mx51_efikasb_keys,
+ .nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
+};
+
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27)
+ .cd_gpio = EFIKASB_SD1_CD,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct regulator *pwgt1, *pwgt2;
+
+static void mx51_efikasb_power_off(void)
+{
+ gpio_set_value(EFIKA_USB_PHY_RESET, 0);
+
+ if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+ regulator_disable(pwgt2);
+ regulator_disable(pwgt1);
+ }
+ gpio_direction_output(EFIKASB_POWEROFF, 1);
+}
+
+static int __init mx51_efikasb_power_init(void)
+{
+ if (machine_is_mx51_efikasb()) {
+ pwgt1 = regulator_get(NULL, "pwgt1");
+ pwgt2 = regulator_get(NULL, "pwgt2");
+ if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+ regulator_enable(pwgt1);
+ regulator_enable(pwgt2);
+ }
+ gpio_request(EFIKASB_POWEROFF, "poweroff");
+ pm_power_off = mx51_efikasb_power_off;
+
+ regulator_has_full_constraints();
+ }
+
+ return 0;
+}
+late_initcall(mx51_efikasb_power_init);
+
+/* 01 R1.3 board
+ 10 R2.0 board */
+static void __init mx51_efikasb_board_id(void)
+{
+ int id;
+
+ gpio_request(EFIKASB_PCBID0, "pcb id0");
+ gpio_direction_input(EFIKASB_PCBID0);
+ gpio_request(EFIKASB_PCBID1, "pcb id1");
+ gpio_direction_input(EFIKASB_PCBID1);
+
+ id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
+ id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
+
+ switch (id) {
+ default:
+ break;
+ case 1:
+ system_rev = 0x13;
+ break;
+ case 2:
+ system_rev = 0x20;
+ break;
+ }
+}
+
+static void __init efikasb_board_init(void)
+{
+ imx51_soc_init();
+
+ mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
+ ARRAY_SIZE(mx51efikasb_pads));
+ efika_board_common_init();
+
+ mx51_efikasb_board_id();
+ mx51_efikasb_usb();
+ imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+ imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
+
+ gpio_led_register_device(-1, &mx51_efikasb_leds_data);
+ imx_add_gpio_keys(&mx51_efikasb_keys_data);
+}
+
+static void __init mx51_efikasb_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikasb_timer = {
+ .init = mx51_efikasb_timer_init,
+};
+
+MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
+ .atag_offset = 0x100,
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .init_machine = efikasb_board_init,
+ .timer = &mx51_efikasb_timer,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN IMX_GPIO_NR(4, 0)
+#define ARD_HOME IMX_GPIO_NR(5, 10)
+#define ARD_BACK IMX_GPIO_NR(5, 11)
+#define ARD_PROG IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+ /* UART1 */
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+ /* WEIM for CS1 */
+ MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+ MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+ MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+ MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+ MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+ MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+ MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+ MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+ MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+ MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+ MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+ MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+ MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+ MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+ MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+ MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+ MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+ MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+ MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+ MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+ MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+ MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+ MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+ MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+ MX53_PAD_EIM_OE__EMI_WEIM_OE,
+ MX53_PAD_EIM_RW__EMI_WEIM_RW,
+ MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+ /* SDHC1 */
+ MX53_PAD_SD1_CMD__ESDHC1_CMD,
+ MX53_PAD_SD1_CLK__ESDHC1_CLK,
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+ MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+ MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+ MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+ MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+ MX53_PAD_GPIO_1__GPIO1_1,
+ MX53_PAD_GPIO_9__GPIO1_9,
+ /* I2C2 */
+ MX53_PAD_EIM_EB2__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+ /* I2C3 */
+ MX53_PAD_GPIO_3__I2C3_SCL,
+ MX53_PAD_GPIO_16__I2C3_SDA,
+ /* GPIO */
+ MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
+ MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
+ MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
+ MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
+ MX53_PAD_GPIO_10__GPIO4_0, /* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+ GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+ GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+ GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+ GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+ .buttons = ard_buttons,
+ .nbuttons = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+ {
+ .start = MX53_CS1_64MB_BASE_ADDR,
+ .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+ .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+ .resource = ard_smsc911x_resources,
+ .dev = {
+ .platform_data = &ard_smsc911x_config,
+ },
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+ .cd_gpio = ARD_SD1_CD,
+ .wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+ .bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+ .bitrate = 400000,
+};
+
+static void __init mx53_ard_io_init(void)
+{
+ gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+ gpio_direction_input(ARD_ETHERNET_INT_B);
+
+ gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+ gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+ u32 reg;
+ void __iomem *weim_base, *iomuxc_base;
+
+ weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+ if (!weim_base)
+ return -ENOMEM;
+
+ iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+ if (!iomuxc_base) {
+ iounmap(weim_base);
+ return -ENOMEM;
+ }
+
+ /* CS1 timings for LAN9220 */
+ writel(0x20001, (weim_base + 0x18));
+ writel(0x0, (weim_base + 0x1C));
+ writel(0x16000202, (weim_base + 0x20));
+ writel(0x00000002, (weim_base + 0x24));
+ writel(0x16002082, (weim_base + 0x28));
+ writel(0x00000000, (weim_base + 0x2C));
+ writel(0x00000000, (weim_base + 0x90));
+
+ /* specify 64 MB on CS1 and CS0 on GPR1 */
+ reg = readl(iomuxc_base + 0x4);
+ reg &= ~0x3F;
+ reg |= 0x1B;
+ writel(reg, (iomuxc_base + 0x4));
+
+ iounmap(iomuxc_base);
+ iounmap(weim_base);
+
+ return 0;
+}
+
+void __init imx53_ard_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+ ARRAY_SIZE(mx53_ard_pads));
+ weim_cs_config();
+}
+
+static struct platform_device *devices[] __initdata = {
+ &ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+ imx53_soc_init();
+ imx53_add_imx_uart(0, NULL);
+
+ imx53_ard_common_init();
+ mx53_ard_io_init();
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
+ imx53_add_imx2_wdt(0, NULL);
+ imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
+ imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
+ imx_add_gpio_keys(&ard_button_data);
+ imx53_add_ahci_imx();
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+ mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+ .init = mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &mx53_ard_timer,
+ .init_machine = mx53_ard_board_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/iomux-mx53.h>
+
+#define MX53_EVK_FEC_PHY_RST IMX_GPIO_NR(7, 6)
+#define EVK_ECSPI1_CS0 IMX_GPIO_NR(2, 30)
+#define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19)
+#define MX53EVK_LED IMX_GPIO_NR(7, 7)
+
+#include "devices-imx53.h"
+
+static iomux_v3_cfg_t mx53_evk_pads[] = {
+ MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+ MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+ MX53_PAD_PATA_DIOR__UART2_RTS,
+ MX53_PAD_PATA_INTRQ__UART2_CTS,
+
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+
+ MX53_PAD_EIM_D16__ECSPI1_SCLK,
+ MX53_PAD_EIM_D17__ECSPI1_MISO,
+ MX53_PAD_EIM_D18__ECSPI1_MOSI,
+
+ /* ecspi chip select lines */
+ MX53_PAD_EIM_EB2__GPIO2_30,
+ MX53_PAD_EIM_D19__GPIO3_19,
+ /* LED */
+ MX53_PAD_PATA_DA_1__GPIO7_7,
+};
+
+static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct gpio_led mx53evk_leds[] __initconst = {
+ {
+ .name = "green",
+ .default_trigger = "heartbeat",
+ .gpio = MX53EVK_LED,
+ },
+};
+
+static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
+ .leds = mx53evk_leds,
+ .num_leds = ARRAY_SIZE(mx53evk_leds),
+};
+
+static inline void mx53_evk_init_uart(void)
+{
+ imx53_add_imx_uart(0, NULL);
+ imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
+ imx53_add_imx_uart(2, NULL);
+}
+
+static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+static inline void mx53_evk_fec_reset(void)
+{
+ int ret;
+
+ /* reset FEC PHY */
+ ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
+ "fec-phy-reset");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+ return;
+ }
+ msleep(1);
+ gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
+ {
+ .modalias = "mtd_dataflash",
+ .max_speed_hz = 25000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ },
+};
+
+static int mx53_evk_spi_cs[] = {
+ EVK_ECSPI1_CS0,
+ EVK_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx53_evk_spi_data __initconst = {
+ .chipselect = mx53_evk_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
+};
+
+void __init imx53_evk_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+ ARRAY_SIZE(mx53_evk_pads));
+}
+
+static void __init mx53_evk_board_init(void)
+{
+ imx53_soc_init();
+ imx53_evk_common_init();
+
+ mx53_evk_init_uart();
+ mx53_evk_fec_reset();
+ imx53_add_fec(&mx53_evk_fec_pdata);
+
+ imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
+ imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
+
+ imx53_add_sdhci_esdhc_imx(0, NULL);
+ imx53_add_sdhci_esdhc_imx(1, NULL);
+
+ spi_register_board_info(mx53_evk_spi_board_info,
+ ARRAY_SIZE(mx53_evk_spi_board_info));
+ imx53_add_ecspi(0, &mx53_evk_spi_data);
+ imx53_add_imx2_wdt(0, NULL);
+ gpio_led_register_device(-1, &mx53evk_leds_data);
+}
+
+static void __init mx53_evk_timer_init(void)
+{
+ mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_evk_timer = {
+ .init = mx53_evk_timer_init,
+};
+
+MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &mx53_evk_timer,
+ .init_machine = mx53_evk_board_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define MX53_LOCO_POWER IMX_GPIO_NR(1, 8)
+#define MX53_LOCO_UI1 IMX_GPIO_NR(2, 14)
+#define MX53_LOCO_UI2 IMX_GPIO_NR(2, 15)
+#define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6)
+#define LOCO_LED IMX_GPIO_NR(7, 7)
+#define LOCO_SD3_CD IMX_GPIO_NR(3, 11)
+#define LOCO_SD3_WP IMX_GPIO_NR(3, 12)
+#define LOCO_SD1_CD IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN IMX_GPIO_NR(6, 14)
+
+static iomux_v3_cfg_t mx53_loco_pads[] = {
+ /* FEC */
+ MX53_PAD_FEC_MDC__FEC_MDC,
+ MX53_PAD_FEC_MDIO__FEC_MDIO,
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1,
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0,
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1,
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0,
+ /* FEC_nRST */
+ MX53_PAD_PATA_DA_0__GPIO7_6,
+ /* FEC_nINT */
+ MX53_PAD_PATA_DATA4__GPIO2_4,
+ /* AUDMUX5 */
+ MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
+ MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
+ MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
+ MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+ /* I2C1 */
+ MX53_PAD_CSI0_DAT8__I2C1_SDA,
+ MX53_PAD_CSI0_DAT9__I2C1_SCL,
+ MX53_PAD_NANDF_CS1__GPIO6_14, /* Accelerometer Enable */
+ /* I2C2 */
+ MX53_PAD_KEY_COL3__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+ /* SD1 */
+ MX53_PAD_SD1_CMD__ESDHC1_CMD,
+ MX53_PAD_SD1_CLK__ESDHC1_CLK,
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+ /* SD1_CD */
+ MX53_PAD_EIM_DA13__GPIO3_13,
+ /* SD3 */
+ MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+ MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+ MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+ MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+ MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+ MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+ MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+ MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+ MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+ MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+ /* SD3_CD */
+ MX53_PAD_EIM_DA11__GPIO3_11,
+ /* SD3_WP */
+ MX53_PAD_EIM_DA12__GPIO3_12,
+ /* VGA */
+ MX53_PAD_EIM_OE__IPU_DI1_PIN7,
+ MX53_PAD_EIM_RW__IPU_DI1_PIN8,
+ /* DISPLB */
+ MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
+ MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
+ MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
+ MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
+ /* DISP0_POWER_EN */
+ MX53_PAD_EIM_D24__GPIO3_24,
+ /* DISP0 DET INT */
+ MX53_PAD_EIM_D31__GPIO3_31,
+ /* LVDS */
+ MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+ MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+ MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+ MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+ MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+ MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+ MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+ MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+ MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+ MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+ /* I2C1 */
+ MX53_PAD_CSI0_DAT8__I2C1_SDA,
+ MX53_PAD_CSI0_DAT9__I2C1_SCL,
+ /* UART1 */
+ MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+ MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+ /* CSI0 */
+ MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
+ MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
+ MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
+ MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
+ MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
+ MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
+ MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
+ MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
+ MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
+ MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
+ MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
+ /* DISPLAY */
+ MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+ MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+ MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+ MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+ MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+ MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+ MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+ MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+ MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+ MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+ MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+ MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+ MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+ MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+ MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+ MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+ MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+ MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+ MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+ MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+ MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+ MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+ MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+ MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+ MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+ MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+ MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+ MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+ /* Audio CLK*/
+ MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
+ /* PWM */
+ MX53_PAD_GPIO_1__PWM2_PWMO,
+ /* SPDIF */
+ MX53_PAD_GPIO_7__SPDIF_PLOCK,
+ MX53_PAD_GPIO_17__SPDIF_OUT1,
+ /* GPIO */
+ MX53_PAD_PATA_DA_1__GPIO7_7, /* LED */
+ MX53_PAD_PATA_DA_2__GPIO7_8,
+ MX53_PAD_PATA_DATA5__GPIO2_5,
+ MX53_PAD_PATA_DATA6__GPIO2_6,
+ MX53_PAD_PATA_DATA14__GPIO2_14,
+ MX53_PAD_PATA_DATA15__GPIO2_15,
+ MX53_PAD_PATA_INTRQ__GPIO7_2,
+ MX53_PAD_EIM_WAIT__GPIO5_0,
+ MX53_PAD_NANDF_WP_B__GPIO6_9,
+ MX53_PAD_NANDF_RB0__GPIO6_10,
+ MX53_PAD_NANDF_CS1__GPIO6_14,
+ MX53_PAD_NANDF_CS2__GPIO6_15,
+ MX53_PAD_NANDF_CS3__GPIO6_16,
+ MX53_PAD_GPIO_5__GPIO1_5,
+ MX53_PAD_GPIO_16__GPIO7_11,
+ MX53_PAD_GPIO_8__GPIO1_8,
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button loco_buttons[] = {
+ GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
+ GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data loco_button_data __initconst = {
+ .buttons = loco_buttons,
+ .nbuttons = ARRAY_SIZE(loco_buttons),
+};
+
+static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
+ .cd_gpio = LOCO_SD1_CD,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_NONE,
+};
+
+static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
+ .cd_gpio = LOCO_SD3_CD,
+ .wp_gpio = LOCO_SD3_WP,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_GPIO,
+};
+
+static inline void mx53_loco_fec_reset(void)
+{
+ int ret;
+
+ /* reset FEC PHY */
+ ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+ return;
+ }
+ gpio_direction_output(LOCO_FEC_PHY_RST, 0);
+ msleep(1);
+ gpio_set_value(LOCO_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_loco_fec_data __initconst = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+static const struct gpio_led mx53loco_leds[] __initconst = {
+ {
+ .name = "green",
+ .default_trigger = "heartbeat",
+ .gpio = LOCO_LED,
+ },
+};
+
+static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
+ .leds = mx53loco_leds,
+ .num_leds = ARRAY_SIZE(mx53loco_leds),
+};
+
+void __init imx53_qsb_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+ ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("mma8450", 0x1C),
+ },
+};
+
+static void __init mx53_loco_board_init(void)
+{
+ int ret;
+ imx53_soc_init();
+ imx53_qsb_common_init();
+
+ imx53_add_imx_uart(0, NULL);
+ mx53_loco_fec_reset();
+ imx53_add_fec(&mx53_loco_fec_data);
+ imx53_add_imx2_wdt(0, NULL);
+
+ ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+ if (ret)
+ pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+ i2c_register_board_info(0, mx53loco_i2c_devices,
+ ARRAY_SIZE(mx53loco_i2c_devices));
+ imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
+ imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
+ imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
+ imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
+ imx_add_gpio_keys(&loco_button_data);
+ gpio_led_register_device(-1, &mx53loco_leds_data);
+ imx53_add_ahci_imx();
+}
+
+static void __init mx53_loco_timer_init(void)
+{
+ mx53_clocks_init(32768, 24000000, 0, 0);
+}
+
+static struct sys_timer mx53_loco_timer = {
+ .init = mx53_loco_timer_init,
+};
+
+MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &mx53_loco_timer,
+ .init_machine = mx53_loco_board_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN IMX_GPIO_NR(3, 3)
+
+static iomux_v3_cfg_t mx53_smd_pads[] = {
+ MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+ MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+ MX53_PAD_PATA_DA_1__UART3_CTS,
+ MX53_PAD_PATA_DA_2__UART3_RTS,
+ /* I2C1 */
+ MX53_PAD_CSI0_DAT8__I2C1_SDA,
+ MX53_PAD_CSI0_DAT9__I2C1_SCL,
+ /* SD1 */
+ MX53_PAD_SD1_CMD__ESDHC1_CMD,
+ MX53_PAD_SD1_CLK__ESDHC1_CLK,
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+ /* SD2 */
+ MX53_PAD_SD2_CMD__ESDHC2_CMD,
+ MX53_PAD_SD2_CLK__ESDHC2_CLK,
+ MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
+ MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
+ MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
+ MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
+ /* SD3 */
+ MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+ MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+ MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+ MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+ MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+ MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+ MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+ MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+ MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+ MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+};
+
+static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mx53_smd_init_uart(void)
+{
+ imx53_add_imx_uart(0, NULL);
+ imx53_add_imx_uart(1, NULL);
+ imx53_add_imx_uart(2, &mx53_smd_uart_data);
+}
+
+static inline void mx53_smd_fec_reset(void)
+{
+ int ret;
+
+ /* reset FEC PHY */
+ ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+ return;
+ }
+ gpio_direction_output(SMD_FEC_PHY_RST, 0);
+ msleep(1);
+ gpio_set_value(SMD_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_smd_fec_data __initconst = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+ int ret;
+
+ /* Enable SATA PWR */
+ ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+ GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+ if (ret) {
+ pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+ return;
+ }
+}
+
+void __init imx53_smd_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+ ARRAY_SIZE(mx53_smd_pads));
+}
+
+static void __init mx53_smd_board_init(void)
+{
+ imx53_soc_init();
+ imx53_smd_common_init();
+
+ mx53_smd_init_uart();
+ mx53_smd_fec_reset();
+ imx53_add_fec(&mx53_smd_fec_data);
+ imx53_add_imx2_wdt(0, NULL);
+ imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
+ imx53_add_sdhci_esdhc_imx(0, NULL);
+ imx53_add_sdhci_esdhc_imx(1, NULL);
+ imx53_add_sdhci_esdhc_imx(2, NULL);
+ mx53_smd_ahci_pwr_on();
+ imx53_add_ahci_imx();
+}
+
+static void __init mx53_smd_timer_init(void)
+{
+ mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_smd_timer = {
+ .init = mx53_smd_timer_init,
+};
+
+MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &mx53_smd_timer,
+ .init_machine = mx53_smd_board_init,
+ .restart = mxc_restart,
+MACHINE_END
--- /dev/null
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/iomux-v3.h>
+
+static struct clk *gpc_dvfs_clk;
+
+static void imx5_idle(void)
+{
+ if (!need_resched()) {
+ /* gpc clock is needed for SRPG */
+ if (gpc_dvfs_clk == NULL) {
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+ if (IS_ERR(gpc_dvfs_clk))
+ goto err0;
+ }
+ clk_enable(gpc_dvfs_clk);
+ mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ if (tzic_enable_wake())
+ goto err1;
+ cpu_do_idle();
+err1:
+ clk_disable(gpc_dvfs_clk);
+ }
+err0:
+ local_irq_enable();
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+ imx_map_entry(MX50, TZIC, MT_DEVICE),
+ imx_map_entry(MX50, SPBA0, MT_DEVICE),
+ imx_map_entry(MX50, AIPS1, MT_DEVICE),
+ imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
+/*
+ * Define the MX51 memory map.
+ */
+static struct map_desc mx51_io_desc[] __initdata = {
+ imx_map_entry(MX51, TZIC, MT_DEVICE),
+ imx_map_entry(MX51, IRAM, MT_DEVICE),
+ imx_map_entry(MX51, AIPS1, MT_DEVICE),
+ imx_map_entry(MX51, SPBA0, MT_DEVICE),
+ imx_map_entry(MX51, AIPS2, MT_DEVICE),
+};
+
+/*
+ * Define the MX53 memory map.
+ */
+static struct map_desc mx53_io_desc[] __initdata = {
+ imx_map_entry(MX53, TZIC, MT_DEVICE),
+ imx_map_entry(MX53, AIPS1, MT_DEVICE),
+ imx_map_entry(MX53, SPBA0, MT_DEVICE),
+ imx_map_entry(MX53, AIPS2, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx50_map_io(void)
+{
+ iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
+void __init mx51_map_io(void)
+{
+ iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
+}
+
+void __init mx53_map_io(void)
+{
+ iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX50);
+ mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
+}
+
+void __init imx51_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX51);
+ mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
+ pm_idle = imx5_idle;
+}
+
+void __init imx53_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX53);
+ mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
+}
+
+void __init mx50_init_irq(void)
+{
+ tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
+
+void __init mx51_init_irq(void)
+{
+ tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
+}
+
+void __init mx53_init_irq(void)
+{
+ tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
+ .ap_2_ap_addr = 642,
+ .uart_2_mcu_addr = 817,
+ .mcu_2_app_addr = 747,
+ .mcu_2_shp_addr = 961,
+ .ata_2_mcu_addr = 1473,
+ .mcu_2_ata_addr = 1392,
+ .app_2_per_addr = 1033,
+ .app_2_mcu_addr = 683,
+ .shp_2_per_addr = 1251,
+ .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_platform_data imx51_sdma_pdata __initdata = {
+ .fw_name = "sdma-imx51.bin",
+ .script_addrs = &imx51_sdma_script,
+};
+
+static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
+ .ap_2_ap_addr = 642,
+ .app_2_mcu_addr = 683,
+ .mcu_2_app_addr = 747,
+ .uart_2_mcu_addr = 817,
+ .shp_2_mcu_addr = 891,
+ .mcu_2_shp_addr = 960,
+ .uartsh_2_mcu_addr = 1032,
+ .spdif_2_mcu_addr = 1100,
+ .mcu_2_spdif_addr = 1134,
+ .firi_2_mcu_addr = 1193,
+ .mcu_2_firi_addr = 1290,
+};
+
+static struct sdma_platform_data imx53_sdma_pdata __initdata = {
+ .fw_name = "sdma-imx53.bin",
+ .script_addrs = &imx53_sdma_script,
+};
+
+void __init imx50_soc_init(void)
+{
+ /* i.mx50 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+ mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+ mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+ mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+ mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+ mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
+void __init imx51_soc_init(void)
+{
+ /* i.mx51 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+ mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+ mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+ mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
+
+ /* i.mx51 has the i.mx35 type sdma */
+ imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+}
+
+void __init imx53_soc_init(void)
+{
+ /* i.mx53 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
+ mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
+ mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
+ mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
+ mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
+ mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
+ mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+
+ /* i.mx53 has the i.mx35 type sdma */
+ imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+}
--- /dev/null
+/*
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+#include "cpu_op-mx51.h"
+
+#define MX51_USB_CTRL_1_OFFSET 0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
+#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
+
+#define EFIKAMX_USB_HUB_RESET IMX_GPIO_NR(1, 5)
+#define EFIKAMX_USBH1_STP IMX_GPIO_NR(1, 27)
+
+#define EFIKAMX_SPI_CS0 IMX_GPIO_NR(4, 24)
+#define EFIKAMX_SPI_CS1 IMX_GPIO_NR(4, 25)
+
+#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6)
+
+static iomux_v3_cfg_t mx51efika_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+
+ /* SD 1 */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+ /* SD 2 */
+ MX51_PAD_SD2_CMD__SD2_CMD,
+ MX51_PAD_SD2_CLK__SD2_CLK,
+ MX51_PAD_SD2_DATA0__SD2_DATA0,
+ MX51_PAD_SD2_DATA1__SD2_DATA1,
+ MX51_PAD_SD2_DATA2__SD2_DATA2,
+ MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+ /* SD/MMC WP/CD */
+ MX51_PAD_GPIO1_0__SD1_CD,
+ MX51_PAD_GPIO1_1__SD1_WP,
+ MX51_PAD_GPIO1_7__SD2_WP,
+ MX51_PAD_GPIO1_8__SD2_CD,
+
+ /* spi */
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+ MX51_PAD_CSPI1_SS0__GPIO4_24,
+ MX51_PAD_CSPI1_SS1__GPIO4_25,
+ MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+ MX51_PAD_GPIO1_6__GPIO1_6,
+
+ /* USB HOST1 */
+ MX51_PAD_USBH1_CLK__USBH1_CLK,
+ MX51_PAD_USBH1_DIR__USBH1_DIR,
+ MX51_PAD_USBH1_NXT__USBH1_NXT,
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+ /* USB HUB RESET */
+ MX51_PAD_GPIO1_5__GPIO1_5,
+
+ /* WLAN */
+ MX51_PAD_EIM_A22__GPIO2_16,
+ MX51_PAD_EIM_A16__GPIO2_10,
+
+ /* USB PHY RESET */
+ MX51_PAD_EIM_D27__GPIO2_9,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ if (!usb_base)
+ return -ENOMEM;
+ usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+ /* Set the PHY clock to 19.2MHz */
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ v |= MX51_USB_PLL_DIV_19_2_MHZ;
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ iounmap(usb_base);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+ .init = initialize_otg_port,
+ .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+ iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+ iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *socregs_base;
+
+ mxc_iomux_v3_setup_pad(usbh1gpio);
+ gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
+ gpio_direction_output(EFIKAMX_USBH1_STP, 0);
+ msleep(1);
+ gpio_set_value(EFIKAMX_USBH1_STP, 1);
+ msleep(1);
+
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+ socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+ /* The clock for the USBH1 ULPI port will come externally */
+ /* from the PHY. */
+ v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
+ __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+ socregs_base + MX51_USB_CTRL_1_OFFSET);
+
+ iounmap(usb_base);
+
+ gpio_free(EFIKAMX_USBH1_STP);
+ mxc_iomux_v3_setup_pad(usbh1stp);
+
+ mdelay(10);
+
+ return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
+ .init = initialize_usbh1_port,
+ .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void mx51_efika_hubreset(void)
+{
+ gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
+ gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
+ msleep(1);
+ gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
+ msleep(1);
+ gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
+}
+
+static void __init mx51_efika_usb(void)
+{
+ mx51_efika_hubreset();
+
+ /* pulling it low, means no USB at all... */
+ gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
+ gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
+ msleep(1);
+ gpio_set_value(EFIKA_USB_PHY_RESET, 1);
+
+ usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+ ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
+ if (usbh1_config.otg)
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
+}
+
+static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_256K,
+ },
+ {
+ .name = "config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ },
+};
+
+static struct flash_platform_data mx51_efika_spi_flash_data = {
+ .name = "spi_flash",
+ .parts = mx51_efika_spi_nor_partitions,
+ .nr_parts = ARRAY_SIZE(mx51_efika_spi_nor_partitions),
+ .type = "sst25vf032b",
+};
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+static struct regulator_consumer_supply vdig_consumers[] = {
+ /* sgtl5000 */
+ REGULATOR_SUPPLY("VDDA", "1-000a"),
+ REGULATOR_SUPPLY("VDDD", "1-000a"),
+};
+
+static struct regulator_consumer_supply vvideo_consumers[] = {
+ /* sgtl5000 */
+ REGULATOR_SUPPLY("VDDIO", "1-000a"),
+};
+
+static struct regulator_consumer_supply vsd_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
+ REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
+};
+
+static struct regulator_consumer_supply pwgt1_consumer[] = {
+ {
+ .supply = "pwgt1",
+ }
+};
+
+static struct regulator_consumer_supply pwgt2_consumer[] = {
+ {
+ .supply = "pwgt2",
+ }
+};
+
+static struct regulator_consumer_supply coincell_consumer[] = {
+ {
+ .supply = "coincell",
+ }
+};
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = 600000,
+ .max_uV = 1375000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .state_mem = {
+ .uV = 850000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = 900000,
+ .max_uV = 1850000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = 1100000,
+ .max_uV = 1850000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .min_uV = 1100000,
+ .max_uV = 1850000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = 1050000,
+ .max_uV = 1800000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
+ .consumer_supplies = vdig_consumers,
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .min_uV = 1050000,
+ .max_uV = 1800000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .min_uV = 2400000,
+ .max_uV = 2775000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .min_uV = 2775000,
+ .max_uV = 2775000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .apply_uV = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
+ .consumer_supplies = vvideo_consumers,
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = 2300000,
+ .max_uV = 3000000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vsd_init = {
+ .constraints = {
+ .name = "VSD",
+ .min_uV = 1800000,
+ .max_uV = 3150000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
+ .consumer_supplies = vsd_consumers,
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = 2500000,
+ .max_uV = 3000000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ .min_uV = 1200000,
+ .max_uV = 3150000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .min_uV = 1200000,
+ .max_uV = 3150000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = 1800000,
+ .max_uV = 2900000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .name = "GPO1",
+ }
+};
+
+static struct regulator_init_data gpo2_init = {
+ .constraints = {
+ .name = "GPO2",
+ }
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .name = "GPO3",
+ }
+};
+
+static struct regulator_init_data gpo4_init = {
+ .constraints = {
+ .name = "GPO4",
+ }
+};
+
+static struct regulator_init_data pwgt1_init = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
+ .consumer_supplies = pwgt1_consumer,
+};
+
+static struct regulator_init_data pwgt2_init = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
+ .consumer_supplies = pwgt2_consumer,
+};
+
+static struct regulator_init_data vcoincell_init = {
+ .constraints = {
+ .name = "COINCELL",
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
+ .consumer_supplies = coincell_consumer,
+};
+
+static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
+ { .id = MC13892_SW1, .init_data = &sw1_init },
+ { .id = MC13892_SW2, .init_data = &sw2_init },
+ { .id = MC13892_SW3, .init_data = &sw3_init },
+ { .id = MC13892_SW4, .init_data = &sw4_init },
+ { .id = MC13892_SWBST, .init_data = &swbst_init },
+ { .id = MC13892_VIOHI, .init_data = &viohi_init },
+ { .id = MC13892_VPLL, .init_data = &vpll_init },
+ { .id = MC13892_VDIG, .init_data = &vdig_init },
+ { .id = MC13892_VSD, .init_data = &vsd_init },
+ { .id = MC13892_VUSB2, .init_data = &vusb2_init },
+ { .id = MC13892_VVIDEO, .init_data = &vvideo_init },
+ { .id = MC13892_VAUDIO, .init_data = &vaudio_init },
+ { .id = MC13892_VCAM, .init_data = &vcam_init },
+ { .id = MC13892_VGEN1, .init_data = &vgen1_init },
+ { .id = MC13892_VGEN2, .init_data = &vgen2_init },
+ { .id = MC13892_VGEN3, .init_data = &vgen3_init },
+ { .id = MC13892_VUSB, .init_data = &vusb_init },
+ { .id = MC13892_GPO1, .init_data = &gpo1_init },
+ { .id = MC13892_GPO2, .init_data = &gpo2_init },
+ { .id = MC13892_GPO3, .init_data = &gpo3_init },
+ { .id = MC13892_GPO4, .init_data = &gpo4_init },
+ { .id = MC13892_PWGT1SPI, .init_data = &pwgt1_init },
+ { .id = MC13892_PWGT2SPI, .init_data = &pwgt2_init },
+ { .id = MC13892_VCOINCELL, .init_data = &vcoincell_init },
+};
+
+static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
+ .flags = MC13XXX_USE_RTC,
+ .regulators = {
+ .num_regulators = ARRAY_SIZE(mx51_efika_regulators),
+ .regulators = mx51_efika_regulators,
+ },
+};
+
+static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
+ {
+ .modalias = "m25p80",
+ .max_speed_hz = 25000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .platform_data = &mx51_efika_spi_flash_data,
+ .irq = -1,
+ },
+ {
+ .modalias = "mc13892",
+ .max_speed_hz = 1000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = &mx51_efika_mc13892_data,
+ .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
+ },
+};
+
+static int mx51_efika_spi_cs[] = {
+ EFIKAMX_SPI_CS0,
+ EFIKAMX_SPI_CS1,
+};
+
+static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
+ .chipselect = mx51_efika_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
+};
+
+void __init efika_board_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
+ ARRAY_SIZE(mx51efika_pads));
+ imx51_add_imx_uart(0, &uart_pdata);
+ mx51_efika_usb();
+
+ /* FIXME: comes from original code. check this. */
+ if (mx51_revision() < IMX_CHIP_REVISION_2_0)
+ sw2_init.constraints.state_mem.uV = 1100000;
+ else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
+ sw2_init.constraints.state_mem.uV = 1250000;
+ sw1_init.constraints.state_mem.uV = 1000000;
+ }
+ if (machine_is_mx51_efikasb())
+ vgen1_init.constraints.max_uV = 1200000;
+
+ gpio_request(EFIKAMX_PMIC, "pmic irq");
+ gpio_direction_input(EFIKAMX_PMIC);
+ spi_register_board_info(mx51_efika_spi_board_info,
+ ARRAY_SIZE(mx51_efika_spi_board_info));
+ imx51_add_ecspi(0, &mx51_efika_spi_pdata);
+
+ imx51_add_pata_imx();
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+ get_cpu_op = mx51_get_cpu_op;
+#endif
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include "crm-regs-imx5.h"
+
+static struct clk *gpc_dvfs_clk;
+
+/*
+ * set cpu low power mode before WFI instruction. This function is called
+ * mx5 because it can be used for mx50, mx51, and mx53.
+ */
+void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+ u32 plat_lpc, arm_srpgcr, ccm_clpcr;
+ u32 empgc0, empgc1;
+ int stop_mode = 0;
+
+ /* always allow platform to issue a deep sleep mode request */
+ plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+ ~(MXC_CORTEXA8_PLAT_LPC_DSM);
+ ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+ arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
+ empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
+ empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+
+ switch (mode) {
+ case WAIT_CLOCKED:
+ break;
+ case WAIT_UNCLOCKED:
+ ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+ break;
+ case WAIT_UNCLOCKED_POWER_OFF:
+ case STOP_POWER_OFF:
+ plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
+ | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
+ if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+ ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+ stop_mode = 0;
+ } else {
+ ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+ stop_mode = 1;
+ }
+ arm_srpgcr |= MXC_SRPGCR_PCR;
+ break;
+ case STOP_POWER_ON:
+ ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ break;
+ default:
+ printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+ return;
+ }
+
+ __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
+ __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+ __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
+
+ /* Enable NEON SRPG for all but MX50TO1.0. */
+ if (mx50_revision() != IMX_CHIP_REVISION_1_0)
+ __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+
+ if (stop_mode) {
+ empgc0 |= MXC_SRPGCR_PCR;
+ empgc1 |= MXC_SRPGCR_PCR;
+
+ __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+ }
+}
+
+static int mx5_suspend_prepare(void)
+{
+ return clk_enable(gpc_dvfs_clk);
+}
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ mx5_cpu_lp_set(STOP_POWER_OFF);
+ break;
+ case PM_SUSPEND_STANDBY:
+ mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (state == PM_SUSPEND_MEM) {
+ local_flush_tlb_all();
+ flush_cache_all();
+
+ /*clear the EMPGC0/1 bits */
+ __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ }
+ cpu_do_idle();
+ return 0;
+}
+
+static void mx5_suspend_finish(void)
+{
+ clk_disable(gpc_dvfs_clk);
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+ return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+ .valid = mx5_pm_valid,
+ .prepare = mx5_suspend_prepare,
+ .enter = mx5_suspend_enter,
+ .finish = mx5_suspend_finish,
+};
+
+static int __init mx5_pm_init(void)
+{
+ if (!cpu_is_mx51() && !cpu_is_mx53())
+ return 0;
+
+ if (gpc_dvfs_clk == NULL)
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+ if (!IS_ERR(gpc_dvfs_clk)) {
+ if (cpu_is_mx51())
+ suspend_set_ops(&mx5_suspend_ops);
+ } else
+ return -EPERM;
+
+ return 0;
+}
+device_initcall(mx5_pm_init);
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/smp.h>
+#include <asm/smp_plat.h>
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
static void __iomem *src_base;
-#ifndef CONFIG_SMP
-#define cpu_logical_map(cpu) 0
-#endif
-
void imx_enable_cpu(int cpu, bool enable)
{
u32 mask, val;
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
extern volatile int pen_release;
#include <asm/cacheflush.h>
#include <asm/cputype.h>
#include <asm/mach-types.h>
+#include <asm/smp_plat.h>
#include <mach/msm_iomap.h>
+++ /dev/null
-if ARCH_MX5
-
-# ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single
-# image. So for most time, SOC_IMX50/51/53 should be used.
-
-config ARCH_MX51
- bool
-
-config ARCH_MX50
- bool
-
-config ARCH_MX53
- bool
-
-config SOC_IMX50
- bool
- select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
- select MXC_TZIC
- select ARCH_MXC_IOMUX_V3
- select ARCH_MXC_AUDMUX_V2
- select ARCH_HAS_CPUFREQ
- select ARCH_MX50
-
-config SOC_IMX51
- bool
- select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
- select MXC_TZIC
- select ARCH_MXC_IOMUX_V3
- select ARCH_MXC_AUDMUX_V2
- select ARCH_HAS_CPUFREQ
- select ARCH_MX51
-
-config SOC_IMX53
- bool
- select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
- select MXC_TZIC
- select ARCH_MXC_IOMUX_V3
- select ARCH_MX53
-
-#comment "i.MX50 machines:"
-
-config MACH_MX50_RDP
- bool "Support MX50 reference design platform"
- depends on BROKEN
- select SOC_IMX50
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_SPI_IMX
- help
- Include support for MX50 reference design platform (RDP) board. This
- includes specific configurations for the board and its peripherals.
-
-comment "i.MX51 machines:"
-
-config MACH_IMX51_DT
- bool "Support i.MX51 platforms from device tree"
- select SOC_IMX51
- select USE_OF
- select MACH_MX51_BABBAGE
- help
- Include support for Freescale i.MX51 based platforms
- using the device tree for discovery
-
-config MACH_MX51_BABBAGE
- bool "Support MX51 BABBAGE platforms"
- select SOC_IMX51
- select IMX_HAVE_PLATFORM_FSL_USB2_UDC
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_MXC_EHCI
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_SPI_IMX
- help
- Include support for MX51 Babbage platform, also known as MX51EVK in
- u-boot. This includes specific configurations for the board and its
- peripherals.
-
-config MACH_MX51_3DS
- bool "Support MX51PDK (3DS)"
- select SOC_IMX51
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_KEYPAD
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_SPI_IMX
- select MXC_DEBUG_BOARD
- help
- Include support for MX51PDK (3DS) platform. This includes specific
- configurations for the board and its peripherals.
-
-config MACH_EUKREA_CPUIMX51
- bool "Support Eukrea CPUIMX51 module"
- select SOC_IMX51
- select IMX_HAVE_PLATFORM_FSL_USB2_UDC
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_MXC_EHCI
- select IMX_HAVE_PLATFORM_MXC_NAND
- select IMX_HAVE_PLATFORM_SPI_IMX
- help
- Include support for Eukrea CPUIMX51 platform. This includes
- specific configurations for the module and its peripherals.
-
-choice
- prompt "Baseboard"
- depends on MACH_EUKREA_CPUIMX51
- default MACH_EUKREA_MBIMX51_BASEBOARD
-
-config MACH_EUKREA_MBIMX51_BASEBOARD
- prompt "Eukrea MBIMX51 development board"
- bool
- select IMX_HAVE_PLATFORM_IMX_KEYPAD
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select LEDS_GPIO_REGISTER
- help
- This adds board specific devices that can be found on Eukrea's
- MBIMX51 evaluation board.
-
-endchoice
-
-config MACH_EUKREA_CPUIMX51SD
- bool "Support Eukrea CPUIMX51SD module"
- select SOC_IMX51
- select IMX_HAVE_PLATFORM_FSL_USB2_UDC
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_MXC_EHCI
- select IMX_HAVE_PLATFORM_MXC_NAND
- select IMX_HAVE_PLATFORM_SPI_IMX
- help
- Include support for Eukrea CPUIMX51SD platform. This includes
- specific configurations for the module and its peripherals.
-
-choice
- prompt "Baseboard"
- depends on MACH_EUKREA_CPUIMX51SD
- default MACH_EUKREA_MBIMXSD51_BASEBOARD
-
-config MACH_EUKREA_MBIMXSD51_BASEBOARD
- prompt "Eukrea MBIMXSD development board"
- bool
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select LEDS_GPIO_REGISTER
- help
- This adds board specific devices that can be found on Eukrea's
- MBIMXSD evaluation board.
-
-endchoice
-
-config MX51_EFIKA_COMMON
- bool
- select SOC_IMX51
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_MXC_EHCI
- select IMX_HAVE_PLATFORM_PATA_IMX
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_SPI_IMX
- select MXC_ULPI if USB_ULPI
-
-config MACH_MX51_EFIKAMX
- bool "Support MX51 Genesi Efika MX nettop"
- select LEDS_GPIO_REGISTER
- select MX51_EFIKA_COMMON
- help
- Include support for Genesi Efika MX nettop. This includes specific
- configurations for the board and its peripherals.
-
-config MACH_MX51_EFIKASB
- bool "Support MX51 Genesi Efika Smartbook"
- select LEDS_GPIO_REGISTER
- select MX51_EFIKA_COMMON
- help
- Include support for Genesi Efika Smartbook. This includes specific
- configurations for the board and its peripherals.
-
-comment "i.MX53 machines:"
-
-config MACH_IMX53_DT
- bool "Support i.MX53 platforms from device tree"
- select SOC_IMX53
- select USE_OF
- select MACH_MX53_ARD
- select MACH_MX53_EVK
- select MACH_MX53_LOCO
- select MACH_MX53_SMD
- help
- Include support for Freescale i.MX53 based platforms
- using the device tree for discovery
-
-config MACH_MX53_EVK
- bool "Support MX53 EVK platforms"
- select SOC_IMX53
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_SPI_IMX
- select LEDS_GPIO_REGISTER
- help
- Include support for MX53 EVK platform. This includes specific
- configurations for the board and its peripherals.
-
-config MACH_MX53_SMD
- bool "Support MX53 SMD platforms"
- select SOC_IMX53
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- help
- Include support for MX53 SMD platform. This includes specific
- configurations for the board and its peripherals.
-
-config MACH_MX53_LOCO
- bool "Support MX53 LOCO platforms"
- select SOC_IMX53
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_GPIO_KEYS
- select LEDS_GPIO_REGISTER
- help
- Include support for MX53 LOCO platform. This includes specific
- configurations for the board and its peripherals.
-
-config MACH_MX53_ARD
- bool "Support MX53 ARD platforms"
- select SOC_IMX53
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select IMX_HAVE_PLATFORM_GPIO_KEYS
- help
- Include support for MX53 ARD platform. This includes specific
- configurations for the board and its peripherals.
-
-endif
+++ /dev/null
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-obj-y := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
-
-obj-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o
-obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
-obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
-obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
-obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
-obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
-obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
-obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
-obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
-obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
-obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
-obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
-obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
-
-obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
-obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
+++ /dev/null
- zreladdr-$(CONFIG_ARCH_MX50) += 0x70008000
-params_phys-$(CONFIG_ARCH_MX50) := 0x70000100
-initrd_phys-$(CONFIG_ARCH_MX50) := 0x70800000
- zreladdr-$(CONFIG_ARCH_MX51) += 0x90008000
-params_phys-$(CONFIG_ARCH_MX51) := 0x90000100
-initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000
- zreladdr-$(CONFIG_ARCH_MX53) += 0x70008000
-params_phys-$(CONFIG_ARCH_MX53) := 0x70000100
-initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000
+++ /dev/null
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-
-#define CPUIMX51_USBH1_STP IMX_GPIO_NR(1, 27)
-#define CPUIMX51_QUARTA_GPIO IMX_GPIO_NR(3, 28)
-#define CPUIMX51_QUARTB_GPIO IMX_GPIO_NR(3, 25)
-#define CPUIMX51_QUARTC_GPIO IMX_GPIO_NR(3, 26)
-#define CPUIMX51_QUARTD_GPIO IMX_GPIO_NR(3, 27)
-#define CPUIMX51_QUART_XTAL 14745600
-#define CPUIMX51_QUART_REGSHIFT 17
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET 0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
-
-#define MX51_USB_PLLDIV_12_MHZ 0x00
-#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
-#define MX51_USB_PLL_DIV_24_MHZ 0x02
-
-static struct plat_serial8250_port serial_platform_data[] = {
- {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- }
-};
-
-static struct platform_device serial_device = {
- .name = "serial8250",
- .id = 0,
- .dev = {
- .platform_data = serial_platform_data,
- },
-};
-
-static struct platform_device *devices[] __initdata = {
- &serial_device,
-};
-
-static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
- /* UART1 */
- MX51_PAD_UART1_RXD__UART1_RXD,
- MX51_PAD_UART1_TXD__UART1_TXD,
- MX51_PAD_UART1_RTS__UART1_RTS,
- MX51_PAD_UART1_CTS__UART1_CTS,
-
- /* I2C2 */
- MX51_PAD_GPIO1_2__I2C2_SCL,
- MX51_PAD_GPIO1_3__I2C2_SDA,
- MX51_PAD_NANDF_D10__GPIO3_30,
-
- /* QUART IRQ */
- MX51_PAD_NANDF_D15__GPIO3_25,
- MX51_PAD_NANDF_D14__GPIO3_26,
- MX51_PAD_NANDF_D13__GPIO3_27,
- MX51_PAD_NANDF_D12__GPIO3_28,
-
- /* USB HOST1 */
- MX51_PAD_USBH1_CLK__USBH1_CLK,
- MX51_PAD_USBH1_DIR__USBH1_DIR,
- MX51_PAD_USBH1_NXT__USBH1_NXT,
- MX51_PAD_USBH1_DATA0__USBH1_DATA0,
- MX51_PAD_USBH1_DATA1__USBH1_DATA1,
- MX51_PAD_USBH1_DATA2__USBH1_DATA2,
- MX51_PAD_USBH1_DATA3__USBH1_DATA3,
- MX51_PAD_USBH1_DATA4__USBH1_DATA4,
- MX51_PAD_USBH1_DATA5__USBH1_DATA5,
- MX51_PAD_USBH1_DATA6__USBH1_DATA6,
- MX51_PAD_USBH1_DATA7__USBH1_DATA7,
- MX51_PAD_USBH1_STP__USBH1_STP,
-};
-
-static const struct mxc_nand_platform_data
- eukrea_cpuimx51_nand_board_info __initconst = {
- .width = 1,
- .hw_ecc = 1,
- .flash_bbt = 1,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const
-struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- },
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* Set the PHY clock to 19.2MHz */
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
- v |= MX51_USB_PLL_DIV_19_2_MHZ;
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* The clock for the USBH1 ULPI port will come externally from the PHY. */
- v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
- __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
- MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
- .init = initialize_otg_port,
- .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
- .operating_mode = FSL_USB2_DR_DEVICE,
- .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
- .init = initialize_usbh1_port,
- .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51_otg_mode(char *options)
-{
- if (!strcmp(options, "host"))
- otg_mode_host = 1;
- else if (!strcmp(options, "device"))
- otg_mode_host = 0;
- else
- pr_info("otg_mode neither \"host\" nor \"device\". "
- "Defaulting to device\n");
- return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
-
-/*
- * Board specific initialization.
- */
-static void __init eukrea_cpuimx51_init(void)
-{
- imx51_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
- ARRAY_SIZE(eukrea_cpuimx51_pads));
-
- imx51_add_imx_uart(0, &uart_pdata);
- imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
-
- gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
- gpio_direction_input(CPUIMX51_QUARTA_GPIO);
- gpio_free(CPUIMX51_QUARTA_GPIO);
- gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
- gpio_direction_input(CPUIMX51_QUARTB_GPIO);
- gpio_free(CPUIMX51_QUARTB_GPIO);
- gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
- gpio_direction_input(CPUIMX51_QUARTC_GPIO);
- gpio_free(CPUIMX51_QUARTC_GPIO);
- gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
- gpio_direction_input(CPUIMX51_QUARTD_GPIO);
- gpio_free(CPUIMX51_QUARTD_GPIO);
-
- imx51_add_fec(NULL);
- platform_add_devices(devices, ARRAY_SIZE(devices));
-
- imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
- i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
- ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
-
- if (otg_mode_host)
- imx51_add_mxc_ehci_otg(&dr_utmi_config);
- else {
- initialize_otg_port(NULL);
- imx51_add_fsl_usb2_udc(&usb_pdata);
- }
- imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
- eukrea_mbimx51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
- .init = eukrea_cpuimx51_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
- /* Maintainer: Eric Bénard <eric@eukrea.com> */
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &mxc_timer,
- .init_machine = eukrea_cpuimx51_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/i2c-gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/can/platform/mcp251x.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "cpu_op-mx51.h"
-
-#define USBH1_RST IMX_GPIO_NR(2, 28)
-#define ETH_RST IMX_GPIO_NR(2, 31)
-#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 12)
-#define CAN_IRQGPIO IMX_GPIO_NR(1, 1)
-#define CAN_RST IMX_GPIO_NR(4, 15)
-#define CAN_NCS IMX_GPIO_NR(4, 24)
-#define CAN_RXOBF IMX_GPIO_NR(1, 4)
-#define CAN_RX1BF IMX_GPIO_NR(1, 6)
-#define CAN_TXORTS IMX_GPIO_NR(1, 7)
-#define CAN_TX1RTS IMX_GPIO_NR(1, 8)
-#define CAN_TX2RTS IMX_GPIO_NR(1, 9)
-#define I2C_SCL IMX_GPIO_NR(4, 16)
-#define I2C_SDA IMX_GPIO_NR(4, 17)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET 0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
-
-#define MX51_USB_PLLDIV_12_MHZ 0x00
-#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
-#define MX51_USB_PLL_DIV_24_MHZ 0x02
-
-static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
- /* UART1 */
- MX51_PAD_UART1_RXD__UART1_RXD,
- MX51_PAD_UART1_TXD__UART1_TXD,
- MX51_PAD_UART1_RTS__UART1_RTS,
- MX51_PAD_UART1_CTS__UART1_CTS,
-
- /* USB HOST1 */
- MX51_PAD_USBH1_CLK__USBH1_CLK,
- MX51_PAD_USBH1_DIR__USBH1_DIR,
- MX51_PAD_USBH1_NXT__USBH1_NXT,
- MX51_PAD_USBH1_DATA0__USBH1_DATA0,
- MX51_PAD_USBH1_DATA1__USBH1_DATA1,
- MX51_PAD_USBH1_DATA2__USBH1_DATA2,
- MX51_PAD_USBH1_DATA3__USBH1_DATA3,
- MX51_PAD_USBH1_DATA4__USBH1_DATA4,
- MX51_PAD_USBH1_DATA5__USBH1_DATA5,
- MX51_PAD_USBH1_DATA6__USBH1_DATA6,
- MX51_PAD_USBH1_DATA7__USBH1_DATA7,
- MX51_PAD_USBH1_STP__USBH1_STP,
- MX51_PAD_EIM_CS3__GPIO2_28, /* PHY nRESET */
-
- /* FEC */
- MX51_PAD_EIM_DTACK__GPIO2_31, /* PHY nRESET */
-
- /* HSI2C */
- MX51_PAD_I2C1_CLK__GPIO4_16,
- MX51_PAD_I2C1_DAT__GPIO4_17,
-
- /* CAN */
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
- MX51_PAD_CSPI1_SS0__GPIO4_24, /* nCS */
- MX51_PAD_CSI2_PIXCLK__GPIO4_15, /* nReset */
- MX51_PAD_GPIO1_1__GPIO1_1, /* IRQ */
- MX51_PAD_GPIO1_4__GPIO1_4, /* Control signals */
- MX51_PAD_GPIO1_6__GPIO1_6,
- MX51_PAD_GPIO1_7__GPIO1_7,
- MX51_PAD_GPIO1_8__GPIO1_8,
- MX51_PAD_GPIO1_9__GPIO1_9,
-
- /* Touchscreen */
- /* IRQ */
- NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
- PAD_CTL_PKE | PAD_CTL_SRE_FAST |
- PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct tsc2007_platform_data tsc2007_info = {
- .model = 2007,
- .x_plate_ohms = 180,
-};
-
-static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- }, {
- I2C_BOARD_INFO("tsc2007", 0x49),
- .type = "tsc2007",
- .platform_data = &tsc2007_info,
- .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
- },
-};
-
-static const struct mxc_nand_platform_data
- eukrea_cpuimx51sd_nand_board_info __initconst = {
- .width = 1,
- .hw_ecc = 1,
- .flash_bbt = 1,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* Set the PHY clock to 19.2MHz */
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
- v |= MX51_USB_PLL_DIV_19_2_MHZ;
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* The clock for the USBH1 ULPI port will come from the PHY. */
- v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
- __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
- usbother_base + MX51_USB_CTRL_1_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
- MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
- .init = initialize_otg_port,
- .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
- .operating_mode = FSL_USB2_DR_DEVICE,
- .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
- .init = initialize_usbh1_port,
- .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51sd_otg_mode(char *options)
-{
- if (!strcmp(options, "host"))
- otg_mode_host = 1;
- else if (!strcmp(options, "device"))
- otg_mode_host = 0;
- else
- pr_info("otg_mode neither \"host\" nor \"device\". "
- "Defaulting to device\n");
- return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
-
-static struct i2c_gpio_platform_data pdata = {
- .sda_pin = I2C_SDA,
- .sda_is_open_drain = 0,
- .scl_pin = I2C_SCL,
- .scl_is_open_drain = 0,
- .udelay = 2,
-};
-
-static struct platform_device hsi2c_gpio_device = {
- .name = "i2c-gpio",
- .id = 0,
- .dev.platform_data = &pdata,
-};
-
-static struct mcp251x_platform_data mcp251x_info = {
- .oscillator_frequency = 24E6,
-};
-
-static struct spi_board_info cpuimx51sd_spi_device[] = {
- {
- .modalias = "mcp2515",
- .max_speed_hz = 10000000,
- .bus_num = 0,
- .mode = SPI_MODE_0,
- .chip_select = 0,
- .platform_data = &mcp251x_info,
- .irq = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
- },
-};
-
-static int cpuimx51sd_spi1_cs[] = {
- CAN_NCS,
-};
-
-static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
- .chipselect = cpuimx51sd_spi1_cs,
- .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
-};
-
-static struct platform_device *platform_devices[] __initdata = {
- &hsi2c_gpio_device,
-};
-
-static void __init eukrea_cpuimx51sd_init(void)
-{
- imx51_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
- ARRAY_SIZE(eukrea_cpuimx51sd_pads));
-
-#if defined(CONFIG_CPU_FREQ_IMX)
- get_cpu_op = mx51_get_cpu_op;
-#endif
-
- imx51_add_imx_uart(0, &uart_pdata);
- imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
-
- gpio_request(ETH_RST, "eth_rst");
- gpio_set_value(ETH_RST, 1);
- imx51_add_fec(NULL);
-
- gpio_request(CAN_IRQGPIO, "can_irq");
- gpio_direction_input(CAN_IRQGPIO);
- gpio_free(CAN_IRQGPIO);
- gpio_request(CAN_NCS, "can_ncs");
- gpio_direction_output(CAN_NCS, 1);
- gpio_free(CAN_NCS);
- gpio_request(CAN_RST, "can_rst");
- gpio_direction_output(CAN_RST, 0);
- msleep(20);
- gpio_set_value(CAN_RST, 1);
- imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
- spi_register_board_info(cpuimx51sd_spi_device,
- ARRAY_SIZE(cpuimx51sd_spi_device));
-
- gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
- gpio_direction_input(TSC2007_IRQGPIO);
- gpio_free(TSC2007_IRQGPIO);
-
- i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
- ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-
- if (otg_mode_host)
- imx51_add_mxc_ehci_otg(&dr_utmi_config);
- else {
- initialize_otg_port(NULL);
- imx51_add_fsl_usb2_udc(&usb_pdata);
- }
-
- gpio_request(USBH1_RST, "usb_rst");
- gpio_direction_output(USBH1_RST, 0);
- msleep(20);
- gpio_set_value(USBH1_RST, 1);
- imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
- eukrea_mbimxsd51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51sd_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
- .init = eukrea_cpuimx51sd_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
- /* Maintainer: Eric Bénard <eric@eukrea.com> */
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &mxc_timer,
- .init_machine = eukrea_cpuimx51sd_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx50.h>
-
-#include <asm/irq.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx50.h"
-
-#define FEC_EN IMX_GPIO_NR(6, 23)
-#define FEC_RESET_B IMX_GPIO_NR(4, 12)
-
-static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
- /* SD1 */
- MX50_PAD_ECSPI2_SS0__GPIO_4_19,
- MX50_PAD_EIM_CRE__GPIO_1_27,
- MX50_PAD_SD1_CMD__SD1_CMD,
-
- MX50_PAD_SD1_CLK__SD1_CLK,
- MX50_PAD_SD1_D0__SD1_D0,
- MX50_PAD_SD1_D1__SD1_D1,
- MX50_PAD_SD1_D2__SD1_D2,
- MX50_PAD_SD1_D3__SD1_D3,
-
- /* SD2 */
- MX50_PAD_SD2_CD__GPIO_5_17,
- MX50_PAD_SD2_WP__GPIO_5_16,
- MX50_PAD_SD2_CMD__SD2_CMD,
- MX50_PAD_SD2_CLK__SD2_CLK,
- MX50_PAD_SD2_D0__SD2_D0,
- MX50_PAD_SD2_D1__SD2_D1,
- MX50_PAD_SD2_D2__SD2_D2,
- MX50_PAD_SD2_D3__SD2_D3,
- MX50_PAD_SD2_D4__SD2_D4,
- MX50_PAD_SD2_D5__SD2_D5,
- MX50_PAD_SD2_D6__SD2_D6,
- MX50_PAD_SD2_D7__SD2_D7,
-
- /* SD3 */
- MX50_PAD_SD3_CMD__SD3_CMD,
- MX50_PAD_SD3_CLK__SD3_CLK,
- MX50_PAD_SD3_D0__SD3_D0,
- MX50_PAD_SD3_D1__SD3_D1,
- MX50_PAD_SD3_D2__SD3_D2,
- MX50_PAD_SD3_D3__SD3_D3,
- MX50_PAD_SD3_D4__SD3_D4,
- MX50_PAD_SD3_D5__SD3_D5,
- MX50_PAD_SD3_D6__SD3_D6,
- MX50_PAD_SD3_D7__SD3_D7,
-
- /* PWR_INT */
- MX50_PAD_ECSPI2_MISO__GPIO_4_18,
-
- /* UART pad setting */
- MX50_PAD_UART1_TXD__UART1_TXD,
- MX50_PAD_UART1_RXD__UART1_RXD,
- MX50_PAD_UART1_RTS__UART1_RTS,
- MX50_PAD_UART2_TXD__UART2_TXD,
- MX50_PAD_UART2_RXD__UART2_RXD,
- MX50_PAD_UART2_CTS__UART2_CTS,
- MX50_PAD_UART2_RTS__UART2_RTS,
-
- MX50_PAD_I2C1_SCL__I2C1_SCL,
- MX50_PAD_I2C1_SDA__I2C1_SDA,
- MX50_PAD_I2C2_SCL__I2C2_SCL,
- MX50_PAD_I2C2_SDA__I2C2_SDA,
-
- MX50_PAD_EPITO__USBH1_PWR,
- /* Need to comment below line if
- * one needs to debug owire.
- */
- MX50_PAD_OWIRE__USBH1_OC,
- /* using gpio to control otg pwr */
- MX50_PAD_PWM2__GPIO_6_25,
- MX50_PAD_I2C3_SCL__USBOTG_OC,
-
- MX50_PAD_SSI_RXC__FEC_MDIO,
- MX50_PAD_SSI_RXFS__FEC_MDC,
- MX50_PAD_DISP_D0__FEC_TXCLK,
- MX50_PAD_DISP_D1__FEC_RX_ER,
- MX50_PAD_DISP_D2__FEC_RX_DV,
- MX50_PAD_DISP_D3__FEC_RXD1,
- MX50_PAD_DISP_D4__FEC_RXD0,
- MX50_PAD_DISP_D5__FEC_TX_EN,
- MX50_PAD_DISP_D6__FEC_TXD1,
- MX50_PAD_DISP_D7__FEC_TXD0,
- MX50_PAD_I2C3_SDA__GPIO_6_23,
- MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
-
- MX50_PAD_CSPI_SS0__CSPI_SS0,
- MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
- MX50_PAD_CSPI_MOSI__CSPI_MOSI,
- MX50_PAD_CSPI_MISO__CSPI_MISO,
-
- /* SGTL500_OSC_EN */
- MX50_PAD_UART1_CTS__GPIO_6_8,
-
- /* SGTL_AMP_SHDN */
- MX50_PAD_UART3_RXD__GPIO_6_15,
-
- /* Keypad */
- MX50_PAD_KEY_COL0__KEY_COL0,
- MX50_PAD_KEY_ROW0__KEY_ROW0,
- MX50_PAD_KEY_COL1__KEY_COL1,
- MX50_PAD_KEY_ROW1__KEY_ROW1,
- MX50_PAD_KEY_COL2__KEY_COL2,
- MX50_PAD_KEY_ROW2__KEY_ROW2,
- MX50_PAD_KEY_COL3__KEY_COL3,
- MX50_PAD_KEY_ROW3__KEY_ROW3,
- MX50_PAD_EIM_DA0__KEY_COL4,
- MX50_PAD_EIM_DA1__KEY_ROW4,
- MX50_PAD_EIM_DA2__KEY_COL5,
- MX50_PAD_EIM_DA3__KEY_ROW5,
- MX50_PAD_EIM_DA4__KEY_COL6,
- MX50_PAD_EIM_DA5__KEY_ROW6,
- MX50_PAD_EIM_DA6__KEY_COL7,
- MX50_PAD_EIM_DA7__KEY_ROW7,
- /*EIM pads */
- MX50_PAD_EIM_DA8__GPIO_1_8,
- MX50_PAD_EIM_DA9__GPIO_1_9,
- MX50_PAD_EIM_DA10__GPIO_1_10,
- MX50_PAD_EIM_DA11__GPIO_1_11,
- MX50_PAD_EIM_DA12__GPIO_1_12,
- MX50_PAD_EIM_DA13__GPIO_1_13,
- MX50_PAD_EIM_DA14__GPIO_1_14,
- MX50_PAD_EIM_DA15__GPIO_1_15,
- MX50_PAD_EIM_CS2__GPIO_1_16,
- MX50_PAD_EIM_CS1__GPIO_1_17,
- MX50_PAD_EIM_CS0__GPIO_1_18,
- MX50_PAD_EIM_EB0__GPIO_1_19,
- MX50_PAD_EIM_EB1__GPIO_1_20,
- MX50_PAD_EIM_WAIT__GPIO_1_21,
- MX50_PAD_EIM_BCLK__GPIO_1_22,
- MX50_PAD_EIM_RDY__GPIO_1_23,
- MX50_PAD_EIM_OE__GPIO_1_24,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct fec_platform_data fec_data __initconst = {
- .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static inline void mx50_rdp_fec_reset(void)
-{
- gpio_request(FEC_EN, "fec-en");
- gpio_direction_output(FEC_EN, 0);
- gpio_request(FEC_RESET_B, "fec-reset_b");
- gpio_direction_output(FEC_RESET_B, 0);
- msleep(1);
- gpio_set_value(FEC_RESET_B, 1);
-}
-
-static const struct imxi2c_platform_data i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx50_rdp_board_init(void)
-{
- imx50_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
- ARRAY_SIZE(mx50_rdp_pads));
-
- imx50_add_imx_uart(0, &uart_pdata);
- imx50_add_imx_uart(1, &uart_pdata);
- mx50_rdp_fec_reset();
- imx50_add_fec(&fec_data);
- imx50_add_imx_i2c(0, &i2c_data);
- imx50_add_imx_i2c(1, &i2c_data);
- imx50_add_imx_i2c(2, &i2c_data);
-}
-
-static void __init mx50_rdp_timer_init(void)
-{
- mx50_clocks_init(32768, 24000000, 22579200);
-}
-
-static struct sys_timer mx50_rdp_timer = {
- .init = mx50_rdp_timer_init,
-};
-
-MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
- .map_io = mx50_map_io,
- .init_early = imx50_init_early,
- .init_irq = mx50_init_irq,
- .handle_irq = imx50_handle_irq,
- .timer = &mx50_rdp_timer,
- .init_machine = mx50_rdp_board_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/3ds_debugboard.h>
-
-#include "devices-imx51.h"
-
-#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6))
-#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28)
-
-static iomux_v3_cfg_t mx51_3ds_pads[] = {
- /* UART1 */
- MX51_PAD_UART1_RXD__UART1_RXD,
- MX51_PAD_UART1_TXD__UART1_TXD,
- MX51_PAD_UART1_RTS__UART1_RTS,
- MX51_PAD_UART1_CTS__UART1_CTS,
-
- /* UART2 */
- MX51_PAD_UART2_RXD__UART2_RXD,
- MX51_PAD_UART2_TXD__UART2_TXD,
- MX51_PAD_EIM_D25__UART2_CTS,
- MX51_PAD_EIM_D26__UART2_RTS,
-
- /* UART3 */
- MX51_PAD_UART3_RXD__UART3_RXD,
- MX51_PAD_UART3_TXD__UART3_TXD,
- MX51_PAD_EIM_D24__UART3_CTS,
- MX51_PAD_EIM_D27__UART3_RTS,
-
- /* CPLD PARENT IRQ PIN */
- MX51_PAD_GPIO1_6__GPIO1_6,
-
- /* KPP */
- MX51_PAD_KEY_ROW0__KEY_ROW0,
- MX51_PAD_KEY_ROW1__KEY_ROW1,
- MX51_PAD_KEY_ROW2__KEY_ROW2,
- MX51_PAD_KEY_ROW3__KEY_ROW3,
- MX51_PAD_KEY_COL0__KEY_COL0,
- MX51_PAD_KEY_COL1__KEY_COL1,
- MX51_PAD_KEY_COL2__KEY_COL2,
- MX51_PAD_KEY_COL3__KEY_COL3,
- MX51_PAD_KEY_COL4__KEY_COL4,
- MX51_PAD_KEY_COL5__KEY_COL5,
-
- /* eCSPI2 */
- MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
- MX51_PAD_NANDF_RB3__ECSPI2_MISO,
- MX51_PAD_NANDF_D15__ECSPI2_MOSI,
- MX51_PAD_NANDF_D12__GPIO3_28,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mx51_3ds_board_keymap[] = {
- KEY(0, 0, KEY_1),
- KEY(0, 1, KEY_2),
- KEY(0, 2, KEY_3),
- KEY(0, 3, KEY_F1),
- KEY(0, 4, KEY_UP),
- KEY(0, 5, KEY_F2),
-
- KEY(1, 0, KEY_4),
- KEY(1, 1, KEY_5),
- KEY(1, 2, KEY_6),
- KEY(1, 3, KEY_LEFT),
- KEY(1, 4, KEY_SELECT),
- KEY(1, 5, KEY_RIGHT),
-
- KEY(2, 0, KEY_7),
- KEY(2, 1, KEY_8),
- KEY(2, 2, KEY_9),
- KEY(2, 3, KEY_F3),
- KEY(2, 4, KEY_DOWN),
- KEY(2, 5, KEY_F4),
-
- KEY(3, 0, KEY_0),
- KEY(3, 1, KEY_OK),
- KEY(3, 2, KEY_ESC),
- KEY(3, 3, KEY_ENTER),
- KEY(3, 4, KEY_MENU),
- KEY(3, 5, KEY_BACK)
-};
-
-static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
- .keymap = mx51_3ds_board_keymap,
- .keymap_size = ARRAY_SIZE(mx51_3ds_board_keymap),
-};
-
-static int mx51_3ds_spi2_cs[] = {
- MXC_SPI_CS(0),
- MX51_3DS_ECSPI2_CS,
-};
-
-static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
- .chipselect = mx51_3ds_spi2_cs,
- .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs),
-};
-
-static struct spi_board_info mx51_3ds_spi_nor_device[] = {
- {
- .modalias = "m25p80",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 1,
- .mode = SPI_MODE_0,
- .platform_data = NULL,},
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_3ds_init(void)
-{
- imx51_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
- ARRAY_SIZE(mx51_3ds_pads));
-
- imx51_add_imx_uart(0, &uart_pdata);
- imx51_add_imx_uart(1, &uart_pdata);
- imx51_add_imx_uart(2, &uart_pdata);
-
- imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
- spi_register_board_info(mx51_3ds_spi_nor_device,
- ARRAY_SIZE(mx51_3ds_spi_nor_device));
-
- if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
- printk(KERN_WARNING "Init of the debugboard failed, all "
- "devices on the board are unusable.\n");
-
- imx51_add_sdhci_esdhc_imx(0, NULL);
- imx51_add_imx_keypad(&mx51_3ds_map_data);
- imx51_add_imx2_wdt(0, NULL);
-}
-
-static void __init mx51_3ds_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_3ds_timer = {
- .init = mx51_3ds_timer_init,
-};
-
-MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
- /* Maintainer: Freescale Semiconductor, Inc. */
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &mx51_3ds_timer,
- .init_machine = mx51_3ds_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "cpu_op-mx51.h"
-
-#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7)
-#define BABBAGE_USBH1_STP IMX_GPIO_NR(1, 27)
-#define BABBAGE_USB_PHY_RESET IMX_GPIO_NR(2, 5)
-#define BABBAGE_FEC_PHY_RESET IMX_GPIO_NR(2, 14)
-#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
-#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
-#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
-#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET 0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
-
-#define MX51_USB_PLLDIV_12_MHZ 0x00
-#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
-#define MX51_USB_PLL_DIV_24_MHZ 0x02
-
-static struct gpio_keys_button babbage_buttons[] = {
- {
- .gpio = BABBAGE_POWER_KEY,
- .code = BTN_0,
- .desc = "PWR",
- .active_low = 1,
- .wakeup = 1,
- },
-};
-
-static const struct gpio_keys_platform_data imx_button_data __initconst = {
- .buttons = babbage_buttons,
- .nbuttons = ARRAY_SIZE(babbage_buttons),
-};
-
-static iomux_v3_cfg_t mx51babbage_pads[] = {
- /* UART1 */
- MX51_PAD_UART1_RXD__UART1_RXD,
- MX51_PAD_UART1_TXD__UART1_TXD,
- MX51_PAD_UART1_RTS__UART1_RTS,
- MX51_PAD_UART1_CTS__UART1_CTS,
-
- /* UART2 */
- MX51_PAD_UART2_RXD__UART2_RXD,
- MX51_PAD_UART2_TXD__UART2_TXD,
-
- /* UART3 */
- MX51_PAD_EIM_D25__UART3_RXD,
- MX51_PAD_EIM_D26__UART3_TXD,
- MX51_PAD_EIM_D27__UART3_RTS,
- MX51_PAD_EIM_D24__UART3_CTS,
-
- /* I2C1 */
- MX51_PAD_EIM_D16__I2C1_SDA,
- MX51_PAD_EIM_D19__I2C1_SCL,
-
- /* I2C2 */
- MX51_PAD_KEY_COL4__I2C2_SCL,
- MX51_PAD_KEY_COL5__I2C2_SDA,
-
- /* HSI2C */
- MX51_PAD_I2C1_CLK__I2C1_CLK,
- MX51_PAD_I2C1_DAT__I2C1_DAT,
-
- /* USB HOST1 */
- MX51_PAD_USBH1_CLK__USBH1_CLK,
- MX51_PAD_USBH1_DIR__USBH1_DIR,
- MX51_PAD_USBH1_NXT__USBH1_NXT,
- MX51_PAD_USBH1_DATA0__USBH1_DATA0,
- MX51_PAD_USBH1_DATA1__USBH1_DATA1,
- MX51_PAD_USBH1_DATA2__USBH1_DATA2,
- MX51_PAD_USBH1_DATA3__USBH1_DATA3,
- MX51_PAD_USBH1_DATA4__USBH1_DATA4,
- MX51_PAD_USBH1_DATA5__USBH1_DATA5,
- MX51_PAD_USBH1_DATA6__USBH1_DATA6,
- MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
- /* USB HUB reset line*/
- MX51_PAD_GPIO1_7__GPIO1_7,
-
- /* USB PHY reset line */
- MX51_PAD_EIM_D21__GPIO2_5,
-
- /* FEC */
- MX51_PAD_EIM_EB2__FEC_MDIO,
- MX51_PAD_EIM_EB3__FEC_RDATA1,
- MX51_PAD_EIM_CS2__FEC_RDATA2,
- MX51_PAD_EIM_CS3__FEC_RDATA3,
- MX51_PAD_EIM_CS4__FEC_RX_ER,
- MX51_PAD_EIM_CS5__FEC_CRS,
- MX51_PAD_NANDF_RB2__FEC_COL,
- MX51_PAD_NANDF_RB3__FEC_RX_CLK,
- MX51_PAD_NANDF_D9__FEC_RDATA0,
- MX51_PAD_NANDF_D8__FEC_TDATA0,
- MX51_PAD_NANDF_CS2__FEC_TX_ER,
- MX51_PAD_NANDF_CS3__FEC_MDC,
- MX51_PAD_NANDF_CS4__FEC_TDATA1,
- MX51_PAD_NANDF_CS5__FEC_TDATA2,
- MX51_PAD_NANDF_CS6__FEC_TDATA3,
- MX51_PAD_NANDF_CS7__FEC_TX_EN,
- MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
-
- /* FEC PHY reset line */
- MX51_PAD_EIM_A20__GPIO2_14,
-
- /* SD 1 */
- MX51_PAD_SD1_CMD__SD1_CMD,
- MX51_PAD_SD1_CLK__SD1_CLK,
- MX51_PAD_SD1_DATA0__SD1_DATA0,
- MX51_PAD_SD1_DATA1__SD1_DATA1,
- MX51_PAD_SD1_DATA2__SD1_DATA2,
- MX51_PAD_SD1_DATA3__SD1_DATA3,
- /* CD/WP from controller */
- MX51_PAD_GPIO1_0__SD1_CD,
- MX51_PAD_GPIO1_1__SD1_WP,
-
- /* SD 2 */
- MX51_PAD_SD2_CMD__SD2_CMD,
- MX51_PAD_SD2_CLK__SD2_CLK,
- MX51_PAD_SD2_DATA0__SD2_DATA0,
- MX51_PAD_SD2_DATA1__SD2_DATA1,
- MX51_PAD_SD2_DATA2__SD2_DATA2,
- MX51_PAD_SD2_DATA3__SD2_DATA3,
- /* CD/WP gpio */
- MX51_PAD_GPIO1_6__GPIO1_6,
- MX51_PAD_GPIO1_5__GPIO1_5,
-
- /* eCSPI1 */
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
- MX51_PAD_CSPI1_SS0__GPIO4_24,
- MX51_PAD_CSPI1_SS1__GPIO4_25,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
- .bitrate = 400000,
-};
-
-static struct gpio mx51_babbage_usbh1_gpios[] = {
- { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
- { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
-};
-
-static int gpio_usbh1_active(void)
-{
- iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
- int ret;
-
- /* Set USBH1_STP to GPIO and toggle it */
- mxc_iomux_v3_setup_pad(usbh1stp_gpio);
- ret = gpio_request_array(mx51_babbage_usbh1_gpios,
- ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-
- if (ret) {
- pr_debug("failed to get USBH1 pins: %d\n", ret);
- return ret;
- }
-
- msleep(100);
- gpio_set_value(BABBAGE_USBH1_STP, 1);
- gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
- gpio_free_array(mx51_babbage_usbh1_gpios,
- ARRAY_SIZE(mx51_babbage_usbh1_gpios));
- return 0;
-}
-
-static inline void babbage_usbhub_reset(void)
-{
- int ret;
-
- /* Reset USB hub */
- ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
- GPIOF_OUT_INIT_LOW, "GPIO1_7");
- if (ret) {
- printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
- return;
- }
-
- msleep(2);
- /* Deassert reset */
- gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
-}
-
-static inline void babbage_fec_reset(void)
-{
- int ret;
-
- /* reset FEC PHY */
- ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
- GPIOF_OUT_INIT_LOW, "fec-phy-reset");
- if (ret) {
- printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
- return;
- }
- msleep(1);
- gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
-}
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* Set the PHY clock to 19.2MHz */
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
- v |= MX51_USB_PLL_DIV_19_2_MHZ;
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* The clock for the USBH1 ULPI port will come externally from the PHY. */
- v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
- __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
- MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
- .init = initialize_otg_port,
- .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
- .operating_mode = FSL_USB2_DR_DEVICE,
- .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
- .init = initialize_usbh1_port,
- .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init babbage_otg_mode(char *options)
-{
- if (!strcmp(options, "host"))
- otg_mode_host = 1;
- else if (!strcmp(options, "device"))
- otg_mode_host = 0;
- else
- pr_info("otg_mode neither \"host\" nor \"device\". "
- "Defaulting to device\n");
- return 0;
-}
-__setup("otg_mode=", babbage_otg_mode);
-
-static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
- {
- .modalias = "mtd_dataflash",
- .max_speed_hz = 25000000,
- .bus_num = 0,
- .chip_select = 1,
- .mode = SPI_MODE_0,
- .platform_data = NULL,
- },
-};
-
-static int mx51_babbage_spi_cs[] = {
- BABBAGE_ECSPI1_CS0,
- BABBAGE_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
- .chipselect = mx51_babbage_spi_cs,
- .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
- .cd_type = ESDHC_CD_CONTROLLER,
- .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
- .cd_gpio = BABBAGE_SD2_CD,
- .wp_gpio = BABBAGE_SD2_WP,
- .cd_type = ESDHC_CD_GPIO,
- .wp_type = ESDHC_WP_GPIO,
-};
-
-void __init imx51_babbage_common_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
- ARRAY_SIZE(mx51babbage_pads));
-}
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_babbage_init(void)
-{
- iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
- iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
- PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
-
- imx51_soc_init();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
- get_cpu_op = mx51_get_cpu_op;
-#endif
- imx51_babbage_common_init();
-
- imx51_add_imx_uart(0, &uart_pdata);
- imx51_add_imx_uart(1, NULL);
- imx51_add_imx_uart(2, &uart_pdata);
-
- babbage_fec_reset();
- imx51_add_fec(NULL);
-
- /* Set the PAD settings for the pwr key. */
- mxc_iomux_v3_setup_pad(power_key);
- imx_add_gpio_keys(&imx_button_data);
-
- imx51_add_imx_i2c(0, &babbage_i2c_data);
- imx51_add_imx_i2c(1, &babbage_i2c_data);
- imx51_add_hsi2c(&babbage_hsi2c_data);
-
- if (otg_mode_host)
- imx51_add_mxc_ehci_otg(&dr_utmi_config);
- else {
- initialize_otg_port(NULL);
- imx51_add_fsl_usb2_udc(&usb_pdata);
- }
-
- gpio_usbh1_active();
- imx51_add_mxc_ehci_hs(1, &usbh1_config);
- /* setback USBH1_STP to be function */
- mxc_iomux_v3_setup_pad(usbh1stp);
- babbage_usbhub_reset();
-
- imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
- imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
-
- spi_register_board_info(mx51_babbage_spi_board_info,
- ARRAY_SIZE(mx51_babbage_spi_board_info));
- imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
- imx51_add_imx2_wdt(0, NULL);
-}
-
-static void __init mx51_babbage_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_babbage_timer = {
- .init = mx51_babbage_timer_init,
-};
-
-MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
- /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &mx51_babbage_timer,
- .init_machine = mx51_babbage_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) 2010 Linaro Limited
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKAMX_PCBID0 IMX_GPIO_NR(3, 16)
-#define EFIKAMX_PCBID1 IMX_GPIO_NR(3, 17)
-#define EFIKAMX_PCBID2 IMX_GPIO_NR(3, 11)
-
-#define EFIKAMX_BLUE_LED IMX_GPIO_NR(3, 13)
-#define EFIKAMX_GREEN_LED IMX_GPIO_NR(3, 14)
-#define EFIKAMX_RED_LED IMX_GPIO_NR(3, 15)
-
-#define EFIKAMX_POWER_KEY IMX_GPIO_NR(2, 31)
-
-/* board 1.1 doesn't have same reset gpio */
-#define EFIKAMX_RESET1_1 IMX_GPIO_NR(3, 2)
-#define EFIKAMX_RESET IMX_GPIO_NR(1, 4)
-
-#define EFIKAMX_POWEROFF IMX_GPIO_NR(4, 13)
-
-#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6)
-
-/* the pci ids pin have pull up. they're driven low according to board id */
-#define MX51_PAD_PCBID0 IOMUX_PAD(0x518, 0x130, 3, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID1 IOMUX_PAD(0x51C, 0x134, 3, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID2 IOMUX_PAD(0x504, 0x128, 3, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-
-static iomux_v3_cfg_t mx51efikamx_pads[] = {
- /* board id */
- MX51_PAD_PCBID0,
- MX51_PAD_PCBID1,
- MX51_PAD_PCBID2,
-
- /* leds */
- MX51_PAD_CSI1_D9__GPIO3_13,
- MX51_PAD_CSI1_VSYNC__GPIO3_14,
- MX51_PAD_CSI1_HSYNC__GPIO3_15,
-
- /* power key */
- MX51_PAD_PWRKEY,
-
- /* reset */
- MX51_PAD_DI1_PIN13__GPIO3_2,
- MX51_PAD_GPIO1_4__GPIO1_4,
-
- /* power off */
- MX51_PAD_CSI2_VSYNC__GPIO4_13,
-};
-
-/* PCBID2 PCBID1 PCBID0 STATE
- 1 1 1 ER1:rev1.1
- 1 1 0 ER2:rev1.2
- 1 0 1 ER3:rev1.3
- 1 0 0 ER4:rev1.4
-*/
-static void __init mx51_efikamx_board_id(void)
-{
- int id;
-
- /* things are taking time to settle */
- msleep(150);
-
- gpio_request(EFIKAMX_PCBID0, "pcbid0");
- gpio_direction_input(EFIKAMX_PCBID0);
- gpio_request(EFIKAMX_PCBID1, "pcbid1");
- gpio_direction_input(EFIKAMX_PCBID1);
- gpio_request(EFIKAMX_PCBID2, "pcbid2");
- gpio_direction_input(EFIKAMX_PCBID2);
-
- id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
- id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
- id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
-
- switch (id) {
- case 7:
- system_rev = 0x11;
- break;
- case 6:
- system_rev = 0x12;
- break;
- case 5:
- system_rev = 0x13;
- break;
- case 4:
- system_rev = 0x14;
- break;
- default:
- system_rev = 0x10;
- break;
- }
-
- if ((system_rev == 0x10)
- || (system_rev == 0x12)
- || (system_rev == 0x14)) {
- printk(KERN_WARNING
- "EfikaMX: Unsupported board revision 1.%u!\n",
- system_rev & 0xf);
- }
-}
-
-static struct gpio_led mx51_efikamx_leds[] __initdata = {
- {
- .name = "efikamx:green",
- .default_trigger = "default-on",
- .gpio = EFIKAMX_GREEN_LED,
- },
- {
- .name = "efikamx:red",
- .default_trigger = "ide-disk",
- .gpio = EFIKAMX_RED_LED,
- },
- {
- .name = "efikamx:blue",
- .default_trigger = "mmc0",
- .gpio = EFIKAMX_BLUE_LED,
- },
-};
-
-static const struct gpio_led_platform_data
- mx51_efikamx_leds_data __initconst = {
- .leds = mx51_efikamx_leds,
- .num_leds = ARRAY_SIZE(mx51_efikamx_leds),
-};
-
-static struct esdhc_platform_data sd_pdata = {
- .cd_type = ESDHC_CD_CONTROLLER,
- .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct gpio_keys_button mx51_efikamx_powerkey[] = {
- {
- .code = KEY_POWER,
- .gpio = EFIKAMX_POWER_KEY,
- .type = EV_PWR,
- .desc = "Power Button (CM)",
- .wakeup = 1,
- .debounce_interval = 10, /* ms */
- },
-};
-
-static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
- .buttons = mx51_efikamx_powerkey,
- .nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
-};
-
-static void mx51_efikamx_restart(char mode, const char *cmd)
-{
- if (system_rev == 0x11)
- gpio_direction_output(EFIKAMX_RESET1_1, 0);
- else
- gpio_direction_output(EFIKAMX_RESET, 0);
-}
-
-static struct regulator *pwgt1, *pwgt2, *coincell;
-
-static void mx51_efikamx_power_off(void)
-{
- if (!IS_ERR(coincell))
- regulator_disable(coincell);
-
- if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
- regulator_disable(pwgt2);
- regulator_disable(pwgt1);
- }
- gpio_direction_output(EFIKAMX_POWEROFF, 1);
-}
-
-static int __init mx51_efikamx_power_init(void)
-{
- if (machine_is_mx51_efikamx()) {
- pwgt1 = regulator_get(NULL, "pwgt1");
- pwgt2 = regulator_get(NULL, "pwgt2");
- if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
- regulator_enable(pwgt1);
- regulator_enable(pwgt2);
- }
- gpio_request(EFIKAMX_POWEROFF, "poweroff");
- pm_power_off = mx51_efikamx_power_off;
-
- /* enable coincell charger. maybe need a small power driver ? */
- coincell = regulator_get(NULL, "coincell");
- if (!IS_ERR(coincell)) {
- regulator_set_voltage(coincell, 3000000, 3000000);
- regulator_enable(coincell);
- }
-
- regulator_has_full_constraints();
- }
-
- return 0;
-}
-late_initcall(mx51_efikamx_power_init);
-
-static void __init mx51_efikamx_init(void)
-{
- imx51_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
- ARRAY_SIZE(mx51efikamx_pads));
- efika_board_common_init();
-
- mx51_efikamx_board_id();
-
- /* on < 1.2 boards both SD controllers are used */
- if (system_rev < 0x12) {
- imx51_add_sdhci_esdhc_imx(0, NULL);
- imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
- mx51_efikamx_leds[2].default_trigger = "mmc1";
- } else
- imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
-
- gpio_led_register_device(-1, &mx51_efikamx_leds_data);
- imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
-
- if (system_rev == 0x11) {
- gpio_request(EFIKAMX_RESET1_1, "reset");
- gpio_direction_output(EFIKAMX_RESET1_1, 1);
- } else {
- gpio_request(EFIKAMX_RESET, "reset");
- gpio_direction_output(EFIKAMX_RESET, 1);
- }
-
- /*
- * enable wifi by default only on mx
- * sb and mx have same wlan pin but the value to enable it are
- * different :/
- */
- gpio_request(EFIKA_WLAN_EN, "wlan_en");
- gpio_direction_output(EFIKA_WLAN_EN, 0);
- msleep(10);
-
- gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
- gpio_direction_output(EFIKA_WLAN_RESET, 0);
- msleep(10);
- gpio_set_value(EFIKA_WLAN_RESET, 1);
-}
-
-static void __init mx51_efikamx_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikamx_timer = {
- .init = mx51_efikamx_timer_init,
-};
-
-MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
- /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &mx51_efikamx_timer,
- .init_machine = mx51_efikamx_init,
- .restart = mx51_efikamx_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKASB_USBH2_STP IMX_GPIO_NR(2, 20)
-#define EFIKASB_GREEN_LED IMX_GPIO_NR(1, 3)
-#define EFIKASB_WHITE_LED IMX_GPIO_NR(2, 25)
-#define EFIKASB_PCBID0 IMX_GPIO_NR(2, 28)
-#define EFIKASB_PCBID1 IMX_GPIO_NR(2, 29)
-#define EFIKASB_PWRKEY IMX_GPIO_NR(2, 31)
-#define EFIKASB_LID IMX_GPIO_NR(3, 14)
-#define EFIKASB_POWEROFF IMX_GPIO_NR(4, 13)
-#define EFIKASB_RFKILL IMX_GPIO_NR(3, 1)
-
-#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-#define MX51_PAD_SD1_CD IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-
-static iomux_v3_cfg_t mx51efikasb_pads[] = {
- /* USB HOST2 */
- MX51_PAD_EIM_D16__USBH2_DATA0,
- MX51_PAD_EIM_D17__USBH2_DATA1,
- MX51_PAD_EIM_D18__USBH2_DATA2,
- MX51_PAD_EIM_D19__USBH2_DATA3,
- MX51_PAD_EIM_D20__USBH2_DATA4,
- MX51_PAD_EIM_D21__USBH2_DATA5,
- MX51_PAD_EIM_D22__USBH2_DATA6,
- MX51_PAD_EIM_D23__USBH2_DATA7,
- MX51_PAD_EIM_A24__USBH2_CLK,
- MX51_PAD_EIM_A25__USBH2_DIR,
- MX51_PAD_EIM_A26__USBH2_STP,
- MX51_PAD_EIM_A27__USBH2_NXT,
-
- /* leds */
- MX51_PAD_EIM_CS0__GPIO2_25,
- MX51_PAD_GPIO1_3__GPIO1_3,
-
- /* pcb id */
- MX51_PAD_EIM_CS3__GPIO2_28,
- MX51_PAD_EIM_CS4__GPIO2_29,
-
- /* lid */
- MX51_PAD_CSI1_VSYNC__GPIO3_14,
-
- /* power key*/
- MX51_PAD_PWRKEY,
-
- /* wifi/bt button */
- MX51_PAD_DI1_PIN12__GPIO3_1,
-
- /* power off */
- MX51_PAD_CSI2_VSYNC__GPIO4_13,
-
- /* wdog reset */
- MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
-
- /* BT */
- MX51_PAD_EIM_A17__GPIO2_11,
-
- MX51_PAD_SD1_CD,
-};
-
-static int initialize_usbh2_port(struct platform_device *pdev)
-{
- iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
- iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
-
- mxc_iomux_v3_setup_pad(usbh2gpio);
- gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
- gpio_direction_output(EFIKASB_USBH2_STP, 0);
- msleep(1);
- gpio_set_value(EFIKASB_USBH2_STP, 1);
- msleep(1);
-
- gpio_free(EFIKASB_USBH2_STP);
- mxc_iomux_v3_setup_pad(usbh2stp);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh2_config __initdata = {
- .init = initialize_usbh2_port,
- .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void __init mx51_efikasb_usb(void)
-{
- usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
- ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
- if (usbh2_config.otg)
- imx51_add_mxc_ehci_hs(2, &usbh2_config);
-}
-
-static const struct gpio_led mx51_efikasb_leds[] __initconst = {
- {
- .name = "efikasb:green",
- .default_trigger = "default-on",
- .gpio = EFIKASB_GREEN_LED,
- .active_low = 1,
- },
- {
- .name = "efikasb:white",
- .default_trigger = "caps",
- .gpio = EFIKASB_WHITE_LED,
- },
-};
-
-static const struct gpio_led_platform_data
- mx51_efikasb_leds_data __initconst = {
- .leds = mx51_efikasb_leds,
- .num_leds = ARRAY_SIZE(mx51_efikasb_leds),
-};
-
-static struct gpio_keys_button mx51_efikasb_keys[] = {
- {
- .code = KEY_POWER,
- .gpio = EFIKASB_PWRKEY,
- .type = EV_KEY,
- .desc = "Power Button",
- .wakeup = 1,
- .active_low = 1,
- },
- {
- .code = SW_LID,
- .gpio = EFIKASB_LID,
- .type = EV_SW,
- .desc = "Lid Switch",
- .active_low = 1,
- },
- {
- .code = KEY_RFKILL,
- .gpio = EFIKASB_RFKILL,
- .type = EV_KEY,
- .desc = "rfkill",
- .active_low = 1,
- },
-};
-
-static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
- .buttons = mx51_efikasb_keys,
- .nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
-};
-
-static struct esdhc_platform_data sd0_pdata = {
-#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27)
- .cd_gpio = EFIKASB_SD1_CD,
- .cd_type = ESDHC_CD_GPIO,
- .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct esdhc_platform_data sd1_pdata = {
- .cd_type = ESDHC_CD_CONTROLLER,
- .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct regulator *pwgt1, *pwgt2;
-
-static void mx51_efikasb_power_off(void)
-{
- gpio_set_value(EFIKA_USB_PHY_RESET, 0);
-
- if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
- regulator_disable(pwgt2);
- regulator_disable(pwgt1);
- }
- gpio_direction_output(EFIKASB_POWEROFF, 1);
-}
-
-static int __init mx51_efikasb_power_init(void)
-{
- if (machine_is_mx51_efikasb()) {
- pwgt1 = regulator_get(NULL, "pwgt1");
- pwgt2 = regulator_get(NULL, "pwgt2");
- if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
- regulator_enable(pwgt1);
- regulator_enable(pwgt2);
- }
- gpio_request(EFIKASB_POWEROFF, "poweroff");
- pm_power_off = mx51_efikasb_power_off;
-
- regulator_has_full_constraints();
- }
-
- return 0;
-}
-late_initcall(mx51_efikasb_power_init);
-
-/* 01 R1.3 board
- 10 R2.0 board */
-static void __init mx51_efikasb_board_id(void)
-{
- int id;
-
- gpio_request(EFIKASB_PCBID0, "pcb id0");
- gpio_direction_input(EFIKASB_PCBID0);
- gpio_request(EFIKASB_PCBID1, "pcb id1");
- gpio_direction_input(EFIKASB_PCBID1);
-
- id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
- id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
-
- switch (id) {
- default:
- break;
- case 1:
- system_rev = 0x13;
- break;
- case 2:
- system_rev = 0x20;
- break;
- }
-}
-
-static void __init efikasb_board_init(void)
-{
- imx51_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
- ARRAY_SIZE(mx51efikasb_pads));
- efika_board_common_init();
-
- mx51_efikasb_board_id();
- mx51_efikasb_usb();
- imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
- imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
-
- gpio_led_register_device(-1, &mx51_efikasb_leds_data);
- imx_add_gpio_keys(&mx51_efikasb_keys_data);
-}
-
-static void __init mx51_efikasb_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikasb_timer = {
- .init = mx51_efikasb_timer_init,
-};
-
-MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .init_machine = efikasb_board_init,
- .timer = &mx51_efikasb_timer,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31)
-#define ARD_SD1_CD IMX_GPIO_NR(1, 1)
-#define ARD_SD1_WP IMX_GPIO_NR(1, 9)
-#define ARD_I2CPORTEXP_B IMX_GPIO_NR(2, 3)
-#define ARD_VOLUMEDOWN IMX_GPIO_NR(4, 0)
-#define ARD_HOME IMX_GPIO_NR(5, 10)
-#define ARD_BACK IMX_GPIO_NR(5, 11)
-#define ARD_PROG IMX_GPIO_NR(5, 12)
-#define ARD_VOLUMEUP IMX_GPIO_NR(5, 13)
-
-static iomux_v3_cfg_t mx53_ard_pads[] = {
- /* UART1 */
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
- /* WEIM for CS1 */
- MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
- MX53_PAD_EIM_D16__EMI_WEIM_D_16,
- MX53_PAD_EIM_D17__EMI_WEIM_D_17,
- MX53_PAD_EIM_D18__EMI_WEIM_D_18,
- MX53_PAD_EIM_D19__EMI_WEIM_D_19,
- MX53_PAD_EIM_D20__EMI_WEIM_D_20,
- MX53_PAD_EIM_D21__EMI_WEIM_D_21,
- MX53_PAD_EIM_D22__EMI_WEIM_D_22,
- MX53_PAD_EIM_D23__EMI_WEIM_D_23,
- MX53_PAD_EIM_D24__EMI_WEIM_D_24,
- MX53_PAD_EIM_D25__EMI_WEIM_D_25,
- MX53_PAD_EIM_D26__EMI_WEIM_D_26,
- MX53_PAD_EIM_D27__EMI_WEIM_D_27,
- MX53_PAD_EIM_D28__EMI_WEIM_D_28,
- MX53_PAD_EIM_D29__EMI_WEIM_D_29,
- MX53_PAD_EIM_D30__EMI_WEIM_D_30,
- MX53_PAD_EIM_D31__EMI_WEIM_D_31,
- MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
- MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
- MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
- MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
- MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
- MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
- MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
- MX53_PAD_EIM_OE__EMI_WEIM_OE,
- MX53_PAD_EIM_RW__EMI_WEIM_RW,
- MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
- /* SDHC1 */
- MX53_PAD_SD1_CMD__ESDHC1_CMD,
- MX53_PAD_SD1_CLK__ESDHC1_CLK,
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
- MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
- MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
- MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
- MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
- MX53_PAD_GPIO_1__GPIO1_1,
- MX53_PAD_GPIO_9__GPIO1_9,
- /* I2C2 */
- MX53_PAD_EIM_EB2__I2C2_SCL,
- MX53_PAD_KEY_ROW3__I2C2_SDA,
- /* I2C3 */
- MX53_PAD_GPIO_3__I2C3_SCL,
- MX53_PAD_GPIO_16__I2C3_SDA,
- /* GPIO */
- MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
- MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
- MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
- MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
- MX53_PAD_GPIO_10__GPIO4_0, /* vol down */
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
-{ \
- .gpio = gpio_num, \
- .type = EV_KEY, \
- .code = ev_code, \
- .active_low = act_low, \
- .desc = "btn " descr, \
- .wakeup = wake, \
-}
-
-static struct gpio_keys_button ard_buttons[] = {
- GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
- GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
- GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
- GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
- GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data ard_button_data __initconst = {
- .buttons = ard_buttons,
- .nbuttons = ARRAY_SIZE(ard_buttons),
-};
-
-static struct resource ard_smsc911x_resources[] = {
- {
- .start = MX53_CS1_64MB_BASE_ADDR,
- .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
- .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct smsc911x_platform_config ard_smsc911x_config = {
- .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
- .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
- .flags = SMSC911X_USE_32BIT,
-};
-
-static struct platform_device ard_smsc_lan9220_device = {
- .name = "smsc911x",
- .id = -1,
- .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
- .resource = ard_smsc911x_resources,
- .dev = {
- .platform_data = &ard_smsc911x_config,
- },
-};
-
-static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
- .cd_gpio = ARD_SD1_CD,
- .wp_gpio = ARD_SD1_WP,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c2_data = {
- .bitrate = 50000,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c3_data = {
- .bitrate = 400000,
-};
-
-static void __init mx53_ard_io_init(void)
-{
- gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
- gpio_direction_input(ARD_ETHERNET_INT_B);
-
- gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
- gpio_direction_output(ARD_I2CPORTEXP_B, 1);
-}
-
-/* Config CS1 settings for ethernet controller */
-static int weim_cs_config(void)
-{
- u32 reg;
- void __iomem *weim_base, *iomuxc_base;
-
- weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
- if (!weim_base)
- return -ENOMEM;
-
- iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
- if (!iomuxc_base)
- return -ENOMEM;
-
- /* CS1 timings for LAN9220 */
- writel(0x20001, (weim_base + 0x18));
- writel(0x0, (weim_base + 0x1C));
- writel(0x16000202, (weim_base + 0x20));
- writel(0x00000002, (weim_base + 0x24));
- writel(0x16002082, (weim_base + 0x28));
- writel(0x00000000, (weim_base + 0x2C));
- writel(0x00000000, (weim_base + 0x90));
-
- /* specify 64 MB on CS1 and CS0 on GPR1 */
- reg = readl(iomuxc_base + 0x4);
- reg &= ~0x3F;
- reg |= 0x1B;
- writel(reg, (iomuxc_base + 0x4));
-
- iounmap(iomuxc_base);
- iounmap(weim_base);
-
- return 0;
-}
-
-void __init imx53_ard_common_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
- ARRAY_SIZE(mx53_ard_pads));
- weim_cs_config();
-}
-
-static struct platform_device *devices[] __initdata = {
- &ard_smsc_lan9220_device,
-};
-
-static void __init mx53_ard_board_init(void)
-{
- imx53_soc_init();
- imx53_add_imx_uart(0, NULL);
-
- imx53_ard_common_init();
- mx53_ard_io_init();
- platform_add_devices(devices, ARRAY_SIZE(devices));
-
- imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
- imx53_add_imx2_wdt(0, NULL);
- imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
- imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
- imx_add_gpio_keys(&ard_button_data);
- imx53_add_ahci_imx();
-}
-
-static void __init mx53_ard_timer_init(void)
-{
- mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_ard_timer = {
- .init = mx53_ard_timer_init,
-};
-
-MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
- .map_io = mx53_map_io,
- .init_early = imx53_init_early,
- .init_irq = mx53_init_irq,
- .handle_irq = imx53_handle_irq,
- .timer = &mx53_ard_timer,
- .init_machine = mx53_ard_board_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/iomux-mx53.h>
-
-#define MX53_EVK_FEC_PHY_RST IMX_GPIO_NR(7, 6)
-#define EVK_ECSPI1_CS0 IMX_GPIO_NR(2, 30)
-#define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19)
-#define MX53EVK_LED IMX_GPIO_NR(7, 7)
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-static iomux_v3_cfg_t mx53_evk_pads[] = {
- MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
- MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
- MX53_PAD_PATA_DIOR__UART2_RTS,
- MX53_PAD_PATA_INTRQ__UART2_CTS,
-
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-
- MX53_PAD_EIM_D16__ECSPI1_SCLK,
- MX53_PAD_EIM_D17__ECSPI1_MISO,
- MX53_PAD_EIM_D18__ECSPI1_MOSI,
-
- /* ecspi chip select lines */
- MX53_PAD_EIM_EB2__GPIO2_30,
- MX53_PAD_EIM_D19__GPIO3_19,
- /* LED */
- MX53_PAD_PATA_DA_1__GPIO7_7,
-};
-
-static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct gpio_led mx53evk_leds[] __initconst = {
- {
- .name = "green",
- .default_trigger = "heartbeat",
- .gpio = MX53EVK_LED,
- },
-};
-
-static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
- .leds = mx53evk_leds,
- .num_leds = ARRAY_SIZE(mx53evk_leds),
-};
-
-static inline void mx53_evk_init_uart(void)
-{
- imx53_add_imx_uart(0, NULL);
- imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
- imx53_add_imx_uart(2, NULL);
-}
-
-static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-static inline void mx53_evk_fec_reset(void)
-{
- int ret;
-
- /* reset FEC PHY */
- ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
- "fec-phy-reset");
- if (ret) {
- printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
- return;
- }
- msleep(1);
- gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
- .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
- {
- .modalias = "mtd_dataflash",
- .max_speed_hz = 25000000,
- .bus_num = 0,
- .chip_select = 1,
- .mode = SPI_MODE_0,
- .platform_data = NULL,
- },
-};
-
-static int mx53_evk_spi_cs[] = {
- EVK_ECSPI1_CS0,
- EVK_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx53_evk_spi_data __initconst = {
- .chipselect = mx53_evk_spi_cs,
- .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
-};
-
-void __init imx53_evk_common_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
- ARRAY_SIZE(mx53_evk_pads));
-}
-
-static void __init mx53_evk_board_init(void)
-{
- imx53_soc_init();
- imx53_evk_common_init();
-
- mx53_evk_init_uart();
- mx53_evk_fec_reset();
- imx53_add_fec(&mx53_evk_fec_pdata);
-
- imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
- imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
-
- imx53_add_sdhci_esdhc_imx(0, NULL);
- imx53_add_sdhci_esdhc_imx(1, NULL);
-
- spi_register_board_info(mx53_evk_spi_board_info,
- ARRAY_SIZE(mx53_evk_spi_board_info));
- imx53_add_ecspi(0, &mx53_evk_spi_data);
- imx53_add_imx2_wdt(0, NULL);
- gpio_led_register_device(-1, &mx53evk_leds_data);
-}
-
-static void __init mx53_evk_timer_init(void)
-{
- mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_evk_timer = {
- .init = mx53_evk_timer_init,
-};
-
-MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
- .map_io = mx53_map_io,
- .init_early = imx53_init_early,
- .init_irq = mx53_init_irq,
- .handle_irq = imx53_handle_irq,
- .timer = &mx53_evk_timer,
- .init_machine = mx53_evk_board_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define MX53_LOCO_POWER IMX_GPIO_NR(1, 8)
-#define MX53_LOCO_UI1 IMX_GPIO_NR(2, 14)
-#define MX53_LOCO_UI2 IMX_GPIO_NR(2, 15)
-#define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6)
-#define LOCO_LED IMX_GPIO_NR(7, 7)
-#define LOCO_SD3_CD IMX_GPIO_NR(3, 11)
-#define LOCO_SD3_WP IMX_GPIO_NR(3, 12)
-#define LOCO_SD1_CD IMX_GPIO_NR(3, 13)
-#define LOCO_ACCEL_EN IMX_GPIO_NR(6, 14)
-
-static iomux_v3_cfg_t mx53_loco_pads[] = {
- /* FEC */
- MX53_PAD_FEC_MDC__FEC_MDC,
- MX53_PAD_FEC_MDIO__FEC_MDIO,
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
- MX53_PAD_FEC_RX_ER__FEC_RX_ER,
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
- MX53_PAD_FEC_RXD1__FEC_RDATA_1,
- MX53_PAD_FEC_RXD0__FEC_RDATA_0,
- MX53_PAD_FEC_TX_EN__FEC_TX_EN,
- MX53_PAD_FEC_TXD1__FEC_TDATA_1,
- MX53_PAD_FEC_TXD0__FEC_TDATA_0,
- /* FEC_nRST */
- MX53_PAD_PATA_DA_0__GPIO7_6,
- /* FEC_nINT */
- MX53_PAD_PATA_DATA4__GPIO2_4,
- /* AUDMUX5 */
- MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
- MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
- MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
- MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
- /* I2C1 */
- MX53_PAD_CSI0_DAT8__I2C1_SDA,
- MX53_PAD_CSI0_DAT9__I2C1_SCL,
- MX53_PAD_NANDF_CS1__GPIO6_14, /* Accelerometer Enable */
- /* I2C2 */
- MX53_PAD_KEY_COL3__I2C2_SCL,
- MX53_PAD_KEY_ROW3__I2C2_SDA,
- /* SD1 */
- MX53_PAD_SD1_CMD__ESDHC1_CMD,
- MX53_PAD_SD1_CLK__ESDHC1_CLK,
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
- /* SD1_CD */
- MX53_PAD_EIM_DA13__GPIO3_13,
- /* SD3 */
- MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
- MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
- MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
- MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
- MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
- MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
- MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
- MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
- MX53_PAD_PATA_IORDY__ESDHC3_CLK,
- MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
- /* SD3_CD */
- MX53_PAD_EIM_DA11__GPIO3_11,
- /* SD3_WP */
- MX53_PAD_EIM_DA12__GPIO3_12,
- /* VGA */
- MX53_PAD_EIM_OE__IPU_DI1_PIN7,
- MX53_PAD_EIM_RW__IPU_DI1_PIN8,
- /* DISPLB */
- MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
- MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
- MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
- MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
- /* DISP0_POWER_EN */
- MX53_PAD_EIM_D24__GPIO3_24,
- /* DISP0 DET INT */
- MX53_PAD_EIM_D31__GPIO3_31,
- /* LVDS */
- MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
- MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
- MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
- MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
- MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
- MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
- MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
- MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
- MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
- MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
- /* I2C1 */
- MX53_PAD_CSI0_DAT8__I2C1_SDA,
- MX53_PAD_CSI0_DAT9__I2C1_SCL,
- /* UART1 */
- MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
- MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
- /* CSI0 */
- MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
- MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
- MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
- MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
- MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
- MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
- MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
- MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
- MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
- MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
- MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
- /* DISPLAY */
- MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
- MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
- MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
- MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
- MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
- MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
- MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
- MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
- MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
- MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
- MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
- MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
- MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
- MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
- MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
- MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
- MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
- MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
- MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
- MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
- MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
- MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
- MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
- MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
- MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
- MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
- MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
- MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
- /* Audio CLK*/
- MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
- /* PWM */
- MX53_PAD_GPIO_1__PWM2_PWMO,
- /* SPDIF */
- MX53_PAD_GPIO_7__SPDIF_PLOCK,
- MX53_PAD_GPIO_17__SPDIF_OUT1,
- /* GPIO */
- MX53_PAD_PATA_DA_1__GPIO7_7, /* LED */
- MX53_PAD_PATA_DA_2__GPIO7_8,
- MX53_PAD_PATA_DATA5__GPIO2_5,
- MX53_PAD_PATA_DATA6__GPIO2_6,
- MX53_PAD_PATA_DATA14__GPIO2_14,
- MX53_PAD_PATA_DATA15__GPIO2_15,
- MX53_PAD_PATA_INTRQ__GPIO7_2,
- MX53_PAD_EIM_WAIT__GPIO5_0,
- MX53_PAD_NANDF_WP_B__GPIO6_9,
- MX53_PAD_NANDF_RB0__GPIO6_10,
- MX53_PAD_NANDF_CS1__GPIO6_14,
- MX53_PAD_NANDF_CS2__GPIO6_15,
- MX53_PAD_NANDF_CS3__GPIO6_16,
- MX53_PAD_GPIO_5__GPIO1_5,
- MX53_PAD_GPIO_16__GPIO7_11,
- MX53_PAD_GPIO_8__GPIO1_8,
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
-{ \
- .gpio = gpio_num, \
- .type = EV_KEY, \
- .code = ev_code, \
- .active_low = act_low, \
- .desc = "btn " descr, \
- .wakeup = wake, \
-}
-
-static struct gpio_keys_button loco_buttons[] = {
- GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
- GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
- GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data loco_button_data __initconst = {
- .buttons = loco_buttons,
- .nbuttons = ARRAY_SIZE(loco_buttons),
-};
-
-static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
- .cd_gpio = LOCO_SD1_CD,
- .cd_type = ESDHC_CD_GPIO,
- .wp_type = ESDHC_WP_NONE,
-};
-
-static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
- .cd_gpio = LOCO_SD3_CD,
- .wp_gpio = LOCO_SD3_WP,
- .cd_type = ESDHC_CD_GPIO,
- .wp_type = ESDHC_WP_GPIO,
-};
-
-static inline void mx53_loco_fec_reset(void)
-{
- int ret;
-
- /* reset FEC PHY */
- ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
- if (ret) {
- printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
- return;
- }
- gpio_direction_output(LOCO_FEC_PHY_RST, 0);
- msleep(1);
- gpio_set_value(LOCO_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_loco_fec_data __initconst = {
- .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-static const struct gpio_led mx53loco_leds[] __initconst = {
- {
- .name = "green",
- .default_trigger = "heartbeat",
- .gpio = LOCO_LED,
- },
-};
-
-static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
- .leds = mx53loco_leds,
- .num_leds = ARRAY_SIZE(mx53loco_leds),
-};
-
-void __init imx53_qsb_common_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
- ARRAY_SIZE(mx53_loco_pads));
-}
-
-static struct i2c_board_info mx53loco_i2c_devices[] = {
- {
- I2C_BOARD_INFO("mma8450", 0x1C),
- },
-};
-
-static void __init mx53_loco_board_init(void)
-{
- int ret;
- imx53_soc_init();
- imx53_qsb_common_init();
-
- imx53_add_imx_uart(0, NULL);
- mx53_loco_fec_reset();
- imx53_add_fec(&mx53_loco_fec_data);
- imx53_add_imx2_wdt(0, NULL);
-
- ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
- if (ret)
- pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
-
- i2c_register_board_info(0, mx53loco_i2c_devices,
- ARRAY_SIZE(mx53loco_i2c_devices));
- imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
- imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
- imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
- imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
- imx_add_gpio_keys(&loco_button_data);
- gpio_led_register_device(-1, &mx53loco_leds_data);
- imx53_add_ahci_imx();
-}
-
-static void __init mx53_loco_timer_init(void)
-{
- mx53_clocks_init(32768, 24000000, 0, 0);
-}
-
-static struct sys_timer mx53_loco_timer = {
- .init = mx53_loco_timer_init,
-};
-
-MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
- .map_io = mx53_map_io,
- .init_early = imx53_init_early,
- .init_irq = mx53_init_irq,
- .handle_irq = imx53_handle_irq,
- .timer = &mx53_loco_timer,
- .init_machine = mx53_loco_board_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6)
-#define MX53_SMD_SATA_PWR_EN IMX_GPIO_NR(3, 3)
-
-static iomux_v3_cfg_t mx53_smd_pads[] = {
- MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
- MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
- MX53_PAD_PATA_DA_1__UART3_CTS,
- MX53_PAD_PATA_DA_2__UART3_RTS,
- /* I2C1 */
- MX53_PAD_CSI0_DAT8__I2C1_SDA,
- MX53_PAD_CSI0_DAT9__I2C1_SCL,
- /* SD1 */
- MX53_PAD_SD1_CMD__ESDHC1_CMD,
- MX53_PAD_SD1_CLK__ESDHC1_CLK,
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
- /* SD2 */
- MX53_PAD_SD2_CMD__ESDHC2_CMD,
- MX53_PAD_SD2_CLK__ESDHC2_CLK,
- MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
- MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
- MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
- MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
- /* SD3 */
- MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
- MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
- MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
- MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
- MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
- MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
- MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
- MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
- MX53_PAD_PATA_IORDY__ESDHC3_CLK,
- MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-};
-
-static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mx53_smd_init_uart(void)
-{
- imx53_add_imx_uart(0, NULL);
- imx53_add_imx_uart(1, NULL);
- imx53_add_imx_uart(2, &mx53_smd_uart_data);
-}
-
-static inline void mx53_smd_fec_reset(void)
-{
- int ret;
-
- /* reset FEC PHY */
- ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
- if (ret) {
- printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
- return;
- }
- gpio_direction_output(SMD_FEC_PHY_RST, 0);
- msleep(1);
- gpio_set_value(SMD_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_smd_fec_data __initconst = {
- .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-static inline void mx53_smd_ahci_pwr_on(void)
-{
- int ret;
-
- /* Enable SATA PWR */
- ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
- GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
- if (ret) {
- pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
- return;
- }
-}
-
-void __init imx53_smd_common_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
- ARRAY_SIZE(mx53_smd_pads));
-}
-
-static void __init mx53_smd_board_init(void)
-{
- imx53_soc_init();
- imx53_smd_common_init();
-
- mx53_smd_init_uart();
- mx53_smd_fec_reset();
- imx53_add_fec(&mx53_smd_fec_data);
- imx53_add_imx2_wdt(0, NULL);
- imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
- imx53_add_sdhci_esdhc_imx(0, NULL);
- imx53_add_sdhci_esdhc_imx(1, NULL);
- imx53_add_sdhci_esdhc_imx(2, NULL);
- mx53_smd_ahci_pwr_on();
- imx53_add_ahci_imx();
-}
-
-static void __init mx53_smd_timer_init(void)
-{
- mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_smd_timer = {
- .init = mx53_smd_timer_init,
-};
-
-MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
- .map_io = mx53_map_io,
- .init_early = imx53_init_early,
- .init_irq = mx53_init_irq,
- .handle_irq = imx53_handle_irq,
- .timer = &mx53_smd_timer,
- .init_machine = mx53_smd_board_init,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/of.h>
-
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/clock.h>
-
-#include "crm_regs.h"
-
-/* External clock values passed-in by the board code */
-static unsigned long external_high_reference, external_low_reference;
-static unsigned long oscillator_reference, ckih2_reference;
-
-static struct clk osc_clk;
-static struct clk pll1_main_clk;
-static struct clk pll1_sw_clk;
-static struct clk pll2_sw_clk;
-static struct clk pll3_sw_clk;
-static struct clk mx53_pll4_sw_clk;
-static struct clk lp_apm_clk;
-static struct clk periph_apm_clk;
-static struct clk ahb_clk;
-static struct clk ipg_clk;
-static struct clk usboh3_clk;
-static struct clk emi_fast_clk;
-static struct clk ipu_clk;
-static struct clk mipi_hsc1_clk;
-static struct clk esdhc1_clk;
-static struct clk esdhc2_clk;
-static struct clk esdhc3_mx53_clk;
-
-#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
-
-/* calculate best pre and post dividers to get the required divider */
-static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
- u32 max_pre, u32 max_post)
-{
- if (div >= max_pre * max_post) {
- *pre = max_pre;
- *post = max_post;
- } else if (div >= max_pre) {
- u32 min_pre, temp_pre, old_err, err;
- min_pre = DIV_ROUND_UP(div, max_post);
- old_err = max_pre;
- for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
- err = div % temp_pre;
- if (err == 0) {
- *pre = temp_pre;
- break;
- }
- err = temp_pre - err;
- if (err < old_err) {
- old_err = err;
- *pre = temp_pre;
- }
- }
- *post = DIV_ROUND_UP(div, *pre);
- } else {
- *pre = div;
- *post = 1;
- }
-}
-
-static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
-{
- u32 reg = __raw_readl(clk->enable_reg);
-
- reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
- reg |= mode << clk->enable_shift;
-
- __raw_writel(reg, clk->enable_reg);
-}
-
-static int _clk_ccgr_enable(struct clk *clk)
-{
- _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
- return 0;
-}
-
-static void _clk_ccgr_disable(struct clk *clk)
-{
- _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
-}
-
-static int _clk_ccgr_enable_inrun(struct clk *clk)
-{
- _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
- return 0;
-}
-
-static void _clk_ccgr_disable_inwait(struct clk *clk)
-{
- _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-}
-
-/*
- * For the 4-to-1 muxed input clock
- */
-static inline u32 _get_mux(struct clk *parent, struct clk *m0,
- struct clk *m1, struct clk *m2, struct clk *m3)
-{
- if (parent == m0)
- return 0;
- else if (parent == m1)
- return 1;
- else if (parent == m2)
- return 2;
- else if (parent == m3)
- return 3;
- else
- BUG();
-
- return -EINVAL;
-}
-
-static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
-{
- if (pll == &pll1_main_clk)
- return MX51_DPLL1_BASE;
- else if (pll == &pll2_sw_clk)
- return MX51_DPLL2_BASE;
- else if (pll == &pll3_sw_clk)
- return MX51_DPLL3_BASE;
- else
- BUG();
-
- return NULL;
-}
-
-static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
-{
- if (pll == &pll1_main_clk)
- return MX53_DPLL1_BASE;
- else if (pll == &pll2_sw_clk)
- return MX53_DPLL2_BASE;
- else if (pll == &pll3_sw_clk)
- return MX53_DPLL3_BASE;
- else if (pll == &mx53_pll4_sw_clk)
- return MX53_DPLL4_BASE;
- else
- BUG();
-
- return NULL;
-}
-
-static inline void __iomem *_get_pll_base(struct clk *pll)
-{
- if (cpu_is_mx51())
- return _mx51_get_pll_base(pll);
- else
- return _mx53_get_pll_base(pll);
-}
-
-static unsigned long clk_pll_get_rate(struct clk *clk)
-{
- long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
- unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
- void __iomem *pllbase;
- s64 temp;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- pllbase = _get_pll_base(clk);
-
- dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
- dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
-
- if (pll_hfsm == 0) {
- dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
- dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
- dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
- } else {
- dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
- dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
- dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
- }
- pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
- mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
- mfi = (mfi <= 5) ? 5 : mfi;
- mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
- mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
- /* Sign extend to 32-bits */
- if (mfn >= 0x04000000) {
- mfn |= 0xFC000000;
- mfn_abs = -mfn;
- }
-
- ref_clk = 2 * parent_rate;
- if (dbl != 0)
- ref_clk *= 2;
-
- ref_clk /= (pdf + 1);
- temp = (u64) ref_clk * mfn_abs;
- do_div(temp, mfd + 1);
- if (mfn < 0)
- temp = -temp;
- temp = (ref_clk * mfi) + temp;
-
- return temp;
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg;
- void __iomem *pllbase;
-
- long mfi, pdf, mfn, mfd = 999999;
- s64 temp64;
- unsigned long quad_parent_rate;
- unsigned long pll_hfsm, dp_ctl;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- pllbase = _get_pll_base(clk);
-
- quad_parent_rate = 4 * parent_rate;
- pdf = mfi = -1;
- while (++pdf < 16 && mfi < 5)
- mfi = rate * (pdf+1) / quad_parent_rate;
- if (mfi > 15)
- return -EINVAL;
- pdf--;
-
- temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
- do_div(temp64, quad_parent_rate/1000000);
- mfn = (long)temp64;
-
- dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- /* use dpdck0_2 */
- __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
- pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
- if (pll_hfsm == 0) {
- reg = mfi << 4 | pdf;
- __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
- __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
- __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
- } else {
- reg = mfi << 4 | pdf;
- __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
- __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
- __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
- }
-
- return 0;
-}
-
-static int _clk_pll_enable(struct clk *clk)
-{
- u32 reg;
- void __iomem *pllbase;
- int i = 0;
-
- pllbase = _get_pll_base(clk);
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- if (reg & MXC_PLL_DP_CTL_UPEN)
- return 0;
-
- reg |= MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-
- /* Wait for lock */
- do {
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- if (reg & MXC_PLL_DP_CTL_LRF)
- break;
-
- udelay(1);
- } while (++i < MAX_DPLL_WAIT_TRIES);
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- pr_err("MX5: pll locking failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void _clk_pll_disable(struct clk *clk)
-{
- u32 reg;
- void __iomem *pllbase;
-
- pllbase = _get_pll_base(clk);
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-}
-
-static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg, step;
-
- reg = __raw_readl(MXC_CCM_CCSR);
-
- /* When switching from pll_main_clk to a bypass clock, first select a
- * multiplexed clock in 'step_sel', then shift the glitchless mux
- * 'pll1_sw_clk_sel'.
- *
- * When switching back, do it in reverse order
- */
- if (parent == &pll1_main_clk) {
- /* Switch to pll1_main_clk */
- reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- __raw_writel(reg, MXC_CCM_CCSR);
- /* step_clk mux switched to lp_apm, to save power. */
- reg = __raw_readl(MXC_CCM_CCSR);
- reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
- reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
- MXC_CCM_CCSR_STEP_SEL_OFFSET);
- } else {
- if (parent == &lp_apm_clk) {
- step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
- } else if (parent == &pll2_sw_clk) {
- step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
- } else if (parent == &pll3_sw_clk) {
- step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
- } else
- return -EINVAL;
-
- reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
- reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
-
- __raw_writel(reg, MXC_CCM_CCSR);
- /* Switch to step_clk */
- reg = __raw_readl(MXC_CCM_CCSR);
- reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- }
- __raw_writel(reg, MXC_CCM_CCSR);
- return 0;
-}
-
-static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
-{
- u32 reg, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CCSR);
-
- if (clk->parent == &pll2_sw_clk) {
- div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
- MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
- } else if (clk->parent == &pll3_sw_clk) {
- div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
- MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
- } else
- div = 1;
- return parent_rate / div;
-}
-
-static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CCSR);
-
- if (parent == &pll2_sw_clk)
- reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
- else
- reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-
- __raw_writel(reg, MXC_CCM_CCSR);
- return 0;
-}
-
-static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- if (parent == &osc_clk)
- reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
- else
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_CCSR);
-
- return 0;
-}
-
-static unsigned long clk_cpu_get_rate(struct clk *clk)
-{
- u32 cacrr, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
- cacrr = __raw_readl(MXC_CCM_CACRR);
- div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
-
- return parent_rate / div;
-}
-
-static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg, cpu_podf;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
- cpu_podf = parent_rate / rate - 1;
- /* use post divider to change freq */
- reg = __raw_readl(MXC_CCM_CACRR);
- reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
- reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
- __raw_writel(reg, MXC_CCM_CACRR);
-
- return 0;
-}
-
-static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg, mux;
- int i = 0;
-
- mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
-
- reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
- reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
- __raw_writel(reg, MXC_CCM_CBCMR);
-
- /* Wait for lock */
- do {
- reg = __raw_readl(MXC_CCM_CDHIPR);
- if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
- break;
-
- udelay(1);
- } while (++i < MAX_DPLL_WAIT_TRIES);
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- pr_err("MX5: Set parent for periph_apm clock failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
-
- if (parent == &pll2_sw_clk)
- reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
- else if (parent == &periph_apm_clk)
- reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
- else
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- return 0;
-}
-
-static struct clk main_bus_clk = {
- .parent = &pll2_sw_clk,
- .set_parent = _clk_main_bus_set_parent,
-};
-
-static unsigned long clk_ahb_get_rate(struct clk *clk)
-{
- u32 reg, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
- MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
- return parent_rate / div;
-}
-
-
-static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg, div;
- unsigned long parent_rate;
- int i = 0;
-
- parent_rate = clk_get_rate(clk->parent);
-
- div = parent_rate / rate;
- if (div > 8 || div < 1 || ((parent_rate / div) != rate))
- return -EINVAL;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
- reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- /* Wait for lock */
- do {
- reg = __raw_readl(MXC_CCM_CDHIPR);
- if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
- break;
-
- udelay(1);
- } while (++i < MAX_DPLL_WAIT_TRIES);
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- pr_err("MX5: clk_ahb_set_rate failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned long _clk_ahb_round_rate(struct clk *clk,
- unsigned long rate)
-{
- u32 div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- div = parent_rate / rate;
- if (div > 8)
- div = 8;
- else if (div == 0)
- div++;
- return parent_rate / div;
-}
-
-
-static int _clk_max_enable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_enable(clk);
-
- /* Handshake with MAX when LPM is entered. */
- reg = __raw_readl(MXC_CCM_CLPCR);
- if (cpu_is_mx51())
- reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
- else if (cpu_is_mx53())
- reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-
- return 0;
-}
-
-static void _clk_max_disable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_disable_inwait(clk);
-
- /* No Handshake with MAX when LPM is entered as its disabled. */
- reg = __raw_readl(MXC_CCM_CLPCR);
- if (cpu_is_mx51())
- reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
- else if (cpu_is_mx53())
- reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static unsigned long clk_ipg_get_rate(struct clk *clk)
-{
- u32 reg, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
- MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
-
- return parent_rate / div;
-}
-
-static unsigned long clk_ipg_per_get_rate(struct clk *clk)
-{
- u32 reg, prediv1, prediv2, podf;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
- /* the main_bus_clk is the one before the DVFS engine */
- reg = __raw_readl(MXC_CCM_CBCDR);
- prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
- MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
- prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
- MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
- podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
- MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
- return parent_rate / (prediv1 * prediv2 * podf);
- } else if (clk->parent == &ipg_clk)
- return parent_rate;
- else
- BUG();
-}
-
-static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CBCMR);
-
- reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
- reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-
- if (parent == &ipg_clk)
- reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
- else if (parent == &lp_apm_clk)
- reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
- else if (parent != &main_bus_clk)
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_CBCMR);
-
- return 0;
-}
-
-#define clk_nfc_set_parent NULL
-
-static unsigned long clk_nfc_get_rate(struct clk *clk)
-{
- unsigned long rate;
- u32 reg, div;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
- MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
- rate = clk_get_rate(clk->parent) / div;
- WARN_ON(rate == 0);
- return rate;
-}
-
-static unsigned long clk_nfc_round_rate(struct clk *clk,
- unsigned long rate)
-{
- u32 div;
- unsigned long parent_rate = clk_get_rate(clk->parent);
-
- if (!rate)
- return -EINVAL;
-
- div = parent_rate / rate;
-
- if (parent_rate % rate)
- div++;
-
- if (div > 8)
- return -EINVAL;
-
- return parent_rate / div;
-
-}
-
-static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg, div;
-
- div = clk_get_rate(clk->parent) / rate;
- if (div == 0)
- div++;
- if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
- return -EINVAL;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
- reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- while (__raw_readl(MXC_CCM_CDHIPR) &
- MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
- }
-
- return 0;
-}
-
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
-{
- return external_high_reference;
-}
-
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
-{
- return external_low_reference;
-}
-
-static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
-{
- return oscillator_reference;
-}
-
-static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
-{
- return ckih2_reference;
-}
-
-static unsigned long clk_emi_slow_get_rate(struct clk *clk)
-{
- u32 reg, div;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
- MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
-
- return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
-{
- unsigned long rate;
- u32 reg, div;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
- MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
- rate = clk_get_rate(clk->parent) / div;
-
- return rate;
-}
-
-/* External high frequency clock */
-static struct clk ckih_clk = {
- .get_rate = get_high_reference_clock_rate,
-};
-
-static struct clk ckih2_clk = {
- .get_rate = get_ckih2_reference_clock_rate,
-};
-
-static struct clk osc_clk = {
- .get_rate = get_oscillator_reference_clock_rate,
-};
-
-/* External low frequency (32kHz) clock */
-static struct clk ckil_clk = {
- .get_rate = get_low_reference_clock_rate,
-};
-
-static struct clk pll1_main_clk = {
- .parent = &osc_clk,
- .get_rate = clk_pll_get_rate,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* Clock tree block diagram (WIP):
- * CCM: Clock Controller Module
- *
- * PLL output -> |
- * | CCM Switcher -> CCM_CLK_ROOT_GEN ->
- * PLL bypass -> |
- *
- */
-
-/* PLL1 SW supplies to ARM core */
-static struct clk pll1_sw_clk = {
- .parent = &pll1_main_clk,
- .set_parent = _clk_pll1_sw_set_parent,
- .get_rate = clk_pll1_sw_get_rate,
-};
-
-/* PLL2 SW supplies to AXI/AHB/IP buses */
-static struct clk pll2_sw_clk = {
- .parent = &osc_clk,
- .get_rate = clk_pll_get_rate,
- .set_rate = _clk_pll_set_rate,
- .set_parent = _clk_pll2_sw_set_parent,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
-static struct clk pll3_sw_clk = {
- .parent = &osc_clk,
- .set_rate = _clk_pll_set_rate,
- .get_rate = clk_pll_get_rate,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
-static struct clk mx53_pll4_sw_clk = {
- .parent = &osc_clk,
- .set_rate = _clk_pll_set_rate,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* Low-power Audio Playback Mode clock */
-static struct clk lp_apm_clk = {
- .parent = &osc_clk,
- .set_parent = _clk_lp_apm_set_parent,
-};
-
-static struct clk periph_apm_clk = {
- .parent = &pll1_sw_clk,
- .set_parent = _clk_periph_apm_set_parent,
-};
-
-static struct clk cpu_clk = {
- .parent = &pll1_sw_clk,
- .get_rate = clk_cpu_get_rate,
- .set_rate = clk_cpu_set_rate,
-};
-
-static struct clk ahb_clk = {
- .parent = &main_bus_clk,
- .get_rate = clk_ahb_get_rate,
- .set_rate = _clk_ahb_set_rate,
- .round_rate = _clk_ahb_round_rate,
-};
-
-static struct clk iim_clk = {
- .parent = &ipg_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
-};
-
-/* Main IP interface clock for access to registers */
-static struct clk ipg_clk = {
- .parent = &ahb_clk,
- .get_rate = clk_ipg_get_rate,
-};
-
-static struct clk ipg_perclk = {
- .parent = &lp_apm_clk,
- .get_rate = clk_ipg_per_get_rate,
- .set_parent = _clk_ipg_per_set_parent,
-};
-
-static struct clk ahb_max_clk = {
- .parent = &ahb_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
- .enable = _clk_max_enable,
- .disable = _clk_max_disable,
-};
-
-static struct clk aips_tz1_clk = {
- .parent = &ahb_clk,
- .secondary = &ahb_max_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk aips_tz2_clk = {
- .parent = &ahb_clk,
- .secondary = &ahb_max_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk gpc_dvfs_clk = {
- .enable_reg = MXC_CCM_CCGR5,
- .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable,
-};
-
-static struct clk gpt_32k_clk = {
- .id = 0,
- .parent = &ckil_clk,
-};
-
-static struct clk dummy_clk = {
- .id = 0,
-};
-
-static struct clk emi_slow_clk = {
- .parent = &pll2_sw_clk,
- .enable_reg = MXC_CCM_CCGR5,
- .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable_inwait,
- .get_rate = clk_emi_slow_get_rate,
-};
-
-static int clk_ipu_enable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_enable(clk);
-
- /* Enable handshake with IPU when certain clock rates are changed */
- reg = __raw_readl(MXC_CCM_CCDR);
- reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
- __raw_writel(reg, MXC_CCM_CCDR);
-
- /* Enable handshake with IPU when LPM is entered */
- reg = __raw_readl(MXC_CCM_CLPCR);
- reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-
- return 0;
-}
-
-static void clk_ipu_disable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_disable(clk);
-
- /* Disable handshake with IPU whe dividers are changed */
- reg = __raw_readl(MXC_CCM_CCDR);
- reg |= MXC_CCM_CCDR_IPU_HS_MASK;
- __raw_writel(reg, MXC_CCM_CCDR);
-
- /* Disable handshake with IPU when LPM is entered */
- reg = __raw_readl(MXC_CCM_CLPCR);
- reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk ahbmux1_clk = {
- .parent = &ahb_clk,
- .secondary = &ahb_max_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk ipu_sec_clk = {
- .parent = &emi_fast_clk,
- .secondary = &ahbmux1_clk,
-};
-
-static struct clk ddr_hf_clk = {
- .parent = &pll1_sw_clk,
- .get_rate = _clk_ddr_hf_get_rate,
-};
-
-static struct clk ddr_clk = {
- .parent = &ddr_hf_clk,
-};
-
-/* clock definitions for MIPI HSC unit which has been removed
- * from documentation, but not from hardware
- */
-static int _clk_hsc_enable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_enable(clk);
- /* Handshake with IPU when certain clock rates are changed. */
- reg = __raw_readl(MXC_CCM_CCDR);
- reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
- __raw_writel(reg, MXC_CCM_CCDR);
-
- reg = __raw_readl(MXC_CCM_CLPCR);
- reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-
- return 0;
-}
-
-static void _clk_hsc_disable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_disable(clk);
- /* No handshake with HSC as its not enabled. */
- reg = __raw_readl(MXC_CCM_CCDR);
- reg |= MXC_CCM_CCDR_HSC_HS_MASK;
- __raw_writel(reg, MXC_CCM_CCDR);
-
- reg = __raw_readl(MXC_CCM_CLPCR);
- reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk mipi_hsp_clk = {
- .parent = &ipu_clk,
- .enable_reg = MXC_CCM_CCGR4,
- .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
- .enable = _clk_hsc_enable,
- .disable = _clk_hsc_disable,
- .secondary = &mipi_hsc1_clk,
-};
-
-#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \
- static struct clk name = { \
- .id = i, \
- .enable_reg = er, \
- .enable_shift = es, \
- .get_rate = pfx##_get_rate, \
- .set_rate = pfx##_set_rate, \
- .round_rate = pfx##_round_rate, \
- .set_parent = pfx##_set_parent, \
- .enable = _clk_ccgr_enable, \
- .disable = _clk_ccgr_disable, \
- .parent = p, \
- .secondary = s, \
- }
-
-#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
- static struct clk name = { \
- .id = i, \
- .enable_reg = er, \
- .enable_shift = es, \
- .get_rate = pfx##_get_rate, \
- .set_rate = pfx##_set_rate, \
- .set_parent = pfx##_set_parent, \
- .enable = _clk_max_enable, \
- .disable = _clk_max_disable, \
- .parent = p, \
- .secondary = s, \
- }
-
-#define CLK_GET_RATE(name, nr, bitsname) \
-static unsigned long clk_##name##_get_rate(struct clk *clk) \
-{ \
- u32 reg, pred, podf; \
- \
- reg = __raw_readl(MXC_CCM_CSCDR##nr); \
- pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
- >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
- podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
- >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
- \
- return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
- (pred + 1) * (podf + 1)); \
-}
-
-#define CLK_SET_PARENT(name, nr, bitsname) \
-static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
-{ \
- u32 reg, mux; \
- \
- mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
- &pll3_sw_clk, &lp_apm_clk); \
- reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
- ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
- reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
- __raw_writel(reg, MXC_CCM_CSCMR##nr); \
- \
- return 0; \
-}
-
-#define CLK_SET_RATE(name, nr, bitsname) \
-static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
-{ \
- u32 reg, div, parent_rate; \
- u32 pre = 0, post = 0; \
- \
- parent_rate = clk_get_rate(clk->parent); \
- div = parent_rate / rate; \
- \
- if ((parent_rate / div) != rate) \
- return -EINVAL; \
- \
- __calc_pre_post_dividers(div, &pre, &post, \
- (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
- MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
- (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
- MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
- \
- /* Set sdhc1 clock divider */ \
- reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
- ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
- | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
- reg |= (post - 1) << \
- MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
- reg |= (pre - 1) << \
- MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
- __raw_writel(reg, MXC_CCM_CSCDR##nr); \
- \
- return 0; \
-}
-
-/* UART */
-CLK_GET_RATE(uart, 1, UART)
-CLK_SET_PARENT(uart, 1, UART)
-
-static struct clk uart_root_clk = {
- .parent = &pll2_sw_clk,
- .get_rate = clk_uart_get_rate,
- .set_parent = clk_uart_set_parent,
-};
-
-/* USBOH3 */
-CLK_GET_RATE(usboh3, 1, USBOH3)
-CLK_SET_PARENT(usboh3, 1, USBOH3)
-
-static struct clk usboh3_clk = {
- .parent = &pll2_sw_clk,
- .get_rate = clk_usboh3_get_rate,
- .set_parent = clk_usboh3_set_parent,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable,
- .enable_reg = MXC_CCM_CCGR2,
- .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-};
-
-static struct clk usb_ahb_clk = {
- .parent = &ipg_clk,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable,
- .enable_reg = MXC_CCM_CCGR2,
- .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-};
-
-static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
-
- if (parent == &pll3_sw_clk)
- reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
-
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-static struct clk usb_phy1_clk = {
- .parent = &pll3_sw_clk,
- .set_parent = clk_usb_phy1_set_parent,
- .enable = _clk_ccgr_enable,
- .enable_reg = MXC_CCM_CCGR2,
- .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
- .disable = _clk_ccgr_disable,
-};
-
-/* eCSPI */
-CLK_GET_RATE(ecspi, 2, CSPI)
-CLK_SET_PARENT(ecspi, 1, CSPI)
-
-static struct clk ecspi_main_clk = {
- .parent = &pll3_sw_clk,
- .get_rate = clk_ecspi_get_rate,
- .set_parent = clk_ecspi_set_parent,
-};
-
-/* eSDHC */
-CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-
-/* mx51 specific */
-CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-
-static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CSCMR1);
- if (parent == &esdhc1_clk)
- reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
- else if (parent == &esdhc2_clk)
- reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
- else
- return -EINVAL;
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CSCMR1);
- if (parent == &esdhc1_clk)
- reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
- else if (parent == &esdhc2_clk)
- reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
- else
- return -EINVAL;
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-/* mx53 specific */
-static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CSCMR1);
- if (parent == &esdhc1_clk)
- reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
- else if (parent == &esdhc3_mx53_clk)
- reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
- else
- return -EINVAL;
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-
-static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CSCMR1);
- if (parent == &esdhc1_clk)
- reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
- else if (parent == &esdhc3_mx53_clk)
- reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
- else
- return -EINVAL;
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
- static struct clk name = { \
- .id = i, \
- .enable_reg = er, \
- .enable_shift = es, \
- .get_rate = gr, \
- .set_rate = sr, \
- .enable = e, \
- .disable = d, \
- .parent = p, \
- .secondary = s, \
- }
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
- DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
-
-/* Shared peripheral bus arbiter */
-DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-
-/* UART */
-DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
- NULL, NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
- NULL, NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
- NULL, NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
- NULL, NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
- NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
- NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
-DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
- NULL, NULL, &uart_root_clk, &uart4_ipg_clk);
-DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
- NULL, NULL, &uart_root_clk, &uart5_ipg_clk);
-
-/* GPT */
-DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &ipg_clk, &gpt_ipg_clk);
-
-DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
- NULL, NULL, &ipg_perclk, NULL);
-
-/* I2C */
-DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
- NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
- NULL, NULL, &ipg_perclk, NULL);
-
-/* FEC */
-DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-
-/* NFC */
-DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
- clk_nfc, &emi_slow_clk, NULL);
-
-/* SSI */
-DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
-DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
- NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
-DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
- NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
-
-/* eCSPI */
-DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
- &ipg_clk, &spba_clk);
-DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
- NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
-DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
- NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
- &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
- NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
-
-/* CSPI */
-DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
- NULL, NULL, &ipg_clk, &cspi_ipg_clk);
-
-/* SDMA */
-DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
- NULL, NULL, &ahb_clk, NULL);
-
-/* eSDHC */
-DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
- NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
- clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
-DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
- NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
- NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-
-/* mx51 specific */
-DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
- clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc3_clk = {
- .id = 2,
- .parent = &esdhc1_clk,
- .set_parent = clk_esdhc3_set_parent,
- .enable_reg = MXC_CCM_CCGR3,
- .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
- .enable = _clk_max_enable,
- .disable = _clk_max_disable,
- .secondary = &esdhc3_ipg_clk,
-};
-static struct clk esdhc4_clk = {
- .id = 3,
- .parent = &esdhc1_clk,
- .set_parent = clk_esdhc4_set_parent,
- .enable_reg = MXC_CCM_CCGR3,
- .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
- .enable = _clk_max_enable,
- .disable = _clk_max_disable,
- .secondary = &esdhc4_ipg_clk,
-};
-
-/* mx53 specific */
-static struct clk esdhc2_mx53_clk = {
- .id = 2,
- .parent = &esdhc1_clk,
- .set_parent = clk_esdhc2_mx53_set_parent,
- .enable_reg = MXC_CCM_CCGR3,
- .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
- .enable = _clk_max_enable,
- .disable = _clk_max_disable,
- .secondary = &esdhc3_ipg_clk,
-};
-
-DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
- clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc4_mx53_clk = {
- .id = 3,
- .parent = &esdhc1_clk,
- .set_parent = clk_esdhc4_mx53_set_parent,
- .enable_reg = MXC_CCM_CCGR3,
- .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
- .enable = _clk_max_enable,
- .disable = _clk_max_disable,
- .secondary = &esdhc4_ipg_clk,
-};
-
-static struct clk sata_clk = {
- .parent = &ipg_clk,
- .enable = _clk_max_enable,
- .enable_reg = MXC_CCM_CCGR4,
- .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
- .disable = _clk_max_disable,
-};
-
-static struct clk ahci_phy_clk = {
- .parent = &usb_phy1_clk,
-};
-
-static struct clk ahci_dma_clk = {
- .parent = &ahb_clk,
-};
-
-DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
-
-/* IPU */
-DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
- NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
-
-DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
- NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
- &ddr_clk, NULL);
-
-DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
- NULL, NULL, &pll3_sw_clk, NULL);
-DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, &pll3_sw_clk, NULL);
-
-/* PATA */
-DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
- NULL, NULL, &ipg_clk, &spba_clk);
-
-#define _REGISTER_CLOCK(d, n, c) \
- { \
- .dev_id = d, \
- .con_id = n, \
- .clk = &c, \
- },
-
-static struct clk_lookup mx51_lookups[] = {
- /* i.mx51 has the i.mx21 type uart */
- _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
- _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
- _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
- _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
- /* i.mx51 has the i.mx27 type fec */
- _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
- _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
- _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
- _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
- _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
- _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
- _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
- _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
- _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
- _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
- _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
- _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
- _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
- _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
- _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
- _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
- _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
- _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
- _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
- _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
- /* i.mx51 has the i.mx35 type sdma */
- _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
- _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
- _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
- _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
- _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
- _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
- /* i.mx51 has the i.mx35 type cspi */
- _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
- _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
- _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
- _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
- _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
- _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
- _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
- _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
- _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
- _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
- _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
-};
-
-static struct clk_lookup mx53_lookups[] = {
- /* i.mx53 has the i.mx21 type uart */
- _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
- _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
- _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
- _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
- _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
- _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
- /* i.mx53 has the i.mx25 type fec */
- _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
- _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
- _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
- _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
- _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
- /* i.mx53 has the i.mx51 type ecspi */
- _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
- _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
- /* i.mx53 has the i.mx25 type cspi */
- _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
- _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
- _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
- _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
- /* i.mx53 has the i.mx35 type sdma */
- _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
- _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
- _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
- _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
- _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
- _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
- _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
- _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
- _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
-};
-
-static void clk_tree_init(void)
-{
- u32 reg;
-
- ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
-
- /*
- * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
- * 8MHz, its derived from lp_apm.
- *
- * FIXME: Verify if true for all boards
- */
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
- reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
- reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
- reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
- __raw_writel(reg, MXC_CCM_CBCDR);
-}
-
-int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
- unsigned long ckih1, unsigned long ckih2)
-{
- int i;
-
- external_low_reference = ckil;
- external_high_reference = ckih1;
- ckih2_reference = ckih2;
- oscillator_reference = osc;
-
- for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
- clkdev_add(&mx51_lookups[i]);
-
- clk_tree_init();
-
- clk_enable(&cpu_clk);
- clk_enable(&main_bus_clk);
-
- clk_enable(&iim_clk);
- imx_print_silicon_rev("i.MX51", mx51_revision());
- clk_disable(&iim_clk);
-
- /* move usb_phy_clk to 24MHz */
- clk_set_parent(&usb_phy1_clk, &osc_clk);
-
- /* set the usboh3_clk parent to pll2_sw_clk */
- clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-
- /* Set SDHC parents to be PLL2 */
- clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
- clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
-
- /* set SDHC root clock as 166.25MHZ*/
- clk_set_rate(&esdhc1_clk, 166250000);
- clk_set_rate(&esdhc2_clk, 166250000);
-
- /* System timer */
- mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
- MX51_INT_GPT);
- return 0;
-}
-
-int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
- unsigned long ckih1, unsigned long ckih2)
-{
- int i;
-
- external_low_reference = ckil;
- external_high_reference = ckih1;
- ckih2_reference = ckih2;
- oscillator_reference = osc;
-
- for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
- clkdev_add(&mx53_lookups[i]);
-
- clk_tree_init();
-
- clk_set_parent(&uart_root_clk, &pll3_sw_clk);
- clk_enable(&cpu_clk);
- clk_enable(&main_bus_clk);
-
- clk_enable(&iim_clk);
- imx_print_silicon_rev("i.MX53", mx53_revision());
- clk_disable(&iim_clk);
-
- /* Set SDHC parents to be PLL2 */
- clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
- clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
-
- /* set SDHC root clock as 200MHZ*/
- clk_set_rate(&esdhc1_clk, 200000000);
- clk_set_rate(&esdhc3_mx53_clk, 200000000);
-
- /* System timer */
- mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
- MX53_INT_GPT);
- return 0;
-}
-
-#ifdef CONFIG_OF
-static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
- unsigned long *ckih1, unsigned long *ckih2)
-{
- struct device_node *np;
-
- /* retrieve the freqency of fixed clocks from device tree */
- for_each_compatible_node(np, NULL, "fixed-clock") {
- u32 rate;
- if (of_property_read_u32(np, "clock-frequency", &rate))
- continue;
-
- if (of_device_is_compatible(np, "fsl,imx-ckil"))
- *ckil = rate;
- else if (of_device_is_compatible(np, "fsl,imx-osc"))
- *osc = rate;
- else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
- *ckih1 = rate;
- else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
- *ckih2 = rate;
- }
-}
-
-int __init mx51_clocks_init_dt(void)
-{
- unsigned long ckil, osc, ckih1, ckih2;
-
- clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
- return mx51_clocks_init(ckil, osc, ckih1, ckih2);
-}
-
-int __init mx53_clocks_init_dt(void)
-{
- unsigned long ckil, osc, ckih1, ckih2;
-
- clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
- return mx53_clocks_init(ckil, osc, ckih1, ckih2);
-}
-#endif
+++ /dev/null
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * This file contains the CPU initialization code.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-static int mx5_cpu_rev = -1;
-
-#define IIM_SREV 0x24
-#define MX50_HW_ADADIG_DIGPROG 0xB0
-
-static int get_mx51_srev(void)
-{
- void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
- u32 rev = readl(iim_base + IIM_SREV) & 0xff;
-
- switch (rev) {
- case 0x0:
- return IMX_CHIP_REVISION_2_0;
- case 0x10:
- return IMX_CHIP_REVISION_3_0;
- default:
- return IMX_CHIP_REVISION_UNKNOWN;
- }
-}
-
-/*
- * Returns:
- * the silicon revision of the cpu
- * -EINVAL - not a mx51
- */
-int mx51_revision(void)
-{
- if (!cpu_is_mx51())
- return -EINVAL;
-
- if (mx5_cpu_rev == -1)
- mx5_cpu_rev = get_mx51_srev();
-
- return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx51_revision);
-
-#ifdef CONFIG_NEON
-
-/*
- * All versions of the silicon before Rev. 3 have broken NEON implementations.
- * Dependent on link order - so the assumption is that vfp_init is called
- * before us.
- */
-static int __init mx51_neon_fixup(void)
-{
- if (!cpu_is_mx51())
- return 0;
-
- if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
- (elf_hwcap & HWCAP_NEON)) {
- elf_hwcap &= ~HWCAP_NEON;
- pr_info("Turning off NEON support, detected broken NEON implementation\n");
- }
- return 0;
-}
-
-late_initcall(mx51_neon_fixup);
-#endif
-
-static int get_mx53_srev(void)
-{
- void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
- u32 rev = readl(iim_base + IIM_SREV) & 0xff;
-
- switch (rev) {
- case 0x0:
- return IMX_CHIP_REVISION_1_0;
- case 0x2:
- return IMX_CHIP_REVISION_2_0;
- case 0x3:
- return IMX_CHIP_REVISION_2_1;
- default:
- return IMX_CHIP_REVISION_UNKNOWN;
- }
-}
-
-/*
- * Returns:
- * the silicon revision of the cpu
- * -EINVAL - not a mx53
- */
-int mx53_revision(void)
-{
- if (!cpu_is_mx53())
- return -EINVAL;
-
- if (mx5_cpu_rev == -1)
- mx5_cpu_rev = get_mx53_srev();
-
- return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx53_revision);
-
-static int get_mx50_srev(void)
-{
- void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
- u32 rev;
-
- if (!anatop) {
- mx5_cpu_rev = -EINVAL;
- return 0;
- }
-
- rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
- rev &= 0xff;
-
- iounmap(anatop);
- if (rev == 0x0)
- return IMX_CHIP_REVISION_1_0;
- else if (rev == 0x1)
- return IMX_CHIP_REVISION_1_1;
- return 0;
-}
-
-/*
- * Returns:
- * the silicon revision of the cpu
- * -EINVAL - not a mx50
- */
-int mx50_revision(void)
-{
- if (!cpu_is_mx50())
- return -EINVAL;
-
- if (mx5_cpu_rev == -1)
- mx5_cpu_rev = get_mx50_srev();
-
- return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx50_revision);
-
-static int __init post_cpu_init(void)
-{
- unsigned int reg;
- void __iomem *base;
-
- if (cpu_is_mx51() || cpu_is_mx53()) {
- if (cpu_is_mx51())
- base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
- else
- base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
-
- __raw_writel(0x0, base + 0x40);
- __raw_writel(0x0, base + 0x44);
- __raw_writel(0x0, base + 0x48);
- __raw_writel(0x0, base + 0x4C);
- reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
- __raw_writel(reg, base + 0x50);
-
- if (cpu_is_mx51())
- base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
- else
- base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
-
- __raw_writel(0x0, base + 0x40);
- __raw_writel(0x0, base + 0x44);
- __raw_writel(0x0, base + 0x48);
- __raw_writel(0x0, base + 0x4C);
- reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
- __raw_writel(reg, base + 0x50);
- }
-
- return 0;
-}
-
-postcore_initcall(post_cpu_init);
+++ /dev/null
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/types.h>
-#include <mach/hardware.h>
-#include <linux/kernel.h>
-
-static struct cpu_op mx51_cpu_op[] = {
- {
- .cpu_rate = 160000000,},
- {
- .cpu_rate = 800000000,},
-};
-
-struct cpu_op *mx51_get_cpu_op(int *op)
-{
- *op = ARRAY_SIZE(mx51_cpu_op);
- return mx51_cpu_op;
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-extern struct cpu_op *mx51_get_cpu_op(int *op);
+++ /dev/null
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-
-#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
-#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
-#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
-#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
-#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
-#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
-
-/*MX53*/
-#define MX53_CCM_BASE MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
-#define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
-#define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
-#define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-
-/* PLL Register Offsets */
-#define MXC_PLL_DP_CTL 0x00
-#define MXC_PLL_DP_CONFIG 0x04
-#define MXC_PLL_DP_OP 0x08
-#define MXC_PLL_DP_MFD 0x0C
-#define MXC_PLL_DP_MFN 0x10
-#define MXC_PLL_DP_MFNMINUS 0x14
-#define MXC_PLL_DP_MFNPLUS 0x18
-#define MXC_PLL_DP_HFS_OP 0x1C
-#define MXC_PLL_DP_HFS_MFD 0x20
-#define MXC_PLL_DP_HFS_MFN 0x24
-#define MXC_PLL_DP_MFN_TOGC 0x28
-#define MXC_PLL_DP_DESTAT 0x2c
-
-/* PLL Register Bit definitions */
-#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000
-#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000
-#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12
-#define MXC_PLL_DP_CTL_ADE 0x800
-#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8)
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8
-#define MXC_PLL_DP_CTL_HFSM 0x80
-#define MXC_PLL_DP_CTL_PRE 0x40
-#define MXC_PLL_DP_CTL_UPEN 0x20
-#define MXC_PLL_DP_CTL_RST 0x10
-#define MXC_PLL_DP_CTL_RCP 0x8
-#define MXC_PLL_DP_CTL_PLM 0x4
-#define MXC_PLL_DP_CTL_BRM0 0x2
-#define MXC_PLL_DP_CTL_LRF 0x1
-
-#define MXC_PLL_DP_CONFIG_BIST 0x8
-#define MXC_PLL_DP_CONFIG_SJC_CE 0x4
-#define MXC_PLL_DP_CONFIG_AREN 0x2
-#define MXC_PLL_DP_CONFIG_LDREQ 0x1
-
-#define MXC_PLL_DP_OP_MFI_OFFSET 4
-#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4)
-#define MXC_PLL_DP_OP_PDF_OFFSET 0
-#define MXC_PLL_DP_OP_PDF_MASK 0xF
-
-#define MXC_PLL_DP_MFD_OFFSET 0
-#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_OFFSET 0x0
-#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17)
-#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16)
-#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0
-#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF
-
-#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31)
-#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF
-
-/* Register addresses of CCM*/
-#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00)
-#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04)
-#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08)
-#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C)
-#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10)
-#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14)
-#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18)
-#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C)
-#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20)
-#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24)
-#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28)
-#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C)
-#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30)
-#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34)
-#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38)
-#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C)
-#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40)
-#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44)
-#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48)
-#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C)
-#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50)
-#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54)
-#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58)
-#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C)
-#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60)
-#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64)
-#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68)
-#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C)
-#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70)
-#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74)
-#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78)
-#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C)
-#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80)
-#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84)
-
-#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84)
-
-/* Define the bits in register CCR */
-#define MXC_CCM_CCR_COSC_EN (1 << 12)
-#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11)
-#define MXC_CCM_CCR_CAMP2_EN (1 << 10)
-#define MXC_CCM_CCR_CAMP1_EN (1 << 9)
-#define MXC_CCM_CCR_FPM_EN (1 << 8)
-#define MXC_CCM_CCR_OSCNT_OFFSET (0)
-#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
-
-/* Define the bits in register CCDR */
-#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18)
-#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
-#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16)
-
-/* Define the bits in register CSR */
-#define MXC_CCM_CSR_COSR_READY (1 << 5)
-#define MXC_CCM_CSR_LVS_VALUE (1 << 4)
-#define MXC_CCM_CSR_CAMP2_READY (1 << 3)
-#define MXC_CCM_CSR_CAMP1_READY (1 << 2)
-#define MXC_CCM_CSR_FPM_READY (1 << 1)
-#define MXC_CCM_CSR_REF_EN_B (1 << 0)
-
-/* Define the bits in register CCSR */
-#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9)
-#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7)
-#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7)
-#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0
-#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */
-#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
-#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
-#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5)
-#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5)
-#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3)
-#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3)
-#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk,
- 1: step_clk */
-#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1)
-#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0)
-
-/* Define the bits in register CACRR */
-#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0)
-#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7)
-
-/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
-#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30)
-#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27)
-#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27)
-#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22)
-#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19)
-#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16)
-#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16)
-#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13)
-#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
-#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0)
-#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7)
-
-/* Define the bits in register CBCMR */
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0)
-
-/* Define the bits in register CSCMR1 */
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30)
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL (0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7)
-#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1)
-
-/* Define the bits in register CSCMR2 */
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3)
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10)
-#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6)
-#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5)
-#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3)
-
-/* Define the bits in register CSCDR1 */
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7)
-
-/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F)
-
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F)
-
-/* Define the bits in register CDCDR */
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7)
-
-/* Define the bits in register CHSCCDR */
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7)
-
-/* Define the bits in register CSCDR2 */
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F)
-
-/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F)
-
-/* Define the bits in register CSCDR4 */
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F)
-
-/* Define the bits in register CDHIPR */
-#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
-#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8)
-#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7)
-#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6)
-#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5)
-#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4)
-#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3)
-#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2)
-#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1)
-#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0)
-
-/* Define the bits in register CDCR */
-#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3)
-
-/* Define the bits in register CLPCR */
-#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23)
-#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22)
-#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21)
-#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25)
-#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20)
-#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19)
-#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
-#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17)
-#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16)
-#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11)
-#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9)
-#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
-#define MXC_CCM_CLPCR_VSTBY (0x1 << 8)
-#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7)
-#define MXC_CCM_CLPCR_SBYOS (0x1 << 6)
-#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
-#define MXC_CCM_CLPCR_LPM_OFFSET (0)
-#define MXC_CCM_CLPCR_LPM_MASK (0x3)
-
-/* Define the bits in register CISR */
-#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25)
-#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
-#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20)
-#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19)
-#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18)
-#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17)
-#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16)
-#define MXC_CCM_CISR_COSC_READY (0x1 << 6)
-#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5)
-#define MXC_CCM_CISR_CKIH_READY (0x1 << 4)
-#define MXC_CCM_CISR_FPM_READY (0x1 << 3)
-#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2)
-#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1)
-#define MXC_CCM_CISR_LRF_PLL1 (0x1)
-
-/* Define the bits in register CIMR */
-#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25)
-#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
-#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20)
-#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19)
-#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18)
-#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17)
-#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16)
-#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5)
-#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4)
-#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3)
-#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2)
-#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1)
-#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1)
-
-/* Define the bits in register CCOSR */
-#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24)
-#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21)
-#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21)
-#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16)
-#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16)
-#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7)
-#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4)
-#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4)
-#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0)
-#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF)
-
-/* Define the bits in registers CGPR */
-#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4)
-#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7)
-
-/* Define the bits in registers CCGRx */
-#define MXC_CCM_CCGRx_CG_MASK 0x3
-#define MXC_CCM_CCGRx_MOD_OFF 0x0
-#define MXC_CCM_CCGRx_MOD_ON 0x3
-#define MXC_CCM_CCGRx_MOD_IDLE 0x1
-
-#define MXC_CCM_CCGRx_CG15_MASK (0x3 << 30)
-#define MXC_CCM_CCGRx_CG14_MASK (0x3 << 28)
-#define MXC_CCM_CCGRx_CG13_MASK (0x3 << 26)
-#define MXC_CCM_CCGRx_CG12_MASK (0x3 << 24)
-#define MXC_CCM_CCGRx_CG11_MASK (0x3 << 22)
-#define MXC_CCM_CCGRx_CG10_MASK (0x3 << 20)
-#define MXC_CCM_CCGRx_CG9_MASK (0x3 << 18)
-#define MXC_CCM_CCGRx_CG8_MASK (0x3 << 16)
-#define MXC_CCM_CCGRx_CG5_MASK (0x3 << 10)
-#define MXC_CCM_CCGRx_CG4_MASK (0x3 << 8)
-#define MXC_CCM_CCGRx_CG3_MASK (0x3 << 6)
-#define MXC_CCM_CCGRx_CG2_MASK (0x3 << 4)
-#define MXC_CCM_CCGRx_CG1_MASK (0x3 << 2)
-#define MXC_CCM_CCGRx_CG0_MASK (0x3 << 0)
-
-#define MXC_CCM_CCGRx_CG15_OFFSET 30
-#define MXC_CCM_CCGRx_CG14_OFFSET 28
-#define MXC_CCM_CCGRx_CG13_OFFSET 26
-#define MXC_CCM_CCGRx_CG12_OFFSET 24
-#define MXC_CCM_CCGRx_CG11_OFFSET 22
-#define MXC_CCM_CCGRx_CG10_OFFSET 20
-#define MXC_CCM_CCGRx_CG9_OFFSET 18
-#define MXC_CCM_CCGRx_CG8_OFFSET 16
-#define MXC_CCM_CCGRx_CG7_OFFSET 14
-#define MXC_CCM_CCGRx_CG6_OFFSET 12
-#define MXC_CCM_CCGRx_CG5_OFFSET 10
-#define MXC_CCM_CCGRx_CG4_OFFSET 8
-#define MXC_CCM_CCGRx_CG3_OFFSET 6
-#define MXC_CCM_CCGRx_CG2_OFFSET 4
-#define MXC_CCM_CCGRx_CG1_OFFSET 2
-#define MXC_CCM_CCGRx_CG0_OFFSET 0
-
-#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80)
-#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100)
-#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180)
-#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0)
-#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220)
-#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240)
-#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260)
-#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280)
-#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0)
-#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0)
-#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0)
-#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0)
-#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300)
-
-/* CORTEXA8 platform */
-#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0)
-#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4)
-#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8)
-#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC)
-#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10)
-#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14)
-#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18)
-#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20)
-#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24)
-
-/* DVFS CORE */
-#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00)
-#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04)
-#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08)
-#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C)
-#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10)
-#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14)
-#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18)
-#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C)
-#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20)
-#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24)
-#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28)
-#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C)
-#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30)
-#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34)
-#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38)
-#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C)
-#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40)
-
-/* GPC */
-#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0)
-#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4)
-#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8)
-#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC)
-#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10)
-#define MXC_GPC_PGR_ARMPG_OFFSET 8
-#define MXC_GPC_PGR_ARMPG_MASK (3 << 8)
-
-/* PGC */
-#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0)
-#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC)
-#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0)
-#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC)
-#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0)
-#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC)
-
-#define MXC_PGCR_PCR 1
-#define MXC_SRPGCR_PCR 1
-#define MXC_EMPGCR_PCR 1
-#define MXC_PGSR_PSR 1
-
-
-#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0)
-#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1)
-
-/* SRPG */
-#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0)
-#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4)
-#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8)
-
-#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0)
-#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4)
-#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0)
-#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4)
-#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0)
-#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4)
-#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8)
-
-#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0)
-#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4)
-#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8)
-
-#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0)
-#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4)
-#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8)
-
-#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
+++ /dev/null
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <mach/mx50.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
-#define imx50_add_imx_uart(id, pdata) \
- imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
-
-extern const struct imx_fec_data imx50_fec_data;
-#define imx50_add_fec(pdata) \
- imx_add_fec(&imx50_fec_data, pdata)
-
-extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
-#define imx50_add_imx_i2c(id, pdata) \
- imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
+++ /dev/null
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx51.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx51_fec_data;
-#define imx51_add_fec(pdata) \
- imx_add_fec(&imx51_fec_data, pdata)
-
-extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
-#define imx51_add_fsl_usb2_udc(pdata) \
- imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
-
-extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
-#define imx51_add_imx_i2c(id, pdata) \
- imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
-#define imx51_add_hsi2c(pdata) \
- imx51_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
-#define imx51_add_imx_ssi(id, pdata) \
- imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
-#define imx51_add_imx_uart(id, pdata) \
- imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
-
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
-#define imx51_add_mxc_ehci_otg(pdata) \
- imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
-#define imx51_add_mxc_ehci_hs(id, pdata) \
- imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
-
-extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
-#define imx51_add_mxc_nand(pdata) \
- imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
-#define imx51_add_sdhci_esdhc_imx(id, pdata) \
- imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx51_cspi_data;
-#define imx51_add_cspi(pdata) \
- imx_add_spi_imx(&imx51_cspi_data, pdata)
-
-extern const struct imx_spi_imx_data imx51_ecspi_data[];
-#define imx51_add_ecspi(id, pdata) \
- imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id, pdata) \
- imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
-
-extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
-#define imx51_add_mxc_pwm(id) \
- imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
-
-extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
-#define imx51_add_imx_keypad(pdata) \
- imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx51_pata_imx_data;
-#define imx51_add_pata_imx() \
- imx_add_pata_imx(&imx51_pata_imx_data)
+++ /dev/null
-/*
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx53.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx53_fec_data;
-#define imx53_add_fec(pdata) \
- imx_add_fec(&imx53_fec_data, pdata)
-
-extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
-#define imx53_add_imx_uart(id, pdata) \
- imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
-
-
-extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
-#define imx53_add_imx_i2c(id, pdata) \
- imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
-#define imx53_add_sdhci_esdhc_imx(id, pdata) \
- imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx53_ecspi_data[];
-#define imx53_add_ecspi(id, pdata) \
- imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
-#define imx53_add_imx2_wdt(id, pdata) \
- imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
-
-extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
-#define imx53_add_imx_ssi(id, pdata) \
- imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
-#define imx53_add_imx_keypad(pdata) \
- imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx53_pata_imx_data;
-#define imx53_add_pata_imx() \
- imx_add_pata_imx(&imx53_pata_imx_data)
-
-extern struct platform_device *__init imx53_add_ahci_imx(void);
+++ /dev/null
-#ifndef _EFIKA_H
-#define _EFIKA_H
-
-#define EFIKA_WLAN_EN IMX_GPIO_NR(2, 16)
-#define EFIKA_WLAN_RESET IMX_GPIO_NR(2, 10)
-#define EFIKA_USB_PHY_RESET IMX_GPIO_NR(2, 9)
-
-void __init efika_board_common_init(void);
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * 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.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
-
-#define MXC_OTG_OFFSET 0
-#define MXC_H1_OFFSET 0x200
-#define MXC_H2_OFFSET 0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT (1 << 4)
-
-#define MXC_USBCMD_OFFSET 0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
-
-int mx51_initialize_usb_hw(int port, unsigned int flags)
-{
- unsigned int v;
- void __iomem *usb_base;
- void __iomem *usbotg_base;
- void __iomem *usbother_base;
- int ret = 0;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base) {
- printk(KERN_ERR "%s(): ioremap failed\n", __func__);
- return -ENOMEM;
- }
-
- switch (port) {
- case 0: /* OTG port */
- usbotg_base = usb_base + MXC_OTG_OFFSET;
- break;
- case 1: /* Host 1 port */
- usbotg_base = usb_base + MXC_H1_OFFSET;
- break;
- case 2: /* Host 2 port */
- usbotg_base = usb_base + MXC_H2_OFFSET;
- break;
- default:
- printk(KERN_ERR"%s no such port %d\n", __func__, port);
- ret = -ENOENT;
- goto error;
- }
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- switch (port) {
- case 0: /*OTG port */
- if (flags & MXC_EHCI_INTERNAL_PHY) {
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
- if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
- /* OC/USBPWR is not used */
- v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
- } else {
- /* OC/USBPWR is used */
- v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
- }
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
- v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
- if (flags & MXC_EHCI_WAKEUP_ENABLED)
- v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
- else
- v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v |= MXC_OTG_UCTRL_OPM_BIT;
- else
- v &= ~MXC_OTG_UCTRL_OPM_BIT;
- __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
- }
- break;
- case 1: /* Host 1 */
- /*Host ULPI */
- v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
- if (flags & MXC_EHCI_WAKEUP_ENABLED) {
- /* HOST1 wakeup/ULPI intr enable */
- v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
- } else {
- /* HOST1 wakeup/ULPI intr disable */
- v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
- }
-
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
- else
- v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
- __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
- else
- v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
- v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
- if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
- /* Interrupt Threshold Control:Immediate (no threshold) */
- v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
- __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
- break;
- case 2: /* Host 2 ULPI */
- v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
- if (flags & MXC_EHCI_WAKEUP_ENABLED) {
- /* HOST1 wakeup/ULPI intr enable */
- v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
- } else {
- /* HOST1 wakeup/ULPI intr disable */
- v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
- }
-
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
- else
- v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
- __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
- break;
- }
-
-error:
- iounmap(usb_base);
- return ret;
-}
-
+++ /dev/null
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/leds.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/mach/arch.h>
-
-#include "devices-imx51.h"
-
-#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30)
-#define MBIMX51_LED0 IMX_GPIO_NR(3, 5)
-#define MBIMX51_LED1 IMX_GPIO_NR(3, 6)
-#define MBIMX51_LED2 IMX_GPIO_NR(3, 7)
-#define MBIMX51_LED3 IMX_GPIO_NR(3, 8)
-
-static const struct gpio_led mbimx51_leds[] __initconst = {
- {
- .name = "led0",
- .default_trigger = "heartbeat",
- .active_low = 1,
- .gpio = MBIMX51_LED0,
- },
- {
- .name = "led1",
- .default_trigger = "nand-disk",
- .active_low = 1,
- .gpio = MBIMX51_LED1,
- },
- {
- .name = "led2",
- .default_trigger = "mmc0",
- .active_low = 1,
- .gpio = MBIMX51_LED2,
- },
- {
- .name = "led3",
- .default_trigger = "default-on",
- .active_low = 1,
- .gpio = MBIMX51_LED3,
- },
-};
-
-static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
- .leds = mbimx51_leds,
- .num_leds = ARRAY_SIZE(mbimx51_leds),
-};
-
-static iomux_v3_cfg_t mbimx51_pads[] = {
- /* UART2 */
- MX51_PAD_UART2_RXD__UART2_RXD,
- MX51_PAD_UART2_TXD__UART2_TXD,
-
- /* UART3 */
- MX51_PAD_UART3_RXD__UART3_RXD,
- MX51_PAD_UART3_TXD__UART3_TXD,
- MX51_PAD_KEY_COL4__UART3_RTS,
- MX51_PAD_KEY_COL5__UART3_CTS,
-
- /* TSC2007 IRQ */
- MX51_PAD_NANDF_D10__GPIO3_30,
-
- /* LEDS */
- MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
- MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
- MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
- MX51_PAD_DISPB2_SER_RS__GPIO3_8,
-
- /* KPP */
- MX51_PAD_KEY_ROW0__KEY_ROW0,
- MX51_PAD_KEY_ROW1__KEY_ROW1,
- MX51_PAD_KEY_ROW2__KEY_ROW2,
- MX51_PAD_KEY_ROW3__KEY_ROW3,
- MX51_PAD_KEY_COL0__KEY_COL0,
- MX51_PAD_KEY_COL1__KEY_COL1,
- MX51_PAD_KEY_COL2__KEY_COL2,
- MX51_PAD_KEY_COL3__KEY_COL3,
-
- /* SD 1 */
- MX51_PAD_SD1_CMD__SD1_CMD,
- MX51_PAD_SD1_CLK__SD1_CLK,
- MX51_PAD_SD1_DATA0__SD1_DATA0,
- MX51_PAD_SD1_DATA1__SD1_DATA1,
- MX51_PAD_SD1_DATA2__SD1_DATA2,
- MX51_PAD_SD1_DATA3__SD1_DATA3,
-
- /* SD 2 */
- MX51_PAD_SD2_CMD__SD2_CMD,
- MX51_PAD_SD2_CLK__SD2_CLK,
- MX51_PAD_SD2_DATA0__SD2_DATA0,
- MX51_PAD_SD2_DATA1__SD2_DATA1,
- MX51_PAD_SD2_DATA2__SD2_DATA2,
- MX51_PAD_SD2_DATA3__SD2_DATA3,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mbimx51_keymap[] = {
- KEY(0, 0, KEY_1),
- KEY(0, 1, KEY_2),
- KEY(0, 2, KEY_3),
- KEY(0, 3, KEY_UP),
-
- KEY(1, 0, KEY_4),
- KEY(1, 1, KEY_5),
- KEY(1, 2, KEY_6),
- KEY(1, 3, KEY_LEFT),
-
- KEY(2, 0, KEY_7),
- KEY(2, 1, KEY_8),
- KEY(2, 2, KEY_9),
- KEY(2, 3, KEY_RIGHT),
-
- KEY(3, 0, KEY_0),
- KEY(3, 1, KEY_DOWN),
- KEY(3, 2, KEY_ESC),
- KEY(3, 3, KEY_ENTER),
-};
-
-static const struct matrix_keymap_data mbimx51_map_data __initconst = {
- .keymap = mbimx51_keymap,
- .keymap_size = ARRAY_SIZE(mbimx51_keymap),
-};
-
-static int tsc2007_get_pendown_state(void)
-{
- return !gpio_get_value(MBIMX51_TSC2007_GPIO);
-}
-
-struct tsc2007_platform_data tsc2007_data = {
- .model = 2007,
- .x_plate_ohms = 180,
- .get_pendown_state = tsc2007_get_pendown_state,
-};
-
-static struct i2c_board_info mbimx51_i2c_devices[] = {
- {
- I2C_BOARD_INFO("tsc2007", 0x49),
- .irq = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
- .platform_data = &tsc2007_data,
- }, {
- I2C_BOARD_INFO("tlv320aic23", 0x1a),
- },
-};
-
-/*
- * baseboard initialization.
- */
-void __init eukrea_mbimx51_baseboard_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
- ARRAY_SIZE(mbimx51_pads));
-
- imx51_add_imx_uart(1, NULL);
- imx51_add_imx_uart(2, &uart_pdata);
-
- gpio_request(MBIMX51_LED0, "LED0");
- gpio_direction_output(MBIMX51_LED0, 1);
- gpio_free(MBIMX51_LED0);
- gpio_request(MBIMX51_LED1, "LED1");
- gpio_direction_output(MBIMX51_LED1, 1);
- gpio_free(MBIMX51_LED1);
- gpio_request(MBIMX51_LED2, "LED2");
- gpio_direction_output(MBIMX51_LED2, 1);
- gpio_free(MBIMX51_LED2);
- gpio_request(MBIMX51_LED3, "LED3");
- gpio_direction_output(MBIMX51_LED3, 1);
- gpio_free(MBIMX51_LED3);
-
- gpio_led_register_device(-1, &mbimx51_leds_info);
-
- imx51_add_imx_keypad(&mbimx51_map_data);
-
- gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
- gpio_direction_input(MBIMX51_TSC2007_GPIO);
- irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
- IRQF_TRIGGER_FALLING);
- i2c_register_board_info(1, mbimx51_i2c_devices,
- ARRAY_SIZE(mbimx51_i2c_devices));
-
- imx51_add_sdhci_esdhc_imx(0, NULL);
- imx51_add_sdhci_esdhc_imx(1, NULL);
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 Eric Benard - eric@eukrea.com
- *
- * Based on pcm970-baseboard.c which is :
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/audmux.h>
-
-#include "devices-imx51.h"
-
-static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
- /* LED */
- MX51_PAD_NANDF_D10__GPIO3_30,
- /* SWITCH */
- NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
- PAD_CTL_PKE | PAD_CTL_SRE_FAST |
- PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
- /* UART2 */
- MX51_PAD_UART2_RXD__UART2_RXD,
- MX51_PAD_UART2_TXD__UART2_TXD,
- /* UART 3 */
- MX51_PAD_UART3_RXD__UART3_RXD,
- MX51_PAD_UART3_TXD__UART3_TXD,
- MX51_PAD_KEY_COL4__UART3_RTS,
- MX51_PAD_KEY_COL5__UART3_CTS,
- /* SD */
- MX51_PAD_SD1_CMD__SD1_CMD,
- MX51_PAD_SD1_CLK__SD1_CLK,
- MX51_PAD_SD1_DATA0__SD1_DATA0,
- MX51_PAD_SD1_DATA1__SD1_DATA1,
- MX51_PAD_SD1_DATA2__SD1_DATA2,
- MX51_PAD_SD1_DATA3__SD1_DATA3,
- /* SD1 CD */
- NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
- PAD_CTL_PKE | PAD_CTL_SRE_FAST |
- PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-};
-
-#define GPIO_LED1 IMX_GPIO_NR(3, 30)
-#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31)
-
-static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
- {
- .name = "led1",
- .default_trigger = "heartbeat",
- .active_low = 1,
- .gpio = GPIO_LED1,
- },
-};
-
-static const struct gpio_led_platform_data
- eukrea_mbimxsd_led_info __initconst = {
- .leds = eukrea_mbimxsd_leds,
- .num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
-};
-
-static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
- {
- .gpio = GPIO_SWITCH1,
- .code = BTN_0,
- .desc = "BP1",
- .active_low = 1,
- .wakeup = 1,
- },
-};
-
-static const struct gpio_keys_platform_data
- eukrea_mbimxsd_button_data __initconst = {
- .buttons = eukrea_mbimxsd_gpio_buttons,
- .nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
- {
- I2C_BOARD_INFO("tlv320aic23", 0x1a),
- },
-};
-
-/*
- * system init for baseboard usage. Will be called by cpuimx51sd init.
- *
- * Add platform devices present on this baseboard and init
- * them from CPU side as far as required to use them later on
- */
-void __init eukrea_mbimxsd51_baseboard_init(void)
-{
- if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
- ARRAY_SIZE(eukrea_mbimxsd_pads)))
- printk(KERN_ERR "error setting mbimxsd pads !\n");
-
- imx51_add_imx_uart(1, NULL);
- imx51_add_imx_uart(2, &uart_pdata);
-
- imx51_add_sdhci_esdhc_imx(0, NULL);
-
- gpio_request(GPIO_LED1, "LED1");
- gpio_direction_output(GPIO_LED1, 1);
- gpio_free(GPIO_LED1);
-
- gpio_request(GPIO_SWITCH1, "SWITCH1");
- gpio_direction_input(GPIO_SWITCH1);
- gpio_free(GPIO_SWITCH1);
-
- i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
- ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
-
- gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
- imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
-}
+++ /dev/null
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx51.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate(). Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
- OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
- OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
- OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
- OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
- OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
- OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
- OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
- OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
- OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
- OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
- OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
- OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
- OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
- OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
- OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
- { /* sentinel */ }
-};
-
-static int __init imx51_tzic_add_irq_domain(struct device_node *np,
- struct device_node *interrupt_parent)
-{
- irq_domain_add_simple(np, 0);
- return 0;
-}
-
-static int __init imx51_gpio_add_irq_domain(struct device_node *np,
- struct device_node *interrupt_parent)
-{
- static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
- gpio_irq_base -= 32;
- irq_domain_add_simple(np, gpio_irq_base);
-
- return 0;
-}
-
-static const struct of_device_id imx51_irq_match[] __initconst = {
- { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
- { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
- { /* sentinel */ }
-};
-
-static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
- { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
- { /* sentinel */ }
-};
-
-static void __init imx51_dt_init(void)
-{
- struct device_node *node;
- const struct of_device_id *of_id;
- void (*func)(void);
-
- of_irq_init(imx51_irq_match);
-
- node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
- if (node) {
- of_id = of_match_node(imx51_iomuxc_of_match, node);
- func = of_id->data;
- func();
- of_node_put(node);
- }
-
- of_platform_populate(NULL, of_default_bus_match_table,
- imx51_auxdata_lookup, NULL);
-}
-
-static void __init imx51_timer_init(void)
-{
- mx51_clocks_init_dt();
-}
-
-static struct sys_timer imx51_timer = {
- .init = imx51_timer_init,
-};
-
-static const char *imx51_dt_board_compat[] __initdata = {
- "fsl,imx51-babbage",
- NULL
-};
-
-DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &imx51_timer,
- .init_machine = imx51_dt_init,
- .dt_compat = imx51_dt_board_compat,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx53.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate(). Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
- OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
- OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
- OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
- OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
- OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
- OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
- OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
- OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
- OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
- OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
- OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
- OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
- OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
- OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
- OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
- OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
- OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
- OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
- { /* sentinel */ }
-};
-
-static int __init imx53_tzic_add_irq_domain(struct device_node *np,
- struct device_node *interrupt_parent)
-{
- irq_domain_add_simple(np, 0);
- return 0;
-}
-
-static int __init imx53_gpio_add_irq_domain(struct device_node *np,
- struct device_node *interrupt_parent)
-{
- static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
- gpio_irq_base -= 32;
- irq_domain_add_simple(np, gpio_irq_base);
-
- return 0;
-}
-
-static const struct of_device_id imx53_irq_match[] __initconst = {
- { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
- { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
- { /* sentinel */ }
-};
-
-static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
- { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
- { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
- { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
- { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
- { /* sentinel */ }
-};
-
-static void __init imx53_dt_init(void)
-{
- struct device_node *node;
- const struct of_device_id *of_id;
- void (*func)(void);
-
- of_irq_init(imx53_irq_match);
-
- node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
- if (node) {
- of_id = of_match_node(imx53_iomuxc_of_match, node);
- func = of_id->data;
- func();
- of_node_put(node);
- }
-
- of_platform_populate(NULL, of_default_bus_match_table,
- imx53_auxdata_lookup, NULL);
-}
-
-static void __init imx53_timer_init(void)
-{
- mx53_clocks_init_dt();
-}
-
-static struct sys_timer imx53_timer = {
- .init = imx53_timer_init,
-};
-
-static const char *imx53_dt_board_compat[] __initdata = {
- "fsl,imx53-ard",
- "fsl,imx53-evk",
- "fsl,imx53-qsb",
- "fsl,imx53-smd",
- NULL
-};
-
-DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
- .map_io = mx53_map_io,
- .init_early = imx53_init_early,
- .init_irq = mx53_init_irq,
- .handle_irq = imx53_handle_irq,
- .timer = &imx53_timer,
- .init_machine = imx53_dt_init,
- .dt_compat = imx53_dt_board_compat,
- .restart = mxc_restart,
-MACHINE_END
+++ /dev/null
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/iomux-v3.h>
-
-static struct clk *gpc_dvfs_clk;
-
-static void imx5_idle(void)
-{
- if (!need_resched()) {
- /* gpc clock is needed for SRPG */
- if (gpc_dvfs_clk == NULL) {
- gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
- if (IS_ERR(gpc_dvfs_clk))
- goto err0;
- }
- clk_enable(gpc_dvfs_clk);
- mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
- if (tzic_enable_wake())
- goto err1;
- cpu_do_idle();
-err1:
- clk_disable(gpc_dvfs_clk);
- }
-err0:
- local_irq_enable();
-}
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
- imx_map_entry(MX50, TZIC, MT_DEVICE),
- imx_map_entry(MX50, SPBA0, MT_DEVICE),
- imx_map_entry(MX50, AIPS1, MT_DEVICE),
- imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX51 memory map.
- */
-static struct map_desc mx51_io_desc[] __initdata = {
- imx_map_entry(MX51, TZIC, MT_DEVICE),
- imx_map_entry(MX51, IRAM, MT_DEVICE),
- imx_map_entry(MX51, AIPS1, MT_DEVICE),
- imx_map_entry(MX51, SPBA0, MT_DEVICE),
- imx_map_entry(MX51, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX53 memory map.
- */
-static struct map_desc mx53_io_desc[] __initdata = {
- imx_map_entry(MX53, TZIC, MT_DEVICE),
- imx_map_entry(MX53, AIPS1, MT_DEVICE),
- imx_map_entry(MX53, SPBA0, MT_DEVICE),
- imx_map_entry(MX53, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx50_map_io(void)
-{
- iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
-void __init mx51_map_io(void)
-{
- iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
-}
-
-void __init mx53_map_io(void)
-{
- iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
-}
-
-void __init imx50_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX50);
- mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
- mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
-void __init imx51_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX51);
- mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
- mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
- pm_idle = imx5_idle;
-}
-
-void __init imx53_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX53);
- mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
- mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
-}
-
-void __init mx50_init_irq(void)
-{
- tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init mx51_init_irq(void)
-{
- tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
-}
-
-void __init mx53_init_irq(void)
-{
- tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
- .ap_2_ap_addr = 642,
- .uart_2_mcu_addr = 817,
- .mcu_2_app_addr = 747,
- .mcu_2_shp_addr = 961,
- .ata_2_mcu_addr = 1473,
- .mcu_2_ata_addr = 1392,
- .app_2_per_addr = 1033,
- .app_2_mcu_addr = 683,
- .shp_2_per_addr = 1251,
- .shp_2_mcu_addr = 892,
-};
-
-static struct sdma_platform_data imx51_sdma_pdata __initdata = {
- .fw_name = "sdma-imx51.bin",
- .script_addrs = &imx51_sdma_script,
-};
-
-static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
- .ap_2_ap_addr = 642,
- .app_2_mcu_addr = 683,
- .mcu_2_app_addr = 747,
- .uart_2_mcu_addr = 817,
- .shp_2_mcu_addr = 891,
- .mcu_2_shp_addr = 960,
- .uartsh_2_mcu_addr = 1032,
- .spdif_2_mcu_addr = 1100,
- .mcu_2_spdif_addr = 1134,
- .firi_2_mcu_addr = 1193,
- .mcu_2_firi_addr = 1290,
-};
-
-static struct sdma_platform_data imx53_sdma_pdata __initdata = {
- .fw_name = "sdma-imx53.bin",
- .script_addrs = &imx53_sdma_script,
-};
-
-void __init imx50_soc_init(void)
-{
- /* i.mx50 has the i.mx31 type gpio */
- mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
- mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
- mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
- mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
- mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
- mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
-
-void __init imx51_soc_init(void)
-{
- /* i.mx51 has the i.mx31 type gpio */
- mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
- mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
- mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
- mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
-
- /* i.mx51 has the i.mx35 type sdma */
- imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
-}
-
-void __init imx53_soc_init(void)
-{
- /* i.mx53 has the i.mx31 type gpio */
- mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
- mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
- mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
- mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
- mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
- mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
- mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
-
- /* i.mx53 has the i.mx35 type sdma */
- imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
-}
+++ /dev/null
-/*
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-#include "cpu_op-mx51.h"
-
-#define MX51_USB_CTRL_1_OFFSET 0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
-#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
-
-#define EFIKAMX_USB_HUB_RESET IMX_GPIO_NR(1, 5)
-#define EFIKAMX_USBH1_STP IMX_GPIO_NR(1, 27)
-
-#define EFIKAMX_SPI_CS0 IMX_GPIO_NR(4, 24)
-#define EFIKAMX_SPI_CS1 IMX_GPIO_NR(4, 25)
-
-#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6)
-
-static iomux_v3_cfg_t mx51efika_pads[] = {
- /* UART1 */
- MX51_PAD_UART1_RXD__UART1_RXD,
- MX51_PAD_UART1_TXD__UART1_TXD,
- MX51_PAD_UART1_RTS__UART1_RTS,
- MX51_PAD_UART1_CTS__UART1_CTS,
-
- /* SD 1 */
- MX51_PAD_SD1_CMD__SD1_CMD,
- MX51_PAD_SD1_CLK__SD1_CLK,
- MX51_PAD_SD1_DATA0__SD1_DATA0,
- MX51_PAD_SD1_DATA1__SD1_DATA1,
- MX51_PAD_SD1_DATA2__SD1_DATA2,
- MX51_PAD_SD1_DATA3__SD1_DATA3,
-
- /* SD 2 */
- MX51_PAD_SD2_CMD__SD2_CMD,
- MX51_PAD_SD2_CLK__SD2_CLK,
- MX51_PAD_SD2_DATA0__SD2_DATA0,
- MX51_PAD_SD2_DATA1__SD2_DATA1,
- MX51_PAD_SD2_DATA2__SD2_DATA2,
- MX51_PAD_SD2_DATA3__SD2_DATA3,
-
- /* SD/MMC WP/CD */
- MX51_PAD_GPIO1_0__SD1_CD,
- MX51_PAD_GPIO1_1__SD1_WP,
- MX51_PAD_GPIO1_7__SD2_WP,
- MX51_PAD_GPIO1_8__SD2_CD,
-
- /* spi */
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
- MX51_PAD_CSPI1_SS0__GPIO4_24,
- MX51_PAD_CSPI1_SS1__GPIO4_25,
- MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
- MX51_PAD_GPIO1_6__GPIO1_6,
-
- /* USB HOST1 */
- MX51_PAD_USBH1_CLK__USBH1_CLK,
- MX51_PAD_USBH1_DIR__USBH1_DIR,
- MX51_PAD_USBH1_NXT__USBH1_NXT,
- MX51_PAD_USBH1_DATA0__USBH1_DATA0,
- MX51_PAD_USBH1_DATA1__USBH1_DATA1,
- MX51_PAD_USBH1_DATA2__USBH1_DATA2,
- MX51_PAD_USBH1_DATA3__USBH1_DATA3,
- MX51_PAD_USBH1_DATA4__USBH1_DATA4,
- MX51_PAD_USBH1_DATA5__USBH1_DATA5,
- MX51_PAD_USBH1_DATA6__USBH1_DATA6,
- MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
- /* USB HUB RESET */
- MX51_PAD_GPIO1_5__GPIO1_5,
-
- /* WLAN */
- MX51_PAD_EIM_A22__GPIO2_16,
- MX51_PAD_EIM_A16__GPIO2_10,
-
- /* USB PHY RESET */
- MX51_PAD_EIM_D27__GPIO2_9,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
- * be different for other Freescale SoCs, thus a common bitmask is not
- * possible and cannot get place in /plat-mxc/ehci.c.
- */
-static int initialize_otg_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
- /* Set the PHY clock to 19.2MHz */
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
- v |= MX51_USB_PLL_DIV_19_2_MHZ;
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
- .init = initialize_otg_port,
- .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
- iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
- iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
- u32 v;
- void __iomem *usb_base;
- void __iomem *socregs_base;
-
- mxc_iomux_v3_setup_pad(usbh1gpio);
- gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
- gpio_direction_output(EFIKAMX_USBH1_STP, 0);
- msleep(1);
- gpio_set_value(EFIKAMX_USBH1_STP, 1);
- msleep(1);
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
- /* The clock for the USBH1 ULPI port will come externally */
- /* from the PHY. */
- v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
- __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
- socregs_base + MX51_USB_CTRL_1_OFFSET);
-
- iounmap(usb_base);
-
- gpio_free(EFIKAMX_USBH1_STP);
- mxc_iomux_v3_setup_pad(usbh1stp);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh1_config __initdata = {
- .init = initialize_usbh1_port,
- .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void mx51_efika_hubreset(void)
-{
- gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
- gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
- msleep(1);
- gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
- msleep(1);
- gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
-}
-
-static void __init mx51_efika_usb(void)
-{
- mx51_efika_hubreset();
-
- /* pulling it low, means no USB at all... */
- gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
- gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
- msleep(1);
- gpio_set_value(EFIKA_USB_PHY_RESET, 1);
-
- usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
- ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-
- imx51_add_mxc_ehci_otg(&dr_utmi_config);
- if (usbh1_config.otg)
- imx51_add_mxc_ehci_hs(1, &usbh1_config);
-}
-
-static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
- {
- .name = "u-boot",
- .offset = 0,
- .size = SZ_256K,
- },
- {
- .name = "config",
- .offset = MTDPART_OFS_APPEND,
- .size = SZ_64K,
- },
-};
-
-static struct flash_platform_data mx51_efika_spi_flash_data = {
- .name = "spi_flash",
- .parts = mx51_efika_spi_nor_partitions,
- .nr_parts = ARRAY_SIZE(mx51_efika_spi_nor_partitions),
- .type = "sst25vf032b",
-};
-
-static struct regulator_consumer_supply sw1_consumers[] = {
- {
- .supply = "cpu_vcc",
- }
-};
-
-static struct regulator_consumer_supply vdig_consumers[] = {
- /* sgtl5000 */
- REGULATOR_SUPPLY("VDDA", "1-000a"),
- REGULATOR_SUPPLY("VDDD", "1-000a"),
-};
-
-static struct regulator_consumer_supply vvideo_consumers[] = {
- /* sgtl5000 */
- REGULATOR_SUPPLY("VDDIO", "1-000a"),
-};
-
-static struct regulator_consumer_supply vsd_consumers[] = {
- REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
- REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
-};
-
-static struct regulator_consumer_supply pwgt1_consumer[] = {
- {
- .supply = "pwgt1",
- }
-};
-
-static struct regulator_consumer_supply pwgt2_consumer[] = {
- {
- .supply = "pwgt2",
- }
-};
-
-static struct regulator_consumer_supply coincell_consumer[] = {
- {
- .supply = "coincell",
- }
-};
-
-static struct regulator_init_data sw1_init = {
- .constraints = {
- .name = "SW1",
- .min_uV = 600000,
- .max_uV = 1375000,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
- .valid_modes_mask = 0,
- .always_on = 1,
- .boot_on = 1,
- .state_mem = {
- .uV = 850000,
- .mode = REGULATOR_MODE_NORMAL,
- .enabled = 1,
- },
- },
- .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
- .consumer_supplies = sw1_consumers,
-};
-
-static struct regulator_init_data sw2_init = {
- .constraints = {
- .name = "SW2",
- .min_uV = 900000,
- .max_uV = 1850000,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
- .always_on = 1,
- .boot_on = 1,
- .state_mem = {
- .uV = 950000,
- .mode = REGULATOR_MODE_NORMAL,
- .enabled = 1,
- },
- }
-};
-
-static struct regulator_init_data sw3_init = {
- .constraints = {
- .name = "SW3",
- .min_uV = 1100000,
- .max_uV = 1850000,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
- .always_on = 1,
- .boot_on = 1,
- }
-};
-
-static struct regulator_init_data sw4_init = {
- .constraints = {
- .name = "SW4",
- .min_uV = 1100000,
- .max_uV = 1850000,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
- .always_on = 1,
- .boot_on = 1,
- }
-};
-
-static struct regulator_init_data viohi_init = {
- .constraints = {
- .name = "VIOHI",
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data vusb_init = {
- .constraints = {
- .name = "VUSB",
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data swbst_init = {
- .constraints = {
- .name = "SWBST",
- }
-};
-
-static struct regulator_init_data vdig_init = {
- .constraints = {
- .name = "VDIG",
- .min_uV = 1050000,
- .max_uV = 1800000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- .always_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
- .consumer_supplies = vdig_consumers,
-};
-
-static struct regulator_init_data vpll_init = {
- .constraints = {
- .name = "VPLL",
- .min_uV = 1050000,
- .max_uV = 1800000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data vusb2_init = {
- .constraints = {
- .name = "VUSB2",
- .min_uV = 2400000,
- .max_uV = 2775000,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data vvideo_init = {
- .constraints = {
- .name = "VVIDEO",
- .min_uV = 2775000,
- .max_uV = 2775000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- .apply_uV = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
- .consumer_supplies = vvideo_consumers,
-};
-
-static struct regulator_init_data vaudio_init = {
- .constraints = {
- .name = "VAUDIO",
- .min_uV = 2300000,
- .max_uV = 3000000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- }
-};
-
-static struct regulator_init_data vsd_init = {
- .constraints = {
- .name = "VSD",
- .min_uV = 1800000,
- .max_uV = 3150000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE,
- .boot_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
- .consumer_supplies = vsd_consumers,
-};
-
-static struct regulator_init_data vcam_init = {
- .constraints = {
- .name = "VCAM",
- .min_uV = 2500000,
- .max_uV = 3000000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
- .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
- .boot_on = 1,
- }
-};
-
-static struct regulator_init_data vgen1_init = {
- .constraints = {
- .name = "VGEN1",
- .min_uV = 1200000,
- .max_uV = 3150000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data vgen2_init = {
- .constraints = {
- .name = "VGEN2",
- .min_uV = 1200000,
- .max_uV = 3150000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data vgen3_init = {
- .constraints = {
- .name = "VGEN3",
- .min_uV = 1800000,
- .max_uV = 2900000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- .always_on = 1,
- }
-};
-
-static struct regulator_init_data gpo1_init = {
- .constraints = {
- .name = "GPO1",
- }
-};
-
-static struct regulator_init_data gpo2_init = {
- .constraints = {
- .name = "GPO2",
- }
-};
-
-static struct regulator_init_data gpo3_init = {
- .constraints = {
- .name = "GPO3",
- }
-};
-
-static struct regulator_init_data gpo4_init = {
- .constraints = {
- .name = "GPO4",
- }
-};
-
-static struct regulator_init_data pwgt1_init = {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
- .consumer_supplies = pwgt1_consumer,
-};
-
-static struct regulator_init_data pwgt2_init = {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- .boot_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
- .consumer_supplies = pwgt2_consumer,
-};
-
-static struct regulator_init_data vcoincell_init = {
- .constraints = {
- .name = "COINCELL",
- .min_uV = 3000000,
- .max_uV = 3000000,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
- .consumer_supplies = coincell_consumer,
-};
-
-static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
- { .id = MC13892_SW1, .init_data = &sw1_init },
- { .id = MC13892_SW2, .init_data = &sw2_init },
- { .id = MC13892_SW3, .init_data = &sw3_init },
- { .id = MC13892_SW4, .init_data = &sw4_init },
- { .id = MC13892_SWBST, .init_data = &swbst_init },
- { .id = MC13892_VIOHI, .init_data = &viohi_init },
- { .id = MC13892_VPLL, .init_data = &vpll_init },
- { .id = MC13892_VDIG, .init_data = &vdig_init },
- { .id = MC13892_VSD, .init_data = &vsd_init },
- { .id = MC13892_VUSB2, .init_data = &vusb2_init },
- { .id = MC13892_VVIDEO, .init_data = &vvideo_init },
- { .id = MC13892_VAUDIO, .init_data = &vaudio_init },
- { .id = MC13892_VCAM, .init_data = &vcam_init },
- { .id = MC13892_VGEN1, .init_data = &vgen1_init },
- { .id = MC13892_VGEN2, .init_data = &vgen2_init },
- { .id = MC13892_VGEN3, .init_data = &vgen3_init },
- { .id = MC13892_VUSB, .init_data = &vusb_init },
- { .id = MC13892_GPO1, .init_data = &gpo1_init },
- { .id = MC13892_GPO2, .init_data = &gpo2_init },
- { .id = MC13892_GPO3, .init_data = &gpo3_init },
- { .id = MC13892_GPO4, .init_data = &gpo4_init },
- { .id = MC13892_PWGT1SPI, .init_data = &pwgt1_init },
- { .id = MC13892_PWGT2SPI, .init_data = &pwgt2_init },
- { .id = MC13892_VCOINCELL, .init_data = &vcoincell_init },
-};
-
-static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
- .flags = MC13XXX_USE_RTC,
- .regulators = {
- .num_regulators = ARRAY_SIZE(mx51_efika_regulators),
- .regulators = mx51_efika_regulators,
- },
-};
-
-static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
- {
- .modalias = "m25p80",
- .max_speed_hz = 25000000,
- .bus_num = 0,
- .chip_select = 1,
- .platform_data = &mx51_efika_spi_flash_data,
- .irq = -1,
- },
- {
- .modalias = "mc13892",
- .max_speed_hz = 1000000,
- .bus_num = 0,
- .chip_select = 0,
- .platform_data = &mx51_efika_mc13892_data,
- .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
- },
-};
-
-static int mx51_efika_spi_cs[] = {
- EFIKAMX_SPI_CS0,
- EFIKAMX_SPI_CS1,
-};
-
-static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
- .chipselect = mx51_efika_spi_cs,
- .num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
-};
-
-void __init efika_board_common_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
- ARRAY_SIZE(mx51efika_pads));
- imx51_add_imx_uart(0, &uart_pdata);
- mx51_efika_usb();
-
- /* FIXME: comes from original code. check this. */
- if (mx51_revision() < IMX_CHIP_REVISION_2_0)
- sw2_init.constraints.state_mem.uV = 1100000;
- else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
- sw2_init.constraints.state_mem.uV = 1250000;
- sw1_init.constraints.state_mem.uV = 1000000;
- }
- if (machine_is_mx51_efikasb())
- vgen1_init.constraints.max_uV = 1200000;
-
- gpio_request(EFIKAMX_PMIC, "pmic irq");
- gpio_direction_input(EFIKAMX_PMIC);
- spi_register_board_info(mx51_efika_spi_board_info,
- ARRAY_SIZE(mx51_efika_spi_board_info));
- imx51_add_ecspi(0, &mx51_efika_spi_pdata);
-
- imx51_add_pata_imx();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
- get_cpu_op = mx51_get_cpu_op;
-#endif
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/suspend.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include "crm_regs.h"
-
-static struct clk *gpc_dvfs_clk;
-
-static int mx5_suspend_prepare(void)
-{
- return clk_enable(gpc_dvfs_clk);
-}
-
-static int mx5_suspend_enter(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_MEM:
- mx5_cpu_lp_set(STOP_POWER_OFF);
- break;
- case PM_SUSPEND_STANDBY:
- mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
- break;
- default:
- return -EINVAL;
- }
-
- if (state == PM_SUSPEND_MEM) {
- local_flush_tlb_all();
- flush_cache_all();
-
- /*clear the EMPGC0/1 bits */
- __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
- __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
- }
- cpu_do_idle();
- return 0;
-}
-
-static void mx5_suspend_finish(void)
-{
- clk_disable(gpc_dvfs_clk);
-}
-
-static int mx5_pm_valid(suspend_state_t state)
-{
- return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
-}
-
-static const struct platform_suspend_ops mx5_suspend_ops = {
- .valid = mx5_pm_valid,
- .prepare = mx5_suspend_prepare,
- .enter = mx5_suspend_enter,
- .finish = mx5_suspend_finish,
-};
-
-static int __init mx5_pm_init(void)
-{
- if (gpc_dvfs_clk == NULL)
- gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-
- if (!IS_ERR(gpc_dvfs_clk)) {
- if (cpu_is_mx51())
- suspend_set_ops(&mx5_suspend_ops);
- } else
- return -EPERM;
-
- return 0;
-}
-device_initcall(mx5_pm_init);
+++ /dev/null
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include "crm_regs.h"
-
-/* set cpu low power mode before WFI instruction. This function is called
- * mx5 because it can be used for mx50, mx51, and mx53.*/
-void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
-{
- u32 plat_lpc, arm_srpgcr, ccm_clpcr;
- u32 empgc0, empgc1;
- int stop_mode = 0;
-
- /* always allow platform to issue a deep sleep mode request */
- plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
- ~(MXC_CORTEXA8_PLAT_LPC_DSM);
- ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
- arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
- empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
- empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
-
- switch (mode) {
- case WAIT_CLOCKED:
- break;
- case WAIT_UNCLOCKED:
- ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
- break;
- case WAIT_UNCLOCKED_POWER_OFF:
- case STOP_POWER_OFF:
- plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
- | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
- if (mode == WAIT_UNCLOCKED_POWER_OFF) {
- ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
- ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
- ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
- stop_mode = 0;
- } else {
- ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
- ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
- ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
- ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
- stop_mode = 1;
- }
- arm_srpgcr |= MXC_SRPGCR_PCR;
- break;
- case STOP_POWER_ON:
- ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
- break;
- default:
- printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
- return;
- }
-
- __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
- __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
- __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
-
- /* Enable NEON SRPG for all but MX50TO1.0. */
- if (mx50_revision() != IMX_CHIP_REVISION_1_0)
- __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
-
- if (stop_mode) {
- empgc0 |= MXC_SRPGCR_PCR;
- empgc1 |= MXC_SRPGCR_PCR;
-
- __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
- __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
- }
-}
default y
select CPU_V7
select USB_ARCH_HAS_EHCI
- select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
select ARCH_HAS_OPP
select PM_OPP if PM
select ARM_CPU_SUSPEND if PM
},
};
-static struct resource sa1100_rtc_resources[] = {
- [0] = {
- .start = 0x40900000,
- .end = 0x409000ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_RTC1Hz,
- .end = IRQ_RTC1Hz,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_RTCAlrm,
- .end = IRQ_RTCAlrm,
- .flags = IORESOURCE_IRQ,
- },
-};
-
struct platform_device sa1100_device_rtc = {
.name = "sa1100-rtc",
.id = -1,
- .num_resources = ARRAY_SIZE(sa1100_rtc_resources),
- .resource = sa1100_rtc_resources,
};
struct platform_device pxa_device_rtc = {
INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
- INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
static struct clk_lookup pxa25x_hwuart_clkreg =
INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
- INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
#ifdef CONFIG_PM
static struct clk_lookup common_clkregs[] = {
INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0);
static struct clk_lookup pxa320_clkregs[] = {
INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
static int __init pxa320_init(void)
INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
/* Power I2C clock is always on */
INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
/* Power I2C clock is always on */
INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
extern volatile int pen_release;
#define REALVIEW_EB_USB_BASE 0x4F000000 /* USB */
#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
-#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */
-#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
-#define REALVIEW_EB11MP_TWD_BASE 0x10100600
-#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
+#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000
#define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
#else
-#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */
-#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
-#define REALVIEW_EB11MP_TWD_BASE 0x1F000600
-#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
+#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000
#define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
#endif
+#define REALVIEW_EB11MP_PRIV_MEM_SIZE SZ_8K
+#define REALVIEW_EB11MP_PRIV_MEM_OFF(x) (REALVIEW_EB11MP_PRIV_MEM_BASE + (x))
+
+#define REALVIEW_EB11MP_SCU_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0) /* SCU registers */
+#define REALVIEW_EB11MP_GIC_CPU_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x0100) /* Generic interrupt controller CPU interface */
+#define REALVIEW_EB11MP_TWD_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x0600)
+#define REALVIEW_EB11MP_GIC_DIST_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x1000) /* Generic interrupt controller distributor */
+
/*
* Core tile identification (REALVIEW_SYS_PROCID)
*/
/*
* Testchip peripheral and fpga gic regions
*/
+#define REALVIEW_TC11MP_PRIV_MEM_BASE 0x1F000000
+#define REALVIEW_TC11MP_PRIV_MEM_SIZE SZ_8K
#define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */
#define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */
#define REALVIEW_TC11MP_TWD_BASE 0x1F000600
static struct map_desc realview_eb11mp_io_desc[] __initdata = {
{
- .virtual = IO_ADDRESS(REALVIEW_EB11MP_SCU_BASE),
- .pfn = __phys_to_pfn(REALVIEW_EB11MP_SCU_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
- .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
- .length = SZ_4K,
+ .virtual = IO_ADDRESS(REALVIEW_EB11MP_PRIV_MEM_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_EB11MP_PRIV_MEM_BASE),
+ .length = REALVIEW_EB11MP_PRIV_MEM_SIZE,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
.pfn = __phys_to_pfn(REALVIEW_PB11MP_GIC_DIST_BASE),
.length = SZ_4K,
.type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_CPU_BASE),
- .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_CPU_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_DIST_BASE),
- .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_DIST_BASE),
- .length = SZ_4K,
+ }, { /* Maps the SCU, GIC CPU interface, TWD, GIC DIST */
+ .virtual = IO_ADDRESS(REALVIEW_TC11MP_PRIV_MEM_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_TC11MP_PRIV_MEM_BASE),
+ .length = REALVIEW_TC11MP_PRIV_MEM_SIZE,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
static struct mcp_plat_data assabet_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init assabet_init(void)
sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
ARRAY_SIZE(assabet_flash_resources));
sa11x0_register_irda(&assabet_irda_data);
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
- ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
sa11x0_register_mcp(&assabet_mcp_data);
}
static struct mcp_plat_data cerf_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init cerf_init(void)
{
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&cerf_mcp_data);
}
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
#include <mach/hardware.h>
-struct clkops {
- void (*enable)(struct clk *);
- void (*disable)(struct clk *);
- unsigned long (*getrate)(struct clk *);
-};
-
+/*
+ * Very simple clock implementation - we only have one clock to deal with.
+ */
struct clk {
- const struct clkops *ops;
- unsigned long rate;
unsigned int enabled;
};
-#define INIT_CLKREG(_clk, _devname, _conname) \
- { \
- .clk = _clk, \
- .dev_id = _devname, \
- .con_id = _conname, \
- }
-
-#define DEFINE_CLK(_name, _ops, _rate) \
-struct clk clk_##_name = { \
- .ops = _ops, \
- .rate = _rate, \
- }
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void clk_gpio27_enable(struct clk *clk)
+static void clk_gpio27_enable(void)
{
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
TUCR = TUCR_3_6864MHz;
}
-static void clk_gpio27_disable(struct clk *clk)
+static void clk_gpio27_disable(void)
{
TUCR = 0;
GPDR &= ~GPIO_32_768kHz;
GAFR &= ~GPIO_32_768kHz;
}
+static struct clk clk_gpio27;
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ const char *devname = dev_name(dev);
+
+ return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
int clk_enable(struct clk *clk)
{
unsigned long flags;
spin_lock_irqsave(&clocks_lock, flags);
if (clk->enabled++ == 0)
- clk->ops->enable(clk);
+ clk_gpio27_enable();
spin_unlock_irqrestore(&clocks_lock, flags);
-
return 0;
}
EXPORT_SYMBOL(clk_enable);
spin_lock_irqsave(&clocks_lock, flags);
if (--clk->enabled == 0)
- clk->ops->disable(clk);
+ clk_gpio27_disable();
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
- unsigned long rate;
-
- rate = clk->rate;
- if (clk->ops->getrate)
- rate = clk->ops->getrate(clk);
-
- return rate;
+ return 3686400;
}
EXPORT_SYMBOL(clk_get_rate);
-
-const struct clkops clk_gpio27_ops = {
- .enable = clk_gpio27_enable,
- .disable = clk_gpio27_disable,
-};
-
-static void clk_dummy_enable(struct clk *clk) { }
-static void clk_dummy_disable(struct clk *clk) { }
-
-const struct clkops clk_dummy_ops = {
- .enable = clk_dummy_enable,
- .disable = clk_dummy_disable,
-};
-
-static DEFINE_CLK(gpio27, &clk_gpio27_ops, 3686400);
-static DEFINE_CLK(dummy, &clk_dummy_ops, 0);
-
-static struct clk_lookup sa11xx_clkregs[] = {
- INIT_CLKREG(&clk_gpio27, "sa1111.0", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
-};
-
-static int __init sa11xx_clk_init(void)
-{
- clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
- return 0;
-}
-
-postcore_initcall(sa11xx_clk_init);
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/pda_power.h>
-#include <linux/mfd/ucb1x00.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
.num_devs = 1,
};
-static struct ucb1x00_plat_data collie_ucb1x00_data = {
- .gpio_base = COLLIE_TC35143_GPIO_BASE,
-};
-
static struct mcp_plat_data collie_mcp_data = {
.mccr0 = MCCR0_ADM | MCCR0_ExtClk,
.sclk_rate = 9216000,
- .codec = "ucb1x00",
- .codec_pdata = &collie_ucb1x00_data,
+ .gpio_base = COLLIE_TC35143_GPIO_BASE,
};
/*
static struct resource collie_power_resource[] = {
{
.name = "ac",
- .start = gpio_to_irq(COLLIE_GPIO_AC_IN),
- .end = gpio_to_irq(COLLIE_GPIO_AC_IN),
.flags = IORESOURCE_IRQ |
IORESOURCE_IRQ_HIGHEDGE |
IORESOURCE_IRQ_LOWEDGE,
GPSR |= _COLLIE_GPIO_UCB1x00_RESET;
-
+ collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN);
+ collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN);
platform_scoop_config = &collie_pcmcia_config;
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
ARRAY_SIZE(collie_flash_resources));
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&collie_mcp_data);
sharpsl_save_param();
return 0;
}
-static struct cpufreq_driver sa1100_driver = {
+static struct cpufreq_driver sa1100_driver __refdata = {
.flags = CPUFREQ_STICKY,
.verify = sa11x0_verify_speed,
.target = sa1100_target,
static struct resource sa11x0mcp_resources[] = {
[0] = {
.start = __PREG(Ser4MCCR0),
- .end = __PREG(Ser4MCCR0) + 0x1C - 1,
+ .end = __PREG(Ser4MCCR0) + 0xffff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = __PREG(Ser4MCCR1),
- .end = __PREG(Ser4MCCR1) + 0x4 - 1,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
.start = IRQ_Ser4MCP,
.end = IRQ_Ser4MCP,
.flags = IORESOURCE_IRQ,
sa11x0_register_device(&sa11x0ir_device, irda);
}
-static struct resource sa11x0rtc_resources[] = {
- [0] = {
- .start = 0x90010000,
- .end = 0x900100ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_RTC1Hz,
- .end = IRQ_RTC1Hz,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_RTCAlrm,
- .end = IRQ_RTCAlrm,
- .flags = IORESOURCE_IRQ,
- },
-};
-
static struct platform_device sa11x0rtc_device = {
.name = "sa1100-rtc",
.id = -1,
- .resource = sa11x0rtc_resources,
- .num_resources = ARRAY_SIZE(sa11x0rtc_resources),
};
static struct platform_device *sa11x0_devices[] __initdata = {
u32 mccr1;
unsigned int sclk_rate;
int gpio_base;
- const char *codec;
- void *codec_pdata;
};
#endif
{
return platform_driver_register(&jornadassp_driver);
}
+
+module_init(jornada_ssp_init);
static struct mcp_plat_data lart_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init lart_init(void)
{
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&lart_mcp_data);
}
static struct mcp_plat_data shannon_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init shannon_init(void)
{
sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1);
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&shannon_mcp_data);
}
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/mfd/ucb1x00.h>
#include <asm/irq.h>
#include <mach/hardware.h>
}
};
-static struct ucb1x00_plat_data simpad_ucb1x00_data = {
- .gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
-};
-
static struct mcp_plat_data simpad_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1300",
- .codec_pdata = &simpad_ucb1x00_data,
+ .gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
};
sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
ARRAY_SIZE(simpad_flash_resources));
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&simpad_mcp_data);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
#include <linux/delay.h>
#include <mach/common.h>
#include <mach/r8a7779.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <mach/common.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
select HAS_MTU
select ARM_ERRATA_753970
select ARM_ERRATA_754322
+ select ARM_ERRATA_764369
menu "Ux500 SoC"
void __init snowball_sdi_init(void)
{
+ /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
+ mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED;
/* On-board eMMC */
db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
/* External Micro SD slot */
static void __iomem *l2x0_base;
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
- /* wait for the operation to complete */
- while (readl_relaxed(reg) & mask)
- cpu_relax();
-}
-
-static inline void ux500_cache_sync(void)
-{
- writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
- ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
- uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
-
- /* invalidate all ways */
- writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
- ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
- ux500_cache_sync();
-}
-
static int __init ux500_l2x0_unlock(void)
{
int i;
/* 64KB way size, 8 way associativity, force WA */
l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
- /* Override invalidate function */
- outer_cache.disable = ux500_l2x0_disable;
- outer_cache.inv_all = ux500_l2x0_inv_all;
+ /*
+ * We can't disable l2 as we are in non secure mode, currently
+ * this seems be called only during kexec path. So let's
+ * override outer.disable with nasty assignment until we have
+ * some SMI service available.
+ */
+ outer_cache.disable = NULL;
return 0;
}
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
extern volatile int pen_release;
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
#include <mach/setup.h>
};
static struct musb_hdrc_platform_data musb_platform_data = {
-#if defined(CONFIG_USB_MUSB_OTG)
.mode = MUSB_OTG,
-#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
- .mode = MUSB_PERIPHERAL,
-#else /* defined(CONFIG_USB_MUSB_HOST) */
- .mode = MUSB_HOST,
-#endif
.config = &musb_hdrc_config,
.board_data = &musb_board_data,
};
}
#ifdef CONFIG_SMP
-static void ct_ca9x4_init_cpu_map(void)
+static void __init ct_ca9x4_init_cpu_map(void)
{
int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
set_smp_cross_call(gic_raise_softirq);
}
-static void ct_ca9x4_smp_enable(unsigned int max_cpus)
+static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
{
scu_enable(MMIO_P2V(A9_MPCORE_SCU));
}
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/system.h>
extern volatile int pen_release;
config ARM_L1_CACHE_SHIFT_6
bool
+ default y if CPU_V7
help
Setting ARM L1 cache line size to 64 Bytes.
static bool arm_memblock_steal_permitted = true;
-phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
+phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
{
phys_addr_t phys;
if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))
continue;
if (__phys_to_pfn(area->phys_addr) > pfn ||
- __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)
+ __pfn_to_phys(pfn) + offset + size-1 >
+ area->phys_addr + area->size-1)
continue;
/* we can drop the lock here as we know *area is static */
read_unlock(&vmlist_lock);
* Initialise TLB, Caches, and MMU state ready to switch the MMU
* on. Return in r0 the new CP15 C1 control register setting.
*
- * We automatically detect if we have a Harvard cache, and use the
- * Harvard cache control instructions insead of the unified cache
- * control instructions.
- *
* This should be able to cover all ARMv7 cores.
*
* It is assumed that:
#endif
3: mov r10, #0
-#ifdef HARVARD_CACHE
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
-#endif
dsb
#ifdef CONFIG_MMU
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
__v7_proc __v7_ca5mp_setup
.size __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
- /*
- * ARM Ltd. Cortex A7 processor.
- */
- .type __v7_ca7mp_proc_info, #object
-__v7_ca7mp_proc_info:
- .long 0x410fc070
- .long 0xff0ffff0
- __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
- .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
-
/*
* ARM Ltd. Cortex A9 processor.
*/
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
#endif /* CONFIG_ARM_LPAE */
+ /*
+ * ARM Ltd. Cortex A7 processor.
+ */
+ .type __v7_ca7mp_proc_info, #object
+__v7_ca7mp_proc_info:
+ .long 0x410fc070
+ .long 0xff0ffff0
+ __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
+ .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
+
/*
* ARM Ltd. Cortex A15 processor.
*/
and ARMv5 SoCs
config ARCH_IMX_V6_V7
- bool "i.MX3, i.MX6"
+ bool "i.MX3, i.MX5, i.MX6"
select AUTO_ZRELADDR if !ZBOOT_ROM
select ARM_PATCH_PHYS_VIRT
select MIGHT_HAVE_CACHE_L2X0
help
- This enables support for systems based on the Freescale i.MX3 and i.MX6
- family.
-
-config ARCH_MX5
- bool "i.MX50, i.MX51, i.MX53"
- select AUTO_ZRELADDR if !ZBOOT_ROM
- select ARM_PATCH_PHYS_VIRT
- help
- This enables support for machines using Freescale's i.MX50 and i.MX53
- processors.
+ This enables support for systems based on the Freescale i.MX3, i.MX5
+ and i.MX6 family.
endchoice
source "arch/arm/mach-imx/Kconfig"
-source "arch/arm/mach-mx5/Kconfig"
endmenu
extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
const char *label);
-extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
+extern int imx_iomuxv1_init(void __iomem *base, int numports);
#endif /* __MACH_IOMUX_V1_H__ */
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/hardware/gic.h>
/*
* FDC val = 4 -> Supervisor only */
asm volatile ("\n"
" .chip 68030\n"
- " pmove %0@,%/tt1\n"
+ " pmove %0,%/tt1\n"
" .chip 68k"
- : : "a" (&tt1_val));
+ : : "m" (tt1_val));
} else {
asm volatile ("\n"
" .chip 68040\n"
: "d0");
} else
asm volatile ("\n"
- " pmove %0@,%%tc\n"
+ " pmove %0,%%tc\n"
" jmp %1@"
: /* no outputs */
- : "a" (&tc_val), "a" (reset_addr));
+ : "m" (tc_val), "a" (reset_addr));
}
#define IRQ_USER 8
-/*
- * various flags for request_irq() - the Amiga now uses the standard
- * mechanism like all other architectures - IRQF_DISABLED and
- * IRQF_SHARED are your friends.
- */
-#ifndef MACH_AMIGA_ONLY
-#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
-#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
-#define IRQ_FLG_FAST (0x0004)
-#define IRQ_FLG_SLOW (0x0008)
-#define IRQ_FLG_STD (0x8000) /* internally used */
-#endif
-
struct irq_data;
struct irq_chip;
struct irq_desc;
current->thread.fs = __USER_DS;
if (!FPU_IS_EMU)
- asm volatile ("frestore %0@" : : "a" (&zero) : "memory");
+ asm volatile("frestore %0": :"m" (zero));
}
/*
#ifdef CONFIG_FPU
if (!FPU_IS_EMU)
asm volatile (".chip 68k/68881\n\t"
- "frestore %0@\n\t"
- ".chip 68k" : : "a" (&zero));
+ "frestore %0\n\t"
+ ".chip 68k" : : "m" (zero));
#endif
}
#ifdef DEBUG
asm volatile ("ptestr %3,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (desc)
- : "a" (&temp), "a" (addr), "d" (ssw));
+ "pmove %%psr,%1"
+ : "=a&" (desc), "=m" (temp)
+ : "a" (addr), "d" (ssw));
#else
asm volatile ("ptestr %2,%1@,#7\n\t"
- "pmove %%psr,%0@"
- : : "a" (&temp), "a" (addr), "d" (ssw));
+ "pmove %%psr,%0"
+ : "=m" (temp) : "a" (addr), "d" (ssw));
#endif
mmusr = temp;
!(ssw & RW) ? "write" : "read", addr,
fp->ptregs.pc, ssw);
asm volatile ("ptestr #1,%1@,#0\n\t"
- "pmove %%psr,%0@"
- : /* no outputs */
- : "a" (&temp), "a" (addr));
+ "pmove %%psr,%0"
+ : "=m" (temp)
+ : "a" (addr));
mmusr = temp;
printk ("level 0 mmusr is %#x\n", mmusr);
#if 0
- asm volatile ("pmove %%tt0,%0@"
- : /* no outputs */
- : "a" (&tlong));
+ asm volatile ("pmove %%tt0,%0"
+ : "=m" (tlong));
printk("tt0 is %#lx, ", tlong);
- asm volatile ("pmove %%tt1,%0@"
- : /* no outputs */
- : "a" (&tlong));
+ asm volatile ("pmove %%tt1,%0"
+ : "=m" (tlong));
printk("tt1 is %#lx\n", tlong);
#endif
#ifdef DEBUG
#ifdef DEBUG
asm volatile ("ptestr #1,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (desc)
- : "a" (&temp), "a" (addr));
+ "pmove %%psr,%1"
+ : "=a&" (desc), "=m" (temp)
+ : "a" (addr));
#else
asm volatile ("ptestr #1,%1@,#7\n\t"
- "pmove %%psr,%0@"
- : : "a" (&temp), "a" (addr));
+ "pmove %%psr,%0"
+ : "=m" (temp) : "a" (addr));
#endif
mmusr = temp;
unsigned long *descaddr;
asm volatile ("ptestr %3,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (descaddr)
- : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg));
+ "pmove %%psr,%1"
+ : "=a&" (descaddr), "=m" (mmusr)
+ : "a" (vaddr), "d" (get_fs().seg));
if (mmusr & (MMU_I|MMU_B|MMU_L))
return 0;
descaddr = phys_to_virt((unsigned long)descaddr);
select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP
select GENERIC_CPU_DEVICES
+ select GENERIC_ATOMIC64
config SWAP
def_bool n
#define _ASM_MICROBLAZE_ATOMIC_H
#include <asm-generic/atomic.h>
+#include <asm-generic/atomic64.h>
/*
* Atomically test *v and decrement if it is greater than 0.
};
/include/ "pq3-esdhc-0.dtsi"
+ sdhc@2e000 {
+ compatible = "fsl,mpc8536-esdhc", "fsl,esdhc";
+ };
+
/include/ "pq3-sec3.0-0.dtsi"
/include/ "pq3-mpic.dtsi"
/include/ "pq3-mpic-timer-B.dtsi"
/include/ "pq3-usb2-dr-0.dtsi"
/include/ "pq3-esdhc-0.dtsi"
sdhc@2e000 {
- fsl,sdhci-auto-cmd12;
+ compatible = "fsl,p1010-esdhc", "fsl,esdhc";
+ sdhci,auto-cmd12;
};
/include/ "pq3-sec4.4-0.dtsi"
/include/ "pq3-usb2-dr-1.dtsi"
/include/ "pq3-esdhc-0.dtsi"
+ sdhc@2e000 {
+ compatible = "fsl,p1020-esdhc", "fsl,esdhc";
+ sdhci,auto-cmd12;
+ };
/include/ "pq3-sec3.3-0.dtsi"
/include/ "pq3-mpic.dtsi"
/include/ "pq3-esdhc-0.dtsi"
sdhc@2e000 {
- fsl,sdhci-auto-cmd12;
+ compatible = "fsl,p1022-esdhc", "fsl,esdhc";
+ sdhci,auto-cmd12;
};
/include/ "pq3-sec3.3-0.dtsi"
/include/ "pq3-etsec1-1.dtsi"
/include/ "pq3-etsec1-2.dtsi"
/include/ "pq3-esdhc-0.dtsi"
+ sdhc@2e000 {
+ compatible = "fsl,p2020-esdhc", "fsl,esdhc";
+ };
+
/include/ "pq3-sec3.1-0.dtsi"
/include/ "pq3-mpic.dtsi"
/include/ "pq3-mpic-timer-B.dtsi"
/*
* P1020 RDB Device Tree Source stub (no addresses or top-level ranges)
*
- * Copyright 2011 Freescale Semiconductor Inc.
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
usb@22000 {
phy_type = "ulpi";
+ dr_mode = "host";
};
- /* USB2 is shared with localbus, so it must be disabled
- by default. We can't put 'status = "disabled";' here
- since U-Boot doesn't clear the status property when
- it enables USB2. OTOH, U-Boot does create a new node
- when there isn't any. So, just comment it out.
+ /* USB2 is shared with localbus. It is used
+ only in case of SPI and SD boot after
+ appropriate device-tree fixup done by uboot */
usb@23000 {
phy_type = "ulpi";
+ dr_mode = "host";
};
- */
mdio@24000 {
phy0: ethernet-phy@0 {
/*
* P1021 MDS Device Tree Source
*
- * Copyright 2010 Freescale Semiconductor Inc.
+ * Copyright 2010,2012 Freescale Semiconductor Inc.
*
* 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
usb@22000 {
phy_type = "ulpi";
+ dr_mode = "host";
};
mdio@24000 {
/*
* P2020DS Device Tree Source stub (no addresses or top-level ranges)
*
- * Copyright 2011 Freescale Semiconductor Inc.
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
&board_soc {
usb@22000 {
phy_type = "ulpi";
+ dr_mode = "host";
};
mdio@24520 {
/*
* P2020 RDB Device Tree Source
*
- * Copyright 2009-2011 Freescale Semiconductor Inc.
+ * Copyright 2009-2012 Freescale Semiconductor Inc.
*
* 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
usb@22000 {
phy_type = "ulpi";
+ dr_mode = "host";
};
mdio@24520 {
/* This keeps a track of which one is the crashing cpu. */
int crashing_cpu = -1;
-static atomic_t cpus_in_crash;
static int time_to_dump;
#define CRASH_HANDLER_MAX 3
#ifdef CONFIG_SMP
+static atomic_t cpus_in_crash;
void crash_ipi_callback(struct pt_regs *regs)
{
static cpumask_t cpus_state_saved = CPU_MASK_NONE;
port->irq = virq;
+#ifdef CONFIG_SERIAL_8250_FSL
if (of_device_is_compatible(np, "fsl,ns16550"))
port->handle_irq = fsl8250_handle_irq;
+#endif
}
static void __init fixup_port_pio(int index,
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#include <asm/udbg.h>
#include <asm/fsl_guts.h>
#include "smp.h"
pr_devel(" -> OBR %s [%x] +%016llx\n",
bus->self ? pci_name(bus->self) : "root", flags, offset);
- for (i = 0; i < 2; i++) {
- r = bus->resource[i];
+ pci_bus_for_each_resource(bus, r, i) {
if (r && (r->flags & flags)) {
- bus->resource[i]->start += offset;
- bus->resource[i]->end += offset;
+ r->start += offset;
+ r->end += offset;
}
}
list_for_each_entry(dev, &bus->devices, bus_list)
* assignment algorithm is going to be uber-trivial for now, we
* can try to be smarter later at filling out holes.
*/
- start = bus->self ? 0 : bus->resource[bres]->start;
-
- /* Don't hand out IO 0 */
- if ((flags & IORESOURCE_IO) && !bus->self)
- start += 0x1000;
-
+ if (bus->self) {
+ /* No offset for downstream bridges */
+ start = 0;
+ } else {
+ /* Offset from the root */
+ if (flags & IORESOURCE_IO)
+ /* Don't hand out IO 0 */
+ start = hose->io_resource.start + 0x1000;
+ else
+ start = hose->mem_resources[0].start;
+ }
while(!list_empty(&head)) {
w = list_first_entry(&head, struct resource_wrap, link);
list_del(&w->link);
empty:
/* Only setup P2P's, not the PHB itself */
if (bus->self) {
- WARN_ON(bus->resource[bres] == NULL);
- bus->resource[bres]->start = 0;
- bus->resource[bres]->flags = (*size) ? flags : 0;
- bus->resource[bres]->end = (*size) ? (*size - 1) : 0;
+ struct resource *res = bus->resource[bres];
+
+ if (WARN_ON(res == NULL))
+ return;
- /* Clear prefetch bus resources for now */
- bus->resource[2]->flags = 0;
+ /*
+ * FIXME: We should probably export and call
+ * pci_bridge_check_ranges() to properly re-initialize
+ * the PCI portion of the flags here, and to detect
+ * what the bridge actually supports.
+ */
+ res->start = 0;
+ res->flags = (*size) ? flags : 0;
+ res->end = (*size) ? (*size - 1) : 0;
}
pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n",
Say N if you are unsure.
config PSERIES_IDLE
- tristate "Cpuidle driver for pSeries platforms"
+ bool "Cpuidle driver for pSeries platforms"
depends on CPU_IDLE
depends on PPC_PSERIES
default y
if (paddr_hi == paddr_lo) {
pr_err("%s: No outbound window space\n", name);
- return ;
+ goto out;
}
if (paddr_lo == 0) {
pr_err("%s: No space for inbound window\n", name);
- return ;
+ goto out;
}
/* setup PCSRBAR/PEXCSRBAR */
(u64)hose->dma_window_size);
}
+out:
iounmap(pci);
}
KBUILD_AFLAGS += $(aflags-y)
OBJCOPYFLAGS := -O binary
-LDFLAGS_vmlinux := -e start
head-y := arch/s390/kernel/head.o
head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_S390
+/*
+ * Size for s390x ELF notes per CPU
+ *
+ * Seven notes plus zero note at the end: prstatus, fpregset, timer,
+ * tod_cmp, tod_reg, control regs, and prefix
+ */
+#define KEXEC_NOTE_BYTES \
+ (ALIGN(sizeof(struct elf_note), 4) * 8 + \
+ ALIGN(sizeof("CORE"), 4) * 7 + \
+ ALIGN(sizeof(struct elf_prstatus), 4) + \
+ ALIGN(sizeof(elf_fpregset_t), 4) + \
+ ALIGN(sizeof(u64), 4) + \
+ ALIGN(sizeof(u64), 4) + \
+ ALIGN(sizeof(u32), 4) + \
+ ALIGN(sizeof(u64) * 16, 4) + \
+ ALIGN(sizeof(u32), 4) \
+ )
+
/* Provide a dummy definition to avoid build failures. */
static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) { }
#ifndef CONFIG_64BIT
OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
OUTPUT_ARCH(s390)
-ENTRY(_start)
+ENTRY(startup)
jiffies = jiffies_64 + 4;
#else
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
OUTPUT_ARCH(s390:64-bit)
-ENTRY(_start)
+ENTRY(startup)
jiffies = jiffies_64;
#endif
sw r9, [r0, PT_EPC]
cmpi.c r27, __NR_syscalls # check syscall number
- bgtu illegal_syscall
+ bgeu illegal_syscall
slli r8, r27, 2 # get syscall routine
la r11, sys_call_table
timers_global = (void __iomem *)
(unsigned long) addr[num_cpu_timers];
+ /* Every per-cpu timer works in timer mode */
+ sbus_writel(0x00000000, &timers_global->timer_config);
+
sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
master_l10_counter = &timers_global->l10_count;
depends on NUMA
depends on SMP
depends on X86_X2APIC
- depends on !EDAC_AMD64
---help---
Adds support for Numascale NumaChip large-SMP systems. Needed to
enable more than ~168 cores.
default: /* Ignore other PT_* */ break;
}
}
+
+ free(phdrs);
}
asmlinkage void decompress_kernel(void *rmode, memptr heap,
#define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */
#define X86_FEATURE_LWP (6*32+15) /* Light Weight Profiling */
#define X86_FEATURE_FMA4 (6*32+16) /* 4 operands MAC instructions */
+#define X86_FEATURE_TCE (6*32+17) /* translation cache extension */
#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
/* UV global physical address --> socket phys RAM */
static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
{
- unsigned long paddr = gpa & uv_hub_info->gpa_mask;
+ unsigned long paddr;
unsigned long remap_base = uv_hub_info->lowmem_remap_base;
unsigned long remap_top = uv_hub_info->lowmem_remap_top;
gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
- gpa = gpa & uv_hub_info->gpa_mask;
+ paddr = gpa & uv_hub_info->gpa_mask;
if (paddr >= remap_base && paddr < remap_base + remap_top)
paddr -= remap_base;
return paddr;
return state;
}
+/*
+ * AMD microcode firmware naming convention, up to family 15h they are in
+ * the legacy file:
+ *
+ * amd-ucode/microcode_amd.bin
+ *
+ * This legacy file is always smaller than 2K in size.
+ *
+ * Starting at family 15h they are in family specific firmware files:
+ *
+ * amd-ucode/microcode_amd_fam15h.bin
+ * amd-ucode/microcode_amd_fam16h.bin
+ * ...
+ *
+ * These might be larger than 2K.
+ */
static enum ucode_state request_microcode_amd(int cpu, struct device *device)
{
- const char *fw_name = "amd-ucode/microcode_amd.bin";
+ char fw_name[36] = "amd-ucode/microcode_amd.bin";
const struct firmware *fw;
enum ucode_state ret = UCODE_NFOUND;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+ if (c->x86 >= 0x15)
+ snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
- if (request_firmware(&fw, fw_name, device)) {
+ if (request_firmware(&fw, (const char *)fw_name, device)) {
pr_err("failed to load file %s\n", fw_name);
goto out;
}
cleanup_addr = proglen; /* epilogue address */
for (pass = 0; pass < 10; pass++) {
+ u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
/* no prologue/epilogue for trivial filters (RET something) */
proglen = 0;
prog = temp;
- if (seen) {
+ if (seen_or_pass0) {
EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */
EMIT4(0x48, 0x83, 0xec, 96); /* subq $96,%rsp */
/* note : must save %rbx in case bpf_error is hit */
- if (seen & (SEEN_XREG | SEEN_DATAREF))
+ if (seen_or_pass0 & (SEEN_XREG | SEEN_DATAREF))
EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */
- if (seen & SEEN_XREG)
+ if (seen_or_pass0 & SEEN_XREG)
CLEAR_X(); /* make sure we dont leek kernel memory */
/*
* r9 = skb->len - skb->data_len
* r8 = skb->data
*/
- if (seen & SEEN_DATAREF) {
+ if (seen_or_pass0 & SEEN_DATAREF) {
if (offsetof(struct sk_buff, len) <= 127)
/* mov off8(%rdi),%r9d */
EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len));
case BPF_S_ALU_DIV_X: /* A /= X; */
seen |= SEEN_XREG;
EMIT2(0x85, 0xdb); /* test %ebx,%ebx */
- if (pc_ret0 != -1)
- EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4));
- else {
+ if (pc_ret0 > 0) {
+ /* addrs[pc_ret0 - 1] is start address of target
+ * (addrs[i] - 4) is the address following this jmp
+ * ("xor %edx,%edx; div %ebx" being 4 bytes long)
+ */
+ EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] -
+ (addrs[i] - 4));
+ } else {
EMIT_COND_JMP(X86_JNE, 2 + 5);
CLEAR_A();
EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */
}
/* fallinto */
case BPF_S_RET_A:
- if (seen) {
+ if (seen_or_pass0) {
if (i != flen - 1) {
EMIT_JMP(cleanup_addr - addrs[i]);
break;
}
- if (seen & SEEN_XREG)
+ if (seen_or_pass0 & SEEN_XREG)
EMIT4(0x48, 0x8b, 0x5d, 0xf8); /* mov -8(%rbp),%rbx */
EMIT1(0xc9); /* leaveq */
}
goto common_load;
case BPF_S_LDX_B_MSH:
if ((int)K < 0) {
- if (pc_ret0 != -1) {
- EMIT_JMP(addrs[pc_ret0] - addrs[i]);
+ if (pc_ret0 > 0) {
+ /* addrs[pc_ret0 - 1] is the start address */
+ EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]);
break;
}
CLEAR_A();
* use it to give the cleanup instruction(s) addr
*/
cleanup_addr = proglen - 1; /* ret */
- if (seen)
+ if (seen_or_pass0)
cleanup_addr -= 1; /* leaveq */
- if (seen & SEEN_XREG)
+ if (seen_or_pass0 & SEEN_XREG)
cleanup_addr -= 4; /* mov -8(%rbp),%rbx */
if (image) {
- WARN_ON(proglen != oldproglen);
+ if (proglen != oldproglen)
+ pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n", proglen, oldproglen);
break;
}
if (proglen == oldproglen) {
bcp->cong_reps = congested_reps;
bcp->cong_period = congested_period;
bcp->clocks_per_100_usec = usec_2_cycles(100);
+ spin_lock_init(&bcp->queue_lock);
+ spin_lock_init(&bcp->uvhub_lock);
}
}
int irq;
};
-static spinlock_t uv_irq_lock;
+static DEFINE_SPINLOCK(uv_irq_lock);
static struct rb_root uv_irq_root;
static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
}
#endif /* CONFIG_XEN_DEBUG_FS */
+/*
+ * Size struct xen_spinlock so it's the same as arch_spinlock_t.
+ */
+#if NR_CPUS < 256
+typedef u8 xen_spinners_t;
+# define inc_spinners(xl) \
+ asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory");
+# define dec_spinners(xl) \
+ asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory");
+#else
+typedef u16 xen_spinners_t;
+# define inc_spinners(xl) \
+ asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory");
+# define dec_spinners(xl) \
+ asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory");
+#endif
+
struct xen_spinlock {
unsigned char lock; /* 0 -> free; 1 -> locked */
- unsigned short spinners; /* count of waiting cpus */
+ xen_spinners_t spinners; /* count of waiting cpus */
};
static int xen_spin_is_locked(struct arch_spinlock *lock)
wmb(); /* set lock of interest before count */
- asm(LOCK_PREFIX " incw %0"
- : "+m" (xl->spinners) : : "memory");
+ inc_spinners(xl);
return prev;
}
*/
static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock *prev)
{
- asm(LOCK_PREFIX " decw %0"
- : "+m" (xl->spinners) : : "memory");
+ dec_spinners(xl);
wmb(); /* decrement count before restoring lock */
__this_cpu_write(lock_spinners, prev);
}
void __init xen_init_spinlocks(void)
{
+ BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t));
+
pv_lock_ops.spin_is_locked = xen_spin_is_locked;
pv_lock_ops.spin_is_contended = xen_spin_is_contended;
pv_lock_ops.spin_lock = xen_spin_lock;
#include <linux/percpu.h>
#include <asm/byteorder.h>
-static DEFINE_PER_CPU(u64[80], msg_schedule);
-
static inline u64 Ch(u64 x, u64 y, u64 z)
{
return z ^ (x & (y ^ z));
static inline void BLEND_OP(int I, u64 *W)
{
- W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+ W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]);
}
static void
u64 a, b, c, d, e, f, g, h, t1, t2;
int i;
- u64 *W = get_cpu_var(msg_schedule);
+ u64 W[16];
/* load the input */
for (i = 0; i < 16; i++)
LOAD_OP(i, W, input);
- for (i = 16; i < 80; i++) {
- BLEND_OP(i, W);
- }
-
/* load the state into our registers */
a=state[0]; b=state[1]; c=state[2]; d=state[3];
e=state[4]; f=state[5]; g=state[6]; h=state[7];
- /* now iterate */
- for (i=0; i<80; i+=8) {
- t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ];
- t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
- t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
- t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
- t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
- t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
- t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
- t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
- t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
- t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
- t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
- t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
- t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
- t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
- t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
- t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+#define SHA512_0_15(i, a, b, c, d, e, f, g, h) \
+ t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i]; \
+ t2 = e0(a) + Maj(a, b, c); \
+ d += t1; \
+ h = t1 + t2
+
+#define SHA512_16_79(i, a, b, c, d, e, f, g, h) \
+ BLEND_OP(i, W); \
+ t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16]; \
+ t2 = e0(a) + Maj(a, b, c); \
+ d += t1; \
+ h = t1 + t2
+
+ for (i = 0; i < 16; i += 8) {
+ SHA512_0_15(i, a, b, c, d, e, f, g, h);
+ SHA512_0_15(i + 1, h, a, b, c, d, e, f, g);
+ SHA512_0_15(i + 2, g, h, a, b, c, d, e, f);
+ SHA512_0_15(i + 3, f, g, h, a, b, c, d, e);
+ SHA512_0_15(i + 4, e, f, g, h, a, b, c, d);
+ SHA512_0_15(i + 5, d, e, f, g, h, a, b, c);
+ SHA512_0_15(i + 6, c, d, e, f, g, h, a, b);
+ SHA512_0_15(i + 7, b, c, d, e, f, g, h, a);
+ }
+ for (i = 16; i < 80; i += 8) {
+ SHA512_16_79(i, a, b, c, d, e, f, g, h);
+ SHA512_16_79(i + 1, h, a, b, c, d, e, f, g);
+ SHA512_16_79(i + 2, g, h, a, b, c, d, e, f);
+ SHA512_16_79(i + 3, f, g, h, a, b, c, d, e);
+ SHA512_16_79(i + 4, e, f, g, h, a, b, c, d);
+ SHA512_16_79(i + 5, d, e, f, g, h, a, b, c);
+ SHA512_16_79(i + 6, c, d, e, f, g, h, a, b);
+ SHA512_16_79(i + 7, b, c, d, e, f, g, h, a);
}
state[0] += a; state[1] += b; state[2] += c; state[3] += d;
/* erase our data */
a = b = c = d = e = f = g = h = t1 = t2 = 0;
- memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
- put_cpu_var(msg_schedule);
}
static int
# All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o
-acpi-y += atomicio.o
acpi-y += nvs.o
# sleep related files
{
int rc;
u64 address;
- u32 tmp, width = reg->bit_width;
acpi_status status;
rc = apei_check_gar(reg, &address);
if (rc)
return rc;
- if (width == 64)
- width = 32; /* Break into two 32-bit transfers */
-
*val = 0;
switch(reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_read_memory((acpi_physical_address)
- address, &tmp, width);
+ status = acpi_os_read_memory64((acpi_physical_address)
+ address, val, reg->bit_width);
if (ACPI_FAILURE(status))
return -EIO;
- *val = tmp;
-
- if (reg->bit_width == 64) {
- /* Read the top 32 bits */
- status = acpi_os_read_memory((acpi_physical_address)
- (address + 4), &tmp, 32);
- if (ACPI_FAILURE(status))
- return -EIO;
- *val |= ((u64)tmp << 32);
- }
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
{
int rc;
u64 address;
- u32 width = reg->bit_width;
acpi_status status;
rc = apei_check_gar(reg, &address);
if (rc)
return rc;
- if (width == 64)
- width = 32; /* Break into two 32-bit transfers */
-
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_write_memory((acpi_physical_address)
- address, ACPI_LODWORD(val),
- width);
+ status = acpi_os_write_memory64((acpi_physical_address)
+ address, val, reg->bit_width);
if (ACPI_FAILURE(status))
return -EIO;
-
- if (reg->bit_width == 64) {
- status = acpi_os_write_memory((acpi_physical_address)
- (address + 4),
- ACPI_HIDWORD(val), 32);
- if (ACPI_FAILURE(status))
- return -EIO;
- }
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_os_write_port(address, val, reg->bit_width);
static void *einj_param;
-#ifndef readq
-static inline __u64 readq(volatile void __iomem *addr)
-{
- return ((__u64)readl(addr+4) << 32) + readl(addr);
-}
-#endif
-
-#ifndef writeq
-static inline void writeq(__u64 val, volatile void __iomem *addr)
-{
- writel(val, addr);
- writel(val >> 32, addr+4);
-}
-#endif
-
static void einj_exec_ctx_init(struct apei_exec_context *ctx)
{
apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type),
static void check_vendor_extension(u64 paddr,
struct set_error_type_with_address *v5param)
{
- int offset = readl(&v5param->vendor_extension);
+ int offset = v5param->vendor_extension;
struct vendor_error_type_extension *v;
u32 sbdf;
if (!offset)
return;
- v = ioremap(paddr + offset, sizeof(*v));
+ v = acpi_os_map_memory(paddr + offset, sizeof(*v));
if (!v)
return;
- sbdf = readl(&v->pcie_sbdf);
+ sbdf = v->pcie_sbdf;
sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
sbdf >> 24, (sbdf >> 16) & 0xff,
(sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
- readw(&v->vendor_id), readw(&v->device_id),
- readb(&v->rev_id));
- iounmap(v);
+ v->vendor_id, v->device_id, v->rev_id);
+ acpi_os_unmap_memory(v, sizeof(*v));
}
static void *einj_get_parameter_address(void)
if (paddrv5) {
struct set_error_type_with_address *v5param;
- v5param = ioremap(paddrv5, sizeof(*v5param));
+ v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param));
if (v5param) {
acpi5 = 1;
check_vendor_extension(paddrv5, v5param);
if (paddrv4) {
struct einj_parameter *v4param;
- v4param = ioremap(paddrv4, sizeof(*v4param));
+ v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
if (!v4param)
- return 0;
- if (readq(&v4param->reserved1) || readq(&v4param->reserved2)) {
- iounmap(v4param);
- return 0;
+ return NULL;
+ if (v4param->reserved1 || v4param->reserved2) {
+ acpi_os_unmap_memory(v4param, sizeof(*v4param));
+ return NULL;
}
return v4param;
}
- return 0;
+ return NULL;
}
/* do sanity check to trigger table */
if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
return -EINVAL;
if (trigger_tab->table_size > PAGE_SIZE ||
- trigger_tab->table_size <= trigger_tab->header_size)
+ trigger_tab->table_size < trigger_tab->header_size)
return -EINVAL;
if (trigger_tab->entry_count !=
(trigger_tab->table_size - trigger_tab->header_size) /
"The trigger error action table is invalid\n");
goto out_rel_header;
}
+
+ /* No action structures in the TRIGGER_ERROR table, nothing to do */
+ if (!trigger_tab->entry_count)
+ goto out_rel_header;
+
rc = -EIO;
table_size = trigger_tab->table_size;
r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
if (acpi5) {
struct set_error_type_with_address *v5param = einj_param;
- writel(type, &v5param->type);
+ v5param->type = type;
if (type & 0x80000000) {
switch (vendor_flags) {
case SETWA_FLAGS_APICID:
- writel(param1, &v5param->apicid);
+ v5param->apicid = param1;
break;
case SETWA_FLAGS_MEM:
- writeq(param1, &v5param->memory_address);
- writeq(param2, &v5param->memory_address_range);
+ v5param->memory_address = param1;
+ v5param->memory_address_range = param2;
break;
case SETWA_FLAGS_PCIE_SBDF:
- writel(param1, &v5param->pcie_sbdf);
+ v5param->pcie_sbdf = param1;
break;
}
- writel(vendor_flags, &v5param->flags);
+ v5param->flags = vendor_flags;
} else {
switch (type) {
case ACPI_EINJ_PROCESSOR_CORRECTABLE:
case ACPI_EINJ_PROCESSOR_UNCORRECTABLE:
case ACPI_EINJ_PROCESSOR_FATAL:
- writel(param1, &v5param->apicid);
- writel(SETWA_FLAGS_APICID, &v5param->flags);
+ v5param->apicid = param1;
+ v5param->flags = SETWA_FLAGS_APICID;
break;
case ACPI_EINJ_MEMORY_CORRECTABLE:
case ACPI_EINJ_MEMORY_UNCORRECTABLE:
case ACPI_EINJ_MEMORY_FATAL:
- writeq(param1, &v5param->memory_address);
- writeq(param2, &v5param->memory_address_range);
- writel(SETWA_FLAGS_MEM, &v5param->flags);
+ v5param->memory_address = param1;
+ v5param->memory_address_range = param2;
+ v5param->flags = SETWA_FLAGS_MEM;
break;
case ACPI_EINJ_PCIX_CORRECTABLE:
case ACPI_EINJ_PCIX_UNCORRECTABLE:
case ACPI_EINJ_PCIX_FATAL:
- writel(param1, &v5param->pcie_sbdf);
- writel(SETWA_FLAGS_PCIE_SBDF, &v5param->flags);
+ v5param->pcie_sbdf = param1;
+ v5param->flags = SETWA_FLAGS_PCIE_SBDF;
break;
}
}
return rc;
if (einj_param) {
struct einj_parameter *v4param = einj_param;
- writeq(param1, &v4param->param1);
- writeq(param2, &v4param->param2);
+ v4param->param1 = param1;
+ v4param->param2 = param2;
}
}
rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
return 0;
err_unmap:
- if (einj_param)
- iounmap(einj_param);
+ if (einj_param) {
+ acpi_size size = (acpi5) ?
+ sizeof(struct set_error_type_with_address) :
+ sizeof(struct einj_parameter);
+
+ acpi_os_unmap_memory(einj_param, size);
+ }
apei_exec_post_unmap_gars(&ctx);
err_release:
apei_resources_release(&einj_resources);
{
struct apei_exec_context ctx;
- if (einj_param)
- iounmap(einj_param);
+ if (einj_param) {
+ acpi_size size = (acpi5) ?
+ sizeof(struct set_error_type_with_address) :
+ sizeof(struct einj_parameter);
+
+ acpi_os_unmap_memory(einj_param, size);
+ }
einj_exec_ctx_init(&ctx);
apei_exec_post_unmap_gars(&ctx);
apei_resources_release(&einj_resources);
+++ /dev/null
-/*
- * atomicio.c - ACPI IO memory pre-mapping/post-unmapping, then
- * accessing in atomic context.
- *
- * This is used for NMI handler to access IO memory area, because
- * ioremap/iounmap can not be used in NMI handler. The IO memory area
- * is pre-mapped in process context and accessed in NMI handler.
- *
- * Copyright (C) 2009-2010, Intel Corp.
- * Author: Huang Ying <ying.huang@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/io.h>
-#include <linux/kref.h>
-#include <linux/rculist.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <acpi/atomicio.h>
-
-#define ACPI_PFX "ACPI: "
-
-static LIST_HEAD(acpi_iomaps);
-/*
- * Used for mutual exclusion between writers of acpi_iomaps list, for
- * synchronization between readers and writer, RCU is used.
- */
-static DEFINE_SPINLOCK(acpi_iomaps_lock);
-
-struct acpi_iomap {
- struct list_head list;
- void __iomem *vaddr;
- unsigned long size;
- phys_addr_t paddr;
- struct kref ref;
-};
-
-/* acpi_iomaps_lock or RCU read lock must be held before calling */
-static struct acpi_iomap *__acpi_find_iomap(phys_addr_t paddr,
- unsigned long size)
-{
- struct acpi_iomap *map;
-
- list_for_each_entry_rcu(map, &acpi_iomaps, list) {
- if (map->paddr + map->size >= paddr + size &&
- map->paddr <= paddr)
- return map;
- }
- return NULL;
-}
-
-/*
- * Atomic "ioremap" used by NMI handler, if the specified IO memory
- * area is not pre-mapped, NULL will be returned.
- *
- * acpi_iomaps_lock or RCU read lock must be held before calling
- */
-static void __iomem *__acpi_ioremap_fast(phys_addr_t paddr,
- unsigned long size)
-{
- struct acpi_iomap *map;
-
- map = __acpi_find_iomap(paddr, size/8);
- if (map)
- return map->vaddr + (paddr - map->paddr);
- else
- return NULL;
-}
-
-/* acpi_iomaps_lock must be held before calling */
-static void __iomem *__acpi_try_ioremap(phys_addr_t paddr,
- unsigned long size)
-{
- struct acpi_iomap *map;
-
- map = __acpi_find_iomap(paddr, size);
- if (map) {
- kref_get(&map->ref);
- return map->vaddr + (paddr - map->paddr);
- } else
- return NULL;
-}
-
-#ifndef CONFIG_IA64
-#define should_use_kmap(pfn) page_is_ram(pfn)
-#else
-/* ioremap will take care of cache attributes */
-#define should_use_kmap(pfn) 0
-#endif
-
-static void __iomem *acpi_map(phys_addr_t pg_off, unsigned long pg_sz)
-{
- unsigned long pfn;
-
- pfn = pg_off >> PAGE_SHIFT;
- if (should_use_kmap(pfn)) {
- if (pg_sz > PAGE_SIZE)
- return NULL;
- return (void __iomem __force *)kmap(pfn_to_page(pfn));
- } else
- return ioremap(pg_off, pg_sz);
-}
-
-static void acpi_unmap(phys_addr_t pg_off, void __iomem *vaddr)
-{
- unsigned long pfn;
-
- pfn = pg_off >> PAGE_SHIFT;
- if (page_is_ram(pfn))
- kunmap(pfn_to_page(pfn));
- else
- iounmap(vaddr);
-}
-
-/*
- * Used to pre-map the specified IO memory area. First try to find
- * whether the area is already pre-mapped, if it is, increase the
- * reference count (in __acpi_try_ioremap) and return; otherwise, do
- * the real ioremap, and add the mapping into acpi_iomaps list.
- */
-static void __iomem *acpi_pre_map(phys_addr_t paddr,
- unsigned long size)
-{
- void __iomem *vaddr;
- struct acpi_iomap *map;
- unsigned long pg_sz, flags;
- phys_addr_t pg_off;
-
- spin_lock_irqsave(&acpi_iomaps_lock, flags);
- vaddr = __acpi_try_ioremap(paddr, size);
- spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
- if (vaddr)
- return vaddr;
-
- pg_off = paddr & PAGE_MASK;
- pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off;
- vaddr = acpi_map(pg_off, pg_sz);
- if (!vaddr)
- return NULL;
- map = kmalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
- goto err_unmap;
- INIT_LIST_HEAD(&map->list);
- map->paddr = pg_off;
- map->size = pg_sz;
- map->vaddr = vaddr;
- kref_init(&map->ref);
-
- spin_lock_irqsave(&acpi_iomaps_lock, flags);
- vaddr = __acpi_try_ioremap(paddr, size);
- if (vaddr) {
- spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
- acpi_unmap(pg_off, map->vaddr);
- kfree(map);
- return vaddr;
- }
- list_add_tail_rcu(&map->list, &acpi_iomaps);
- spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-
- return map->vaddr + (paddr - map->paddr);
-err_unmap:
- acpi_unmap(pg_off, vaddr);
- return NULL;
-}
-
-/* acpi_iomaps_lock must be held before calling */
-static void __acpi_kref_del_iomap(struct kref *ref)
-{
- struct acpi_iomap *map;
-
- map = container_of(ref, struct acpi_iomap, ref);
- list_del_rcu(&map->list);
-}
-
-/*
- * Used to post-unmap the specified IO memory area. The iounmap is
- * done only if the reference count goes zero.
- */
-static void acpi_post_unmap(phys_addr_t paddr, unsigned long size)
-{
- struct acpi_iomap *map;
- unsigned long flags;
- int del;
-
- spin_lock_irqsave(&acpi_iomaps_lock, flags);
- map = __acpi_find_iomap(paddr, size);
- BUG_ON(!map);
- del = kref_put(&map->ref, __acpi_kref_del_iomap);
- spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-
- if (!del)
- return;
-
- synchronize_rcu();
- acpi_unmap(map->paddr, map->vaddr);
- kfree(map);
-}
-
-/* In NMI handler, should set silent = 1 */
-static int acpi_check_gar(struct acpi_generic_address *reg,
- u64 *paddr, int silent)
-{
- u32 width, space_id;
-
- width = reg->bit_width;
- space_id = reg->space_id;
- /* Handle possible alignment issues */
- memcpy(paddr, ®->address, sizeof(*paddr));
- if (!*paddr) {
- if (!silent)
- pr_warning(FW_BUG ACPI_PFX
- "Invalid physical address in GAR [0x%llx/%u/%u]\n",
- *paddr, width, space_id);
- return -EINVAL;
- }
-
- if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
- if (!silent)
- pr_warning(FW_BUG ACPI_PFX
- "Invalid bit width in GAR [0x%llx/%u/%u]\n",
- *paddr, width, space_id);
- return -EINVAL;
- }
-
- if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
- space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
- if (!silent)
- pr_warning(FW_BUG ACPI_PFX
- "Invalid address space type in GAR [0x%llx/%u/%u]\n",
- *paddr, width, space_id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* Pre-map, working on GAR */
-int acpi_pre_map_gar(struct acpi_generic_address *reg)
-{
- u64 paddr;
- void __iomem *vaddr;
- int rc;
-
- if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
- return 0;
-
- rc = acpi_check_gar(reg, &paddr, 0);
- if (rc)
- return rc;
-
- vaddr = acpi_pre_map(paddr, reg->bit_width / 8);
- if (!vaddr)
- return -EIO;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(acpi_pre_map_gar);
-
-/* Post-unmap, working on GAR */
-int acpi_post_unmap_gar(struct acpi_generic_address *reg)
-{
- u64 paddr;
- int rc;
-
- if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
- return 0;
-
- rc = acpi_check_gar(reg, &paddr, 0);
- if (rc)
- return rc;
-
- acpi_post_unmap(paddr, reg->bit_width / 8);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(acpi_post_unmap_gar);
-
-#ifdef readq
-static inline u64 read64(const volatile void __iomem *addr)
-{
- return readq(addr);
-}
-#else
-static inline u64 read64(const volatile void __iomem *addr)
-{
- u64 l, h;
- l = readl(addr);
- h = readl(addr+4);
- return l | (h << 32);
-}
-#endif
-
-/*
- * Can be used in atomic (including NMI) or process context. RCU read
- * lock can only be released after the IO memory area accessing.
- */
-static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width)
-{
- void __iomem *addr;
-
- rcu_read_lock();
- addr = __acpi_ioremap_fast(paddr, width);
- switch (width) {
- case 8:
- *val = readb(addr);
- break;
- case 16:
- *val = readw(addr);
- break;
- case 32:
- *val = readl(addr);
- break;
- case 64:
- *val = read64(addr);
- break;
- default:
- return -EINVAL;
- }
- rcu_read_unlock();
-
- return 0;
-}
-
-#ifdef writeq
-static inline void write64(u64 val, volatile void __iomem *addr)
-{
- writeq(val, addr);
-}
-#else
-static inline void write64(u64 val, volatile void __iomem *addr)
-{
- writel(val, addr);
- writel(val>>32, addr+4);
-}
-#endif
-
-static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width)
-{
- void __iomem *addr;
-
- rcu_read_lock();
- addr = __acpi_ioremap_fast(paddr, width);
- switch (width) {
- case 8:
- writeb(val, addr);
- break;
- case 16:
- writew(val, addr);
- break;
- case 32:
- writel(val, addr);
- break;
- case 64:
- write64(val, addr);
- break;
- default:
- return -EINVAL;
- }
- rcu_read_unlock();
-
- return 0;
-}
-
-/* GAR accessing in atomic (including NMI) or process context */
-int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg)
-{
- u64 paddr;
- int rc;
-
- rc = acpi_check_gar(reg, &paddr, 1);
- if (rc)
- return rc;
-
- *val = 0;
- switch (reg->space_id) {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- return acpi_atomic_read_mem(paddr, val, reg->bit_width);
- case ACPI_ADR_SPACE_SYSTEM_IO:
- return acpi_os_read_port(paddr, (u32 *)val, reg->bit_width);
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(acpi_atomic_read);
-
-int acpi_atomic_write(u64 val, struct acpi_generic_address *reg)
-{
- u64 paddr;
- int rc;
-
- rc = acpi_check_gar(reg, &paddr, 1);
- if (rc)
- return rc;
-
- switch (reg->space_id) {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- return acpi_atomic_write_mem(paddr, val, reg->bit_width);
- case ACPI_ADR_SPACE_SYSTEM_IO:
- return acpi_os_write_port(paddr, val, reg->bit_width);
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(acpi_atomic_write);
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/highmem.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/kmod.h>
return NULL;
}
+#ifndef CONFIG_IA64
+#define should_use_kmap(pfn) page_is_ram(pfn)
+#else
+/* ioremap will take care of cache attributes */
+#define should_use_kmap(pfn) 0
+#endif
+
+static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
+{
+ unsigned long pfn;
+
+ pfn = pg_off >> PAGE_SHIFT;
+ if (should_use_kmap(pfn)) {
+ if (pg_sz > PAGE_SIZE)
+ return NULL;
+ return (void __iomem __force *)kmap(pfn_to_page(pfn));
+ } else
+ return acpi_os_ioremap(pg_off, pg_sz);
+}
+
+static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
+{
+ unsigned long pfn;
+
+ pfn = pg_off >> PAGE_SHIFT;
+ if (page_is_ram(pfn))
+ kunmap(pfn_to_page(pfn));
+ else
+ iounmap(vaddr);
+}
+
void __iomem *__init_refok
acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
pg_off = round_down(phys, PAGE_SIZE);
pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
- virt = acpi_os_ioremap(pg_off, pg_sz);
+ virt = acpi_map(pg_off, pg_sz);
if (!virt) {
mutex_unlock(&acpi_ioremap_lock);
kfree(map);
{
if (!map->refcount) {
synchronize_rcu();
- iounmap(map->virt);
+ acpi_unmap(map->phys, map->virt);
kfree(map);
}
}
return AE_OK;
}
+#ifdef readq
+static inline u64 read64(const volatile void __iomem *addr)
+{
+ return readq(addr);
+}
+#else
+static inline u64 read64(const volatile void __iomem *addr)
+{
+ u64 l, h;
+ l = readl(addr);
+ h = readl(addr+4);
+ return l | (h << 32);
+}
+#endif
+
+acpi_status
+acpi_os_read_memory64(acpi_physical_address phys_addr, u64 *value, u32 width)
+{
+ void __iomem *virt_addr;
+ unsigned int size = width / 8;
+ bool unmap = false;
+ u64 dummy;
+
+ rcu_read_lock();
+ virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+ if (!virt_addr) {
+ rcu_read_unlock();
+ virt_addr = acpi_os_ioremap(phys_addr, size);
+ if (!virt_addr)
+ return AE_BAD_ADDRESS;
+ unmap = true;
+ }
+
+ if (!value)
+ value = &dummy;
+
+ switch (width) {
+ case 8:
+ *(u8 *) value = readb(virt_addr);
+ break;
+ case 16:
+ *(u16 *) value = readw(virt_addr);
+ break;
+ case 32:
+ *(u32 *) value = readl(virt_addr);
+ break;
+ case 64:
+ *(u64 *) value = read64(virt_addr);
+ break;
+ default:
+ BUG();
+ }
+
+ if (unmap)
+ iounmap(virt_addr);
+ else
+ rcu_read_unlock();
+
+ return AE_OK;
+}
+
acpi_status
acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
{
return AE_OK;
}
+#ifdef writeq
+static inline void write64(u64 val, volatile void __iomem *addr)
+{
+ writeq(val, addr);
+}
+#else
+static inline void write64(u64 val, volatile void __iomem *addr)
+{
+ writel(val, addr);
+ writel(val>>32, addr+4);
+}
+#endif
+
+acpi_status
+acpi_os_write_memory64(acpi_physical_address phys_addr, u64 value, u32 width)
+{
+ void __iomem *virt_addr;
+ unsigned int size = width / 8;
+ bool unmap = false;
+
+ rcu_read_lock();
+ virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+ if (!virt_addr) {
+ rcu_read_unlock();
+ virt_addr = acpi_os_ioremap(phys_addr, size);
+ if (!virt_addr)
+ return AE_BAD_ADDRESS;
+ unmap = true;
+ }
+
+ switch (width) {
+ case 8:
+ writeb(value, virt_addr);
+ break;
+ case 16:
+ writew(value, virt_addr);
+ break;
+ case 32:
+ writel(value, virt_addr);
+ break;
+ case 64:
+ write64(value, virt_addr);
+ break;
+ default:
+ BUG();
+ }
+
+ if (unmap)
+ iounmap(virt_addr);
+ else
+ rcu_read_unlock();
+
+ return AE_OK;
+}
+
acpi_status
acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
u64 *value, u32 width)
static void acpi_processor_notify(struct acpi_device *device, u32 event);
static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr);
static int acpi_processor_handle_eject(struct acpi_processor *pr);
-
+static int acpi_processor_start(struct acpi_processor *pr);
static const struct acpi_device_id processor_device_ids[] = {
{ACPI_PROCESSOR_OBJECT_HID, 0},
struct acpi_processor *pr = per_cpu(processors, cpu);
if (action == CPU_ONLINE && pr) {
- acpi_processor_ppc_has_changed(pr, 0);
- acpi_processor_hotplug(pr);
- acpi_processor_reevaluate_tstate(pr, action);
- acpi_processor_tstate_has_changed(pr);
+ /* CPU got physically hotplugged and onlined the first time:
+ * Initialize missing things
+ */
+ if (pr->flags.need_hotplug_init) {
+ struct cpuidle_driver *idle_driver =
+ cpuidle_get_driver();
+
+ printk(KERN_INFO "Will online and init hotplugged "
+ "CPU: %d\n", pr->id);
+ WARN(acpi_processor_start(pr), "Failed to start CPU:"
+ " %d\n", pr->id);
+ pr->flags.need_hotplug_init = 0;
+ if (idle_driver && !strcmp(idle_driver->name,
+ "intel_idle")) {
+ intel_idle_cpu_init(pr->id);
+ }
+ /* Normal CPU soft online event */
+ } else {
+ acpi_processor_ppc_has_changed(pr, 0);
+ acpi_processor_cst_has_changed(pr);
+ acpi_processor_reevaluate_tstate(pr, action);
+ acpi_processor_tstate_has_changed(pr);
+ }
}
if (action == CPU_DEAD && pr) {
/* invalidate the flag.throttling after one CPU is offline */
.notifier_call = acpi_cpu_soft_notify,
};
+/*
+ * acpi_processor_start() is called by the cpu_hotplug_notifier func:
+ * acpi_cpu_soft_notify(). Getting it __cpuinit{data} is difficult, the
+ * root cause seem to be that acpi_processor_uninstall_hotplug_notify()
+ * is in the module_exit (__exit) func. Allowing acpi_processor_start()
+ * to not be in __cpuinit section, but being called from __cpuinit funcs
+ * via __ref looks like the right thing to do here.
+ */
+static __ref int acpi_processor_start(struct acpi_processor *pr)
+{
+ struct acpi_device *device = per_cpu(processor_device_array, pr->id);
+ int result = 0;
+
+#ifdef CONFIG_CPU_FREQ
+ acpi_processor_ppc_has_changed(pr, 0);
+#endif
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
+ if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr, device);
+
+ pr->cdev = thermal_cooling_device_register("Processor", device,
+ &processor_cooling_ops);
+ if (IS_ERR(pr->cdev)) {
+ result = PTR_ERR(pr->cdev);
+ goto err_power_exit;
+ }
+
+ dev_dbg(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
+
+ result = sysfs_create_link(&device->dev.kobj,
+ &pr->cdev->device.kobj,
+ "thermal_cooling");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_thermal_unregister;
+ }
+ result = sysfs_create_link(&pr->cdev->device.kobj,
+ &device->dev.kobj,
+ "device");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_remove_sysfs_thermal;
+ }
+
+ return 0;
+
+err_remove_sysfs_thermal:
+ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+ thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+ acpi_processor_power_exit(pr, device);
+
+ return result;
+}
+
+/*
+ * Do not put anything in here which needs the core to be online.
+ * For example MSR access or setting up things which check for cpuinfo_x86
+ * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
+ * Such things have to be put in and set up above in acpi_processor_start()
+ */
static int __cpuinit acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
goto err_free_cpumask;
}
-#ifdef CONFIG_CPU_FREQ
- acpi_processor_ppc_has_changed(pr, 0);
-#endif
- acpi_processor_get_throttling_info(pr);
- acpi_processor_get_limit_info(pr);
-
- if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
- acpi_processor_power_init(pr, device);
-
- pr->cdev = thermal_cooling_device_register("Processor", device,
- &processor_cooling_ops);
- if (IS_ERR(pr->cdev)) {
- result = PTR_ERR(pr->cdev);
- goto err_power_exit;
- }
+ /*
+ * Do not start hotplugged CPUs now, but when they
+ * are onlined the first time
+ */
+ if (pr->flags.need_hotplug_init)
+ return 0;
- dev_dbg(&device->dev, "registered as cooling_device%d\n",
- pr->cdev->id);
+ /*
+ * Do not start hotplugged CPUs now, but when they
+ * are onlined the first time
+ */
+ if (pr->flags.need_hotplug_init)
+ return 0;
- result = sysfs_create_link(&device->dev.kobj,
- &pr->cdev->device.kobj,
- "thermal_cooling");
- if (result) {
- printk(KERN_ERR PREFIX "Create sysfs link\n");
- goto err_thermal_unregister;
- }
- result = sysfs_create_link(&pr->cdev->device.kobj,
- &device->dev.kobj,
- "device");
- if (result) {
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ result = acpi_processor_start(pr);
+ if (result)
goto err_remove_sysfs;
- }
return 0;
err_remove_sysfs:
- sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-err_thermal_unregister:
- thermal_cooling_device_unregister(pr->cdev);
-err_power_exit:
- acpi_processor_power_exit(pr, device);
sysfs_remove_link(&device->dev.kobj, "sysdev");
err_free_cpumask:
free_cpumask_var(pr->throttling.shared_cpu_map);
return AE_ERROR;
}
+ /* CPU got hot-plugged, but cpu_data is not initialized yet
+ * Set flag to delay cpu_idle/throttling initialization
+ * in:
+ * acpi_processor_add()
+ * acpi_processor_get_info()
+ * and do it when the CPU gets online the first time
+ * TBD: Cleanup above functions and try to do this more elegant.
+ */
+ printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
+ pr->flags.need_hotplug_init = 1;
+
return AE_OK;
}
},
{
.callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCCW29FX",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
.ident = "Averatec AV1020-ED2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
# Makefile for the Linux device tree
-obj-y := core.o sys.o bus.o dd.o syscore.o \
+obj-y := core.o bus.o dd.o syscore.o \
driver.o class.o platform.o \
cpu.o firmware.o init.o map.o devres.o \
attribute_container.o transport_class.o \
/**
* __bus_register - register a driver-core subsystem
- * @bus: bus.
+ * @bus: bus to register
+ * @key: lockdep class key
*
- * Once we have that, we registered the bus with the kobject
+ * Once we have that, we register the bus with the kobject
* infrastructure, then register the children subsystems it has:
* the devices and drivers that belong to the subsystem.
*/
}
/**
* subsys_system_register - register a subsystem at /sys/devices/system/
- * @subsys - system subsystem
- * @groups - default attributes for the root device
+ * @subsys: system subsystem
+ * @groups: default attributes for the root device
*
* All 'system' subsystems have a /sys/devices/system/<name> root device
* with the name of the subsystem. The root device can carry subsystem-
* may be used for reference counting of @dev after calling this
* function.
*
+ * All fields in @dev must be initialized by the caller to 0, except
+ * for those explicitly set to some other value. The simplest
+ * approach is to use kzalloc() to allocate the structure containing
+ * @dev.
+ *
* NOTE: Use put_device() to give up your reference instead of freeing
* @dev directly once you have called this function.
*/
* to the global and sibling lists for the device, then
* adds it to the other relevant subsystems of the driver model.
*
+ * Do not call this routine or device_register() more than once for
+ * any device structure. The driver model core is not designed to work
+ * with devices that get unregistered and then spring back to life.
+ * (Among other things, it's very hard to guarantee that all references
+ * to the previous incarnation of @dev have been dropped.) Allocate
+ * and register a fresh new struct device instead.
+ *
* NOTE: _Never_ directly free @dev after calling this function, even
* if it returned an error! Always use put_device() to give up your
* reference instead.
device_pm_add(dev);
/* Notify clients of device addition. This call must come
- * after dpm_sysf_add() and before kobject_uevent().
+ * after dpm_sysfs_add() and before kobject_uevent().
*/
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
* have a clearly defined need to use and refcount the device
* before it is added to the hierarchy.
*
+ * For more information, see the kerneldoc for device_initialize()
+ * and device_add().
+ *
* NOTE: _Never_ directly free @dev after calling this function, even
* if it returned an error! Always use put_device() to give up the
* reference initialized in this function instead.
if (!firmware) {
dev_err(device, "%s: kmalloc(struct firmware) failed\n",
__func__);
- retval = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
if (fw_get_builtin_firmware(firmware, name)) {
map->precious_reg = config->precious_reg;
map->cache_type = config->cache_type;
+ map->cache_bypass = false;
+ map->cache_only = false;
+
ret = regcache_init(map, config);
mutex_unlock(&map->lock);
+++ /dev/null
-/*
- * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc)
- *
- * Copyright (c) 2002-3 Patrick Mochel
- * 2002-3 Open Source Development Lab
- *
- * This file is released under the GPLv2
- *
- * This exports a 'system' bus type.
- * By default, a 'sys' bus gets added to the root of the system. There will
- * always be core system devices. Devices can use sysdev_register() to
- * add themselves as children of the system bus.
- */
-
-#include <linux/sysdev.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-
-#include "base.h"
-
-#define to_sysdev(k) container_of(k, struct sys_device, kobj)
-#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
-
-
-static ssize_t
-sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
-{
- struct sys_device *sysdev = to_sysdev(kobj);
- struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
-
- if (sysdev_attr->show)
- return sysdev_attr->show(sysdev, sysdev_attr, buffer);
- return -EIO;
-}
-
-
-static ssize_t
-sysdev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct sys_device *sysdev = to_sysdev(kobj);
- struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
-
- if (sysdev_attr->store)
- return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
- return -EIO;
-}
-
-static const struct sysfs_ops sysfs_ops = {
- .show = sysdev_show,
- .store = sysdev_store,
-};
-
-static struct kobj_type ktype_sysdev = {
- .sysfs_ops = &sysfs_ops,
-};
-
-
-int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a)
-{
- return sysfs_create_file(&s->kobj, &a->attr);
-}
-
-
-void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a)
-{
- sysfs_remove_file(&s->kobj, &a->attr);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_create_file);
-EXPORT_SYMBOL_GPL(sysdev_remove_file);
-
-#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj)
-#define to_sysdev_class_attr(a) container_of(a, \
- struct sysdev_class_attribute, attr)
-
-static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
- char *buffer)
-{
- struct sysdev_class *class = to_sysdev_class(kobj);
- struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
-
- if (class_attr->show)
- return class_attr->show(class, class_attr, buffer);
- return -EIO;
-}
-
-static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct sysdev_class *class = to_sysdev_class(kobj);
- struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
-
- if (class_attr->store)
- return class_attr->store(class, class_attr, buffer, count);
- return -EIO;
-}
-
-static const struct sysfs_ops sysfs_class_ops = {
- .show = sysdev_class_show,
- .store = sysdev_class_store,
-};
-
-static struct kobj_type ktype_sysdev_class = {
- .sysfs_ops = &sysfs_class_ops,
-};
-
-int sysdev_class_create_file(struct sysdev_class *c,
- struct sysdev_class_attribute *a)
-{
- return sysfs_create_file(&c->kset.kobj, &a->attr);
-}
-EXPORT_SYMBOL_GPL(sysdev_class_create_file);
-
-void sysdev_class_remove_file(struct sysdev_class *c,
- struct sysdev_class_attribute *a)
-{
- sysfs_remove_file(&c->kset.kobj, &a->attr);
-}
-EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
-
-extern struct kset *system_kset;
-
-int sysdev_class_register(struct sysdev_class *cls)
-{
- int retval;
-
- pr_debug("Registering sysdev class '%s'\n", cls->name);
-
- INIT_LIST_HEAD(&cls->drivers);
- memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
- cls->kset.kobj.parent = &system_kset->kobj;
- cls->kset.kobj.ktype = &ktype_sysdev_class;
- cls->kset.kobj.kset = system_kset;
-
- retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
- if (retval)
- return retval;
-
- retval = kset_register(&cls->kset);
- if (!retval && cls->attrs)
- retval = sysfs_create_files(&cls->kset.kobj,
- (const struct attribute **)cls->attrs);
- return retval;
-}
-
-void sysdev_class_unregister(struct sysdev_class *cls)
-{
- pr_debug("Unregistering sysdev class '%s'\n",
- kobject_name(&cls->kset.kobj));
- if (cls->attrs)
- sysfs_remove_files(&cls->kset.kobj,
- (const struct attribute **)cls->attrs);
- kset_unregister(&cls->kset);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_class_register);
-EXPORT_SYMBOL_GPL(sysdev_class_unregister);
-
-static DEFINE_MUTEX(sysdev_drivers_lock);
-
-/*
- * @dev != NULL means that we're unwinding because some drv->add()
- * failed for some reason. You need to grab sysdev_drivers_lock before
- * calling this.
- */
-static void __sysdev_driver_remove(struct sysdev_class *cls,
- struct sysdev_driver *drv,
- struct sys_device *from_dev)
-{
- struct sys_device *dev = from_dev;
-
- list_del_init(&drv->entry);
- if (!cls)
- return;
-
- if (!drv->remove)
- goto kset_put;
-
- if (dev)
- list_for_each_entry_continue_reverse(dev, &cls->kset.list,
- kobj.entry)
- drv->remove(dev);
- else
- list_for_each_entry(dev, &cls->kset.list, kobj.entry)
- drv->remove(dev);
-
-kset_put:
- kset_put(&cls->kset);
-}
-
-/**
- * sysdev_driver_register - Register auxiliary driver
- * @cls: Device class driver belongs to.
- * @drv: Driver.
- *
- * @drv is inserted into @cls->drivers to be
- * called on each operation on devices of that class. The refcount
- * of @cls is incremented.
- */
-int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
-{
- struct sys_device *dev = NULL;
- int err = 0;
-
- if (!cls) {
- WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
- __func__);
- return -EINVAL;
- }
-
- /* Check whether this driver has already been added to a class. */
- if (drv->entry.next && !list_empty(&drv->entry))
- WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already"
- " been registered to a class, something is wrong, but "
- "will forge on!\n", cls->name, drv);
-
- mutex_lock(&sysdev_drivers_lock);
- if (cls && kset_get(&cls->kset)) {
- list_add_tail(&drv->entry, &cls->drivers);
-
- /* If devices of this class already exist, tell the driver */
- if (drv->add) {
- list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
- err = drv->add(dev);
- if (err)
- goto unwind;
- }
- }
- } else {
- err = -EINVAL;
- WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
- }
-
- goto unlock;
-
-unwind:
- __sysdev_driver_remove(cls, drv, dev);
-
-unlock:
- mutex_unlock(&sysdev_drivers_lock);
- return err;
-}
-
-/**
- * sysdev_driver_unregister - Remove an auxiliary driver.
- * @cls: Class driver belongs to.
- * @drv: Driver.
- */
-void sysdev_driver_unregister(struct sysdev_class *cls,
- struct sysdev_driver *drv)
-{
- mutex_lock(&sysdev_drivers_lock);
- __sysdev_driver_remove(cls, drv, NULL);
- mutex_unlock(&sysdev_drivers_lock);
-}
-EXPORT_SYMBOL_GPL(sysdev_driver_register);
-EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
-
-/**
- * sysdev_register - add a system device to the tree
- * @sysdev: device in question
- *
- */
-int sysdev_register(struct sys_device *sysdev)
-{
- int error;
- struct sysdev_class *cls = sysdev->cls;
-
- if (!cls)
- return -EINVAL;
-
- pr_debug("Registering sys device of class '%s'\n",
- kobject_name(&cls->kset.kobj));
-
- /* initialize the kobject to 0, in case it had previously been used */
- memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
-
- /* Make sure the kset is set */
- sysdev->kobj.kset = &cls->kset;
-
- /* Register the object */
- error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL,
- "%s%d", kobject_name(&cls->kset.kobj),
- sysdev->id);
-
- if (!error) {
- struct sysdev_driver *drv;
-
- pr_debug("Registering sys device '%s'\n",
- kobject_name(&sysdev->kobj));
-
- mutex_lock(&sysdev_drivers_lock);
- /* Generic notification is implicit, because it's that
- * code that should have called us.
- */
-
- /* Notify class auxiliary drivers */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->add)
- drv->add(sysdev);
- }
- mutex_unlock(&sysdev_drivers_lock);
- kobject_uevent(&sysdev->kobj, KOBJ_ADD);
- }
-
- return error;
-}
-
-void sysdev_unregister(struct sys_device *sysdev)
-{
- struct sysdev_driver *drv;
-
- mutex_lock(&sysdev_drivers_lock);
- list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
- if (drv->remove)
- drv->remove(sysdev);
- }
- mutex_unlock(&sysdev_drivers_lock);
-
- kobject_put(&sysdev->kobj);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_register);
-EXPORT_SYMBOL_GPL(sysdev_unregister);
-
-#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
-
-ssize_t sysdev_store_ulong(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- const char *buf, size_t size)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- char *end;
- unsigned long new = simple_strtoul(buf, &end, 0);
- if (end == buf)
- return -EINVAL;
- *(unsigned long *)(ea->var) = new;
- /* Always return full write size even if we didn't consume all */
- return size;
-}
-EXPORT_SYMBOL_GPL(sysdev_store_ulong);
-
-ssize_t sysdev_show_ulong(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- char *buf)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
-}
-EXPORT_SYMBOL_GPL(sysdev_show_ulong);
-
-ssize_t sysdev_store_int(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- const char *buf, size_t size)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- char *end;
- long new = simple_strtol(buf, &end, 0);
- if (end == buf || new > INT_MAX || new < INT_MIN)
- return -EINVAL;
- *(int *)(ea->var) = new;
- /* Always return full write size even if we didn't consume all */
- return size;
-}
-EXPORT_SYMBOL_GPL(sysdev_store_int);
-
-ssize_t sysdev_show_int(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- char *buf)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
-}
-EXPORT_SYMBOL_GPL(sysdev_show_int);
-
err_out:
if (bridge->driver->needs_scratch_page) {
- void *va = page_address(bridge->scratch_page_page);
+ struct page *page = bridge->scratch_page_page;
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
}
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page) {
- void *va = page_address(bridge->scratch_page_page);
+ struct page *page = bridge->scratch_page_page;
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
}
}
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock.
*/
-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
{
struct drm_magic_entry *pt;
struct drm_hash_item *hash;
* If there is a magic number in drm_file::magic then use it, otherwise
* searches an unique non-zero magic number and add it associating it with \p
* file_priv.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
* \return zero if authentication successed, or a negative number otherwise.
*
* Checks if \p file_priv is associated with the magic number passed in \arg.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv)
(long)old_encode_dev(file_priv->minor->device),
dev->open_count);
+ /* Release any auth tokens that might point to this file_priv,
+ (do that under the drm_global_mutex) */
+ if (file_priv->magic)
+ (void) drm_remove_magic(file_priv->master, file_priv->magic);
+
/* if the master has gone away we can't do anything with the lock */
if (file_priv->minor->master)
drm_master_release(dev, filp);
obj->dev = dev;
obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
if (IS_ERR(obj->filp))
- return -ENOMEM;
+ return PTR_ERR(obj->filp);
kref_init(&obj->refcount);
atomic_set(&obj->handle_count, 0);
config DRM_EXYNOS_FIMD
tristate "Exynos DRM FIMD"
- depends on DRM_EXYNOS
+ depends on DRM_EXYNOS && !FB_S3C
default n
help
Choose this option if you want to use Exynos FIMD for DRM.
config DRM_EXYNOS_HDMI
tristate "Exynos DRM HDMI"
- depends on DRM_EXYNOS
+ depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
help
Choose this option if you want to use Exynos HDMI for DRM.
If M is selected, the module will be called exynos_drm_hdmi
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- pm_runtime_put_sync(subdrv_dev);
+ if (!ctx->suspended)
+ pm_runtime_put_sync(subdrv_dev);
break;
default:
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
writel(val, ctx->regs + SHADOWCON);
}
+static int fimd_power_on(struct fimd_context *ctx, bool enable)
+{
+ struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+ struct device *dev = subdrv->manager.dev;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (enable != false && enable != true)
+ return -EINVAL;
+
+ if (enable) {
+ int ret;
+
+ ret = clk_enable(ctx->bus_clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(ctx->lcd_clk);
+ if (ret < 0) {
+ clk_disable(ctx->bus_clk);
+ return ret;
+ }
+
+ ctx->suspended = false;
+
+ /* if vblank was enabled status, enable it again. */
+ if (test_and_clear_bit(0, &ctx->irq_flags))
+ fimd_enable_vblank(dev);
+
+ fimd_apply(dev);
+ } else {
+ clk_disable(ctx->lcd_clk);
+ clk_disable(ctx->bus_clk);
+
+ ctx->suspended = true;
+ }
+
+ return 0;
+}
+
static int __devinit fimd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
#ifdef CONFIG_PM_SLEEP
static int fimd_suspend(struct device *dev)
{
- int ret;
+ struct fimd_context *ctx = get_fimd_context(dev);
if (pm_runtime_suspended(dev))
return 0;
- ret = pm_runtime_suspend(dev);
- if (ret < 0)
- return ret;
-
- return 0;
+ /*
+ * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
+ * called here, an error would be returned by that interface
+ * because the usage_count of pm runtime is more than 1.
+ */
+ return fimd_power_on(ctx, false);
}
static int fimd_resume(struct device *dev)
{
- int ret;
-
- ret = pm_runtime_resume(dev);
- if (ret < 0) {
- DRM_ERROR("failed to resume runtime pm.\n");
- return ret;
- }
-
- pm_runtime_disable(dev);
-
- ret = pm_runtime_set_active(dev);
- if (ret < 0) {
- DRM_ERROR("failed to active runtime pm.\n");
- pm_runtime_enable(dev);
- pm_runtime_suspend(dev);
- return ret;
- }
+ struct fimd_context *ctx = get_fimd_context(dev);
- pm_runtime_enable(dev);
+ /*
+ * if entered to sleep when lcd panel was on, the usage_count
+ * of pm runtime would still be 1 so in this case, fimd driver
+ * should be on directly not drawing on pm runtime interface.
+ */
+ if (!pm_runtime_suspended(dev))
+ return fimd_power_on(ctx, true);
return 0;
}
DRM_DEBUG_KMS("%s\n", __FILE__);
- clk_disable(ctx->lcd_clk);
- clk_disable(ctx->bus_clk);
-
- ctx->suspended = true;
- return 0;
+ return fimd_power_on(ctx, false);
}
static int fimd_runtime_resume(struct device *dev)
{
struct fimd_context *ctx = get_fimd_context(dev);
- int ret;
DRM_DEBUG_KMS("%s\n", __FILE__);
- ret = clk_enable(ctx->bus_clk);
- if (ret < 0)
- return ret;
-
- ret = clk_enable(ctx->lcd_clk);
- if (ret < 0) {
- clk_disable(ctx->bus_clk);
- return ret;
- }
-
- ctx->suspended = false;
-
- /* if vblank was enabled status, enable it again. */
- if (test_and_clear_bit(0, &ctx->irq_flags))
- fimd_enable_vblank(dev);
-
- fimd_apply(dev);
-
- return 0;
+ return fimd_power_on(ctx, true);
}
#endif
err_iomap:
iounmap(hdata->regs);
err_req_region:
- release_resource(hdata->regs_res);
- kfree(hdata->regs_res);
+ release_mem_region(hdata->regs_res->start,
+ resource_size(hdata->regs_res));
err_resource:
hdmi_resources_cleanup(hdata);
err_data:
iounmap(hdata->regs);
- release_resource(hdata->regs_res);
- kfree(hdata->regs_res);
+ release_mem_region(hdata->regs_res->start,
+ resource_size(hdata->regs_res));
/* hdmiphy i2c driver */
i2c_del_driver(&hdmiphy_driver);
void psbfb_suspend(struct drm_device *dev)
{
- struct drm_framebuffer *fb = 0;
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ struct drm_framebuffer *fb;
console_lock();
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
struct fb_info *info = psbfb->fbdev;
fb_set_suspend(info, 1);
drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
void psbfb_resume(struct drm_device *dev)
{
- struct drm_framebuffer *fb = 0;
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ struct drm_framebuffer *fb;
console_lock();
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
struct fb_info *info = psbfb->fbdev;
fb_set_suspend(info, 0);
drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
*/
#include <drm/drmP.h>
+#include <linux/shmem_fs.h>
#include "psb_drv.h"
gt->npage = pages;
for (i = 0; i < pages; i++) {
- /* FIXME: needs updating as per mail from Hugh Dickins */
- p = read_cache_page_gfp(mapping, i,
- __GFP_COLD | GFP_KERNEL);
+ p = shmem_read_mapping_page(mapping, i);
if (IS_ERR(p))
goto err;
gt->pages[i] = p;
}
/* Must be called with the lock held */
-void i810_driver_reclaim_buffers(struct drm_device *dev,
+static void i810_reclaim_buffers(struct drm_device *dev,
struct drm_file *file_priv)
{
struct drm_device_dma *dma = dev->dma;
if (dev_priv->page_flipping)
i810_do_cleanup_pageflip(dev);
}
+}
- if (file_priv->master && file_priv->master->lock.hw_lock) {
- drm_idlelock_take(&file_priv->master->lock);
- i810_driver_reclaim_buffers(dev, file_priv);
- drm_idlelock_release(&file_priv->master->lock);
- } else {
- /* master disappeared, clean up stuff anyway and hope nothing
- * goes wrong */
- i810_driver_reclaim_buffers(dev, file_priv);
- }
-
+void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv)
+{
+ i810_reclaim_buffers(dev, file_priv);
}
int i810_driver_dma_quiescent(struct drm_device *dev)
.lastclose = i810_driver_lastclose,
.preclose = i810_driver_preclose,
.device_is_agp = i810_driver_device_is_agp,
+ .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
.dma_quiescent = i810_driver_dma_quiescent,
.ioctls = i810_ioctls,
.fops = &i810_driver_fops,
/* i810_dma.c */
extern int i810_driver_dma_quiescent(struct drm_device *dev);
-void i810_driver_reclaim_buffers(struct drm_device *dev,
- struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv);
extern int i810_driver_load(struct drm_device *, unsigned long flags);
extern void i810_driver_lastclose(struct drm_device *dev);
extern void i810_driver_preclose(struct drm_device *dev,
struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv);
extern int i810_driver_device_is_agp(struct drm_device *dev);
extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static void
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
{
- seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s%s",
+ seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s",
&obj->base,
get_pin_flag(obj),
get_tiling_flag(obj),
- obj->base.size,
+ obj->base.size / 1024,
obj->base.read_domains,
obj->base.write_domain,
obj->last_rendering_seqno,
seq_printf(m, " Size : %08x\n", ring->size);
seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring));
seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring));
- if (IS_GEN6(dev)) {
+ if (IS_GEN6(dev) || IS_GEN7(dev)) {
seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring));
seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring));
}
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 rpmodectl1, gt_core_status, rcctl1;
+ unsigned forcewake_count;
int count=0, ret;
if (ret)
return ret;
- if (atomic_read(&dev_priv->forcewake_count)) {
- seq_printf(m, "RC information inaccurate because userspace "
- "holds a reference \n");
+ spin_lock_irq(&dev_priv->gt_lock);
+ forcewake_count = dev_priv->forcewake_count;
+ spin_unlock_irq(&dev_priv->gt_lock);
+
+ if (forcewake_count) {
+ seq_printf(m, "RC information inaccurate because somebody "
+ "holds a forcewake reference \n");
} else {
/* NB: we cannot use forcewake, else we read the wrong values */
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
seq_printf(m, "SW control enabled: %s\n",
yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) ==
GEN6_RP_MEDIA_SW_MODE));
- seq_printf(m, "RC6 Enabled: %s\n",
+ seq_printf(m, "RC1e Enabled: %s\n",
yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
seq_printf(m, "RC6 Enabled: %s\n",
yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned forcewake_count;
+
+ spin_lock_irq(&dev_priv->gt_lock);
+ forcewake_count = dev_priv->forcewake_count;
+ spin_unlock_irq(&dev_priv->gt_lock);
- seq_printf(m, "forcewake count = %d\n",
- atomic_read(&dev_priv->forcewake_count));
+ seq_printf(m, "forcewake count = %u\n", forcewake_count);
return 0;
}
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- if (!IS_GEN6(dev))
+ if (INTEL_INFO(dev)->gen < 6)
return 0;
ret = mutex_lock_interruptible(&dev->struct_mutex);
struct drm_device *dev = inode->i_private;
struct drm_i915_private *dev_priv = dev->dev_private;
- if (!IS_GEN6(dev))
+ if (INTEL_INFO(dev)->gen < 6)
return 0;
/*
if (!IS_I945G(dev) && !IS_I945GM(dev))
pci_enable_msi(dev->pdev);
+ spin_lock_init(&dev_priv->gt_lock);
spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->error_lock);
spin_lock_init(&dev_priv->rps_lock);
*/
void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
{
- WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+ unsigned long irqflags;
- /* Forcewake is atomic in case we get in here without the lock */
- if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+ if (dev_priv->forcewake_count++ == 0)
dev_priv->display.force_wake_get(dev_priv);
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
}
void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
*/
void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
{
- WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+ unsigned long irqflags;
- if (atomic_dec_and_test(&dev_priv->forcewake_count))
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+ if (--dev_priv->forcewake_count == 0)
dev_priv->display.force_wake_put(dev_priv);
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
}
void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
static int gen6_do_reset(struct drm_device *dev, u8 flags)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+ unsigned long irqflags;
- I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
- return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+ /* Hold gt_lock across reset to prevent any register access
+ * with forcewake not set correctly
+ */
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+
+ /* Reset the chip */
+
+ /* GEN6_GDRST is not in the gt power well, no need to check
+ * for fifo space for the write or forcewake the chip for
+ * the read
+ */
+ I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
+
+ /* Spin waiting for the device to ack the reset request */
+ ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+
+ /* If reset with a user forcewake, try to restore, otherwise turn it off */
+ if (dev_priv->forcewake_count)
+ dev_priv->display.force_wake_get(dev_priv);
+ else
+ dev_priv->display.force_wake_put(dev_priv);
+
+ /* Restore fifo count */
+ dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
+ return ret;
}
/**
case 7:
case 6:
ret = gen6_do_reset(dev, flags);
- /* If reset with a user forcewake, try to restore */
- if (atomic_read(&dev_priv->forcewake_count))
- __gen6_gt_force_wake_get(dev_priv);
break;
case 5:
ret = ironlake_do_reset(dev, flags);
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
u##x val = 0; \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
- gen6_gt_force_wake_get(dev_priv); \
+ unsigned long irqflags; \
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
+ if (dev_priv->forcewake_count == 0) \
+ dev_priv->display.force_wake_get(dev_priv); \
val = read##y(dev_priv->regs + reg); \
- gen6_gt_force_wake_put(dev_priv); \
+ if (dev_priv->forcewake_count == 0) \
+ dev_priv->display.force_wake_put(dev_priv); \
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
} else { \
val = read##y(dev_priv->regs + reg); \
} \
int relative_constants_mode;
void __iomem *regs;
- u32 gt_fifo_count;
+ /** gt_fifo_count and the subsequent register write are synchronized
+ * with dev->struct_mutex. */
+ unsigned gt_fifo_count;
+ /** forcewake_count is protected by gt_lock */
+ unsigned forcewake_count;
+ /** gt_lock is also taken in irq contexts. */
+ struct spinlock gt_lock;
struct intel_gmbus {
struct i2c_adapter adapter;
struct drm_property *broadcast_rgb_property;
struct drm_property *force_audio_property;
-
- atomic_t forcewake_count;
} drm_i915_private_t;
enum i915_cache_level {
INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
I915_WRITE(HWSTAM, 0xeffe);
- if (IS_GEN6(dev) || IS_GEN7(dev)) {
+
+ if (IS_GEN6(dev)) {
/* Workaround stalls observed on Sandy Bridge GPUs by
* making the blitter command streamer generate a
* write to the Hardware Status Page for
#include "drm.h"
#include "i915_drm.h"
#include "intel_drv.h"
+#include "i915_reg.h"
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpll_reg;
+ /* On IVB, 3rd pipe shares PLL with another one */
+ if (pipe > 1)
+ return false;
+
if (HAS_PCH_SPLIT(dev))
- dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
+ dpll_reg = PCH_DPLL(pipe);
else
dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
if (IS_IRONLAKE_M(dev))
ironlake_disable_drps(dev);
- if (IS_GEN6(dev))
+ if (INTEL_INFO(dev)->gen >= 6)
gen6_disable_rps(dev);
/* Cache mode state */
intel_init_emon(dev);
}
- if (IS_GEN6(dev)) {
+ if (INTEL_INFO(dev)->gen >= 6) {
gen6_enable_rps(dev_priv);
gen6_update_ring_freq(dev_priv);
}
struct bdb_edp {
struct edp_power_seq power_seqs[16];
u32 color_depth;
- u32 sdrrs_msa_timing_delay;
struct edp_link_params link_params[16];
+ u32 sdrrs_msa_timing_delay;
+
+ /* ith bit indicates enabled/disabled for (i+1)th panel */
+ u16 edp_s3d_feature;
+ u16 edp_t3_optimization;
} __attribute__ ((packed));
void intel_setup_bios(struct drm_device *dev);
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include "drmP.h"
.destroy = intel_encoder_destroy,
};
+static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
+{
+ DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id intel_no_crt[] = {
+ {
+ .callback = intel_no_crt_dmi_callback,
+ .ident = "ACER ZGB",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+ },
+ },
+ { }
+};
+
void intel_crt_init(struct drm_device *dev)
{
struct drm_connector *connector;
struct intel_connector *intel_connector;
struct drm_i915_private *dev_priv = dev->dev_private;
+ /* Skip machines without VGA that falsely report hotplug events */
+ if (dmi_check_system(intel_no_crt))
+ return;
+
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
if (!crt)
return;
if (is_lvds) {
temp = I915_READ(PCH_LVDS);
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev)) {
+ temp &= ~PORT_TRANS_SEL_MASK;
temp |= PORT_TRANS_SEL_CPT(pipe);
- else if (pipe == 1)
- temp |= LVDS_PIPEB_SELECT;
- else
- temp &= ~LVDS_PIPEB_SELECT;
+ } else {
+ if (pipe == 1)
+ temp |= LVDS_PIPEB_SELECT;
+ else
+ temp &= ~LVDS_PIPEB_SELECT;
+ }
/* set the corresponsding LVDS_BORDER bit */
temp |= dev_priv->lvds_border_bits;
for (i = 0; i < dev_priv->num_pipe; i++) {
intel_crtc_init(dev, i);
- if (HAS_PCH_SPLIT(dev)) {
- ret = intel_plane_init(dev, i);
- if (ret)
- DRM_ERROR("plane %d init failed: %d\n",
- i, ret);
- }
+ ret = intel_plane_init(dev, i);
+ if (ret)
+ DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
}
/* Just disable it once at startup */
},
},
{
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "Clientron E830",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
+ },
+ },
+ {
.callback = intel_no_lvds_dmi_callback,
.ident = "Asus EeeBox PC EB1007",
.matches = {
return 0;
}
+static u32
+gen6_ring_get_seqno(struct intel_ring_buffer *ring)
+{
+ struct drm_device *dev = ring->dev;
+
+ /* Workaround to force correct ordering between irq and seqno writes on
+ * ivb (and maybe also on snb) by reading from a CS register (like
+ * ACTHD) before reading the status page. */
+ if (IS_GEN7(dev))
+ intel_ring_get_active_head(ring);
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
static u32
ring_get_seqno(struct intel_ring_buffer *ring)
{
return 0;
}
-static bool
-gen7_blt_ring_get_irq(struct intel_ring_buffer *ring)
-{
- /* The BLT ring on IVB appears to have broken synchronization
- * between the seqno write and the interrupt, so that the
- * interrupt appears first. Returning false here makes
- * i915_wait_request() do a polling loop, instead.
- */
- return false;
-}
-
static bool
gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
{
if (!dev->irq_enabled)
return false;
+ /* It looks like we need to prevent the gt from suspending while waiting
+ * for an notifiy irq, otherwise irqs seem to get lost on at least the
+ * blt/bsd rings on ivb. */
+ if (IS_GEN7(dev))
+ gen6_gt_force_wake_get(dev_priv);
+
spin_lock(&ring->irq_lock);
if (ring->irq_refcount++ == 0) {
ring->irq_mask &= ~rflag;
ironlake_disable_irq(dev_priv, gflag);
}
spin_unlock(&ring->irq_lock);
+
+ if (IS_GEN7(dev))
+ gen6_gt_force_wake_put(dev_priv);
}
static bool
.write_tail = gen6_bsd_ring_write_tail,
.flush = gen6_ring_flush,
.add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
+ .get_seqno = gen6_ring_get_seqno,
.irq_get = gen6_bsd_ring_get_irq,
.irq_put = gen6_bsd_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
.write_tail = ring_write_tail,
.flush = blt_ring_flush,
.add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
+ .get_seqno = gen6_ring_get_seqno,
.irq_get = blt_ring_get_irq,
.irq_put = blt_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
ring->flush = gen6_render_ring_flush;
ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq;
+ ring->get_seqno = gen6_ring_get_seqno;
} else if (IS_GEN5(dev)) {
ring->add_request = pc_render_add_request;
ring->get_seqno = pc_render_get_seqno;
*ring = gen6_blt_ring;
- if (IS_GEN7(dev))
- ring->irq_get = gen7_blt_ring_get_irq;
-
return intel_init_ring_buffer(dev, ring);
}
/* Set the SDVO control regs. */
if (INTEL_INFO(dev)->gen >= 4) {
- sdvox = 0;
+ /* The real mode polarity is set by the SDVO commands, using
+ * struct intel_sdvo_dtd. */
+ sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
if (intel_sdvo->is_hdmi)
sdvox |= intel_sdvo->color_range;
if (INTEL_INFO(dev)->gen < 5)
sdvox |= SDVO_BORDER_ENABLE;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
- sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
- sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
} else {
sdvox = I915_READ(intel_sdvo->sdvo_reg);
switch (intel_sdvo->sdvo_reg) {
mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
- if (ret) {
- DRM_ERROR("failed to pin object\n");
+ if (ret)
goto out_unlock;
- }
intel_plane->obj = obj;
unsigned long possible_crtcs;
int ret;
- if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
- DRM_ERROR("new plane code only for SNB+\n");
+ if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV;
- }
intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
if (!intel_plane)
{
.name = "NTSC-M",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
{
.name = "NTSC-443",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
{
.name = "NTSC-J",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
{
.name = "PAL-M",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
.name = "PAL-N",
.clock = 108000,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
.name = "PAL",
.clock = 108000,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
.filter_table = filter_table,
},
- {
- .name = "480p@59.94Hz",
- .clock = 107520,
- .refresh = 59940,
- .oversample = TV_OVERSAMPLE_4X,
- .component_only = 1,
-
- .hsync_end = 64, .hblank_end = 122,
- .hblank_start = 842, .htotal = 857,
-
- .progressive = true, .trilevel_sync = false,
-
- .vsync_start_f1 = 12, .vsync_start_f2 = 12,
- .vsync_len = 12,
-
- .veq_ena = false,
-
- .vi_end_f1 = 44, .vi_end_f2 = 44,
- .nbr_end = 479,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
- {
- .name = "480p@60Hz",
- .clock = 107520,
- .refresh = 60000,
- .oversample = TV_OVERSAMPLE_4X,
- .component_only = 1,
-
- .hsync_end = 64, .hblank_end = 122,
- .hblank_start = 842, .htotal = 856,
-
- .progressive = true, .trilevel_sync = false,
-
- .vsync_start_f1 = 12, .vsync_start_f2 = 12,
- .vsync_len = 12,
-
- .veq_ena = false,
-
- .vi_end_f1 = 44, .vi_end_f2 = 44,
- .nbr_end = 479,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
- {
- .name = "576p",
- .clock = 107520,
- .refresh = 50000,
- .oversample = TV_OVERSAMPLE_4X,
- .component_only = 1,
-
- .hsync_end = 64, .hblank_end = 139,
- .hblank_start = 859, .htotal = 863,
-
- .progressive = true, .trilevel_sync = false,
-
- .vsync_start_f1 = 10, .vsync_start_f2 = 10,
- .vsync_len = 10,
-
- .veq_ena = false,
-
- .vi_end_f1 = 48, .vi_end_f2 = 48,
- .nbr_end = 575,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
{
.name = "720p@60Hz",
.clock = 148800,
.filter_table = filter_table,
},
- {
- .name = "720p@59.94Hz",
- .clock = 148800,
- .refresh = 59940,
- .oversample = TV_OVERSAMPLE_2X,
- .component_only = 1,
-
- .hsync_end = 80, .hblank_end = 300,
- .hblank_start = 1580, .htotal = 1651,
-
- .progressive = true, .trilevel_sync = true,
-
- .vsync_start_f1 = 10, .vsync_start_f2 = 10,
- .vsync_len = 10,
-
- .veq_ena = false,
-
- .vi_end_f1 = 29, .vi_end_f2 = 29,
- .nbr_end = 719,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
{
.name = "720p@50Hz",
.clock = 148800,
{
.name = "1080i@50Hz",
.clock = 148800,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_2X,
.component_only = 1,
{
.name = "1080i@60Hz",
.clock = 148800,
- .refresh = 30000,
+ .refresh = 60000,
.oversample = TV_OVERSAMPLE_2X,
.component_only = 1,
.burst_ena = false,
- .filter_table = filter_table,
- },
- {
- .name = "1080i@59.94Hz",
- .clock = 148800,
- .refresh = 29970,
- .oversample = TV_OVERSAMPLE_2X,
- .component_only = 1,
-
- .hsync_end = 88, .hblank_end = 235,
- .hblank_start = 2155, .htotal = 2201,
-
- .progressive = false, .trilevel_sync = true,
-
- .vsync_start_f1 = 4, .vsync_start_f2 = 5,
- .vsync_len = 10,
-
- .veq_ena = true, .veq_start_f1 = 4,
- .veq_start_f2 = 4, .veq_len = 10,
-
-
- .vi_end_f1 = 21, .vi_end_f2 = 22,
- .nbr_end = 539,
-
- .burst_ena = false,
-
.filter_table = filter_table,
},
};
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vma *vma;
+ /* ttm can now (stupidly) pass the driver bos it didn't create... */
+ if (bo->destroy != nouveau_bo_del_ttm)
+ return;
+
list_for_each_entry(vma, &nvbo->vma_list, head) {
if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
nouveau_vm_map(vma, new_mem->mm_node);
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
-static void atombios_disable_ss(struct drm_crtc *crtc)
+static void atombios_disable_ss(struct radeon_device *rdev, int pll_id)
{
- struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct radeon_device *rdev = dev->dev_private;
u32 ss_cntl;
if (ASIC_IS_DCE4(rdev)) {
- switch (radeon_crtc->pll_id) {
+ switch (pll_id) {
case ATOM_PPLL1:
ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);
ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
return;
}
} else if (ASIC_IS_AVIVO(rdev)) {
- switch (radeon_crtc->pll_id) {
+ switch (pll_id) {
case ATOM_PPLL1:
ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
ss_cntl &= ~1;
ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;
};
-static void atombios_crtc_program_ss(struct drm_crtc *crtc,
+static void atombios_crtc_program_ss(struct radeon_device *rdev,
int enable,
int pll_id,
struct radeon_atom_ss *ss)
{
- struct drm_device *dev = crtc->dev;
- struct radeon_device *rdev = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
union atom_enable_ss args;
} else if (ASIC_IS_AVIVO(rdev)) {
if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
(ss->type & ATOM_EXTERNAL_SS_MASK)) {
- atombios_disable_ss(crtc);
+ atombios_disable_ss(rdev, pll_id);
return;
}
args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
} else {
if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
(ss->type & ATOM_EXTERNAL_SS_MASK)) {
- atombios_disable_ss(crtc);
+ atombios_disable_ss(rdev, pll_id);
return;
}
args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
int encoder_mode = 0;
u32 dp_clock = mode->clock;
int bpc = 8;
+ bool is_duallink = false;
/* reset the pll flags */
pll->flags = 0;
if (connector && connector->display_info.bpc)
bpc = connector->display_info.bpc;
encoder_mode = atombios_get_encoder_mode(encoder);
+ is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
(radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
if (connector) {
if (dig->coherent_mode)
args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_COHERENT_MODE;
- if (mode->clock > 165000)
+ if (is_duallink)
args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_DUAL_LINK;
}
/* on DCE5, make sure the voltage is high enough to support the
* required disp clk.
*/
-static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
+static void atombios_crtc_set_dcpll(struct radeon_device *rdev,
u32 dispclk)
{
- struct drm_device *dev = crtc->dev;
- struct radeon_device *rdev = dev->dev_private;
u8 frev, crev;
int index;
union set_pixel_clock args;
radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
&ref_div, &post_div);
- atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
+ atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
encoder_mode, radeon_encoder->encoder_id, mode->clock,
ss.step = step_size;
}
- atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
+ atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
}
}
}
+void radeon_atom_dcpll_init(struct radeon_device *rdev)
+{
+ /* always set DCPLL */
+ if (ASIC_IS_DCE4(rdev)) {
+ struct radeon_atom_ss ss;
+ bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
+ ASIC_INTERNAL_SS_ON_DCPLL,
+ rdev->clock.default_dispclk);
+ if (ss_enabled)
+ atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss);
+ /* XXX: DCE5, make sure voltage, dispclk is high enough */
+ atombios_crtc_set_dcpll(rdev, rdev->clock.default_dispclk);
+ if (ss_enabled)
+ atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss);
+ }
+
+}
+
int atombios_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
}
}
- /* always set DCPLL */
- if (ASIC_IS_DCE4(rdev)) {
- struct radeon_atom_ss ss;
- bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
- ASIC_INTERNAL_SS_ON_DCPLL,
- rdev->clock.default_dispclk);
- if (ss_enabled)
- atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss);
- /* XXX: DCE5, make sure voltage, dispclk is high enough */
- atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk);
- if (ss_enabled)
- atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss);
- }
atombios_crtc_set_pll(crtc, adjusted_mode);
if (ASIC_IS_DCE4(rdev))
return false;
}
-static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
- struct drm_connector *connector)
+int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
+ struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
if (!ASIC_IS_DCE4(rdev))
- return;
+ return panel_mode;
if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
ENCODER_OBJECT_ID_NUTMEG)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
}
- atombios_dig_encoder_setup(encoder,
- ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
- panel_mode);
-
- if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
- (panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
- radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
- }
+ return panel_mode;
}
void radeon_dp_set_link_config(struct drm_connector *connector,
static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
{
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
u8 tmp;
/* power up the sink */
radeon_write_dpcd_reg(dp_info->radeon_connector,
DP_DOWNSPREAD_CTRL, 0);
- radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector);
+ if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
+ (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
+ radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+ }
/* set the lane count on the sink */
tmp = dp_info->dp_lane_count;
}
}
-static struct drm_connector *
-radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- struct drm_connector *connector;
- struct radeon_connector *radeon_connector;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- radeon_connector = to_radeon_connector(connector);
- if (radeon_encoder->devices & radeon_connector->devices)
- return connector;
- }
- return NULL;
-}
-
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
/* R4xx, R5xx */
args.ext_tmds.sXTmdsEncoder.ucEnable = action;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
/* DFP1, CRT1, TV1 depending on the type of port */
args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
break;
case 3:
} else {
if (dig->linkb)
args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
/*if (pScrn->rgbBits == 8) */
args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
} else {
if (dig->linkb)
args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
}
break;
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
- if (drm_detect_monitor_audio(radeon_connector->edid) &&
+ if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
radeon_audio)
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
default:
- if (drm_detect_monitor_audio(radeon_connector->edid) &&
+ if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
radeon_audio)
return ATOM_ENCODER_MODE_HDMI;
else
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
return ATOM_ENCODER_MODE_DP;
- else if (drm_detect_monitor_audio(radeon_connector->edid) &&
+ else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
radeon_audio)
return ATOM_ENCODER_MODE_HDMI;
else
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
args.v1.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.ucLaneNum = 8;
else
args.v1.ucLaneNum = 4;
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
args.v3.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.ucLaneNum = 8;
else
args.v3.ucLaneNum = 4;
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
args.v4.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.ucLaneNum = 8;
else
args.v4.ucLaneNum = 4;
if (is_dp)
args.v1.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
if ((rdev->flags & RADEON_IS_IGP) &&
(radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
- if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+ if (is_dp ||
+ !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
if (igp_lane_info & 0x1)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
else if (igp_lane_info & 0x2)
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
}
break;
if (is_dp)
args.v2.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v2.acConfig.fCoherentMode = 1;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v2.acConfig.fDualLinkConnector = 1;
}
break;
if (is_dp)
args.v3.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
if (is_dp)
args.v3.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.ucLaneNum = 8;
else
args.v3.ucLaneNum = 4;
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v3.acConfig.fCoherentMode = 1;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.acConfig.fDualLinkConnector = 1;
}
break;
if (is_dp)
args.v4.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
if (is_dp)
args.v4.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.ucLaneNum = 8;
else
args.v4.ucLaneNum = 4;
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v4.acConfig.fCoherentMode = 1;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.acConfig.fDualLinkConnector = 1;
}
break;
if (dp_clock == 270000)
args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
- } else if (radeon_encoder->pixel_clock > 165000)
+ } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.sDigEncoder.ucLaneNum = 8;
else
args.v1.sDigEncoder.ucLaneNum = 4;
else if (dp_clock == 540000)
args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
- } else if (radeon_encoder->pixel_clock > 165000)
+ } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.sExtEncoder.ucLaneNum = 8;
else
args.v3.sExtEncoder.ucLaneNum = 4;
switch (mode) {
case DRM_MODE_DPMS_ON:
/* some early dce3.2 boards have a bug in their transmitter control table */
- if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) ||
+ ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
else
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
ATOM_TRANSMITTER_ACTION_POWER_ON);
radeon_dig_connector->edp_on = true;
}
- if (ASIC_IS_DCE4(rdev))
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
radeon_dp_link_train(encoder, connector);
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ else
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- if (ASIC_IS_DCE4(rdev)) {
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+ if (!connector)
+ dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+ else
+ dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
+
+ /* setup and enable the encoder */
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+ atombios_dig_encoder_setup(encoder,
+ ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
+ dig->panel_mode);
+ } else if (ASIC_IS_DCE4(rdev)) {
/* disable the transmitter */
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
/* setup and enable the encoder */
#endif
WREG32(CP_RB_CNTL, tmp);
WREG32(CP_SEM_WAIT_TIMER, 0x0);
+ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */
WREG32(CP_RB_WPTR_DELAY, 0);
#define CP_RB_WPTR_ADDR_HI 0xC11C
#define CP_RB_WPTR_DELAY 0x8704
#define CP_SEM_WAIT_TIMER 0x85BC
+#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8
#define CP_DEBUG 0xC1FC
RREG32(GRBM_SOFT_RESET);
WREG32(CP_SEM_WAIT_TIMER, 0x0);
+ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */
WREG32(CP_RB_WPTR_DELAY, 0);
#define SCRATCH_UMSK 0x8540
#define SCRATCH_ADDR 0x8544
#define CP_SEM_WAIT_TIMER 0x85BC
+#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8
#define CP_COHER_CNTL2 0x85E8
#define CP_ME_CNTL 0x86D8
#define CP_ME_HALT (1 << 28)
bool radeon_get_bios(struct radeon_device *rdev);
+/*
+ * Mutex which allows recursive locking from the same process.
+ */
+struct radeon_mutex {
+ struct mutex mutex;
+ struct task_struct *owner;
+ int level;
+};
+
+static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+{
+ mutex_init(&mutex->mutex);
+ mutex->owner = NULL;
+ mutex->level = 0;
+}
+
+static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+{
+ if (mutex_trylock(&mutex->mutex)) {
+ /* The mutex was unlocked before, so it's ours now */
+ mutex->owner = current;
+ } else if (mutex->owner != current) {
+ /* Another process locked the mutex, take it */
+ mutex_lock(&mutex->mutex);
+ mutex->owner = current;
+ }
+ /* Otherwise the mutex was already locked by this process */
+
+ mutex->level++;
+}
+
+static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+{
+ if (--mutex->level > 0)
+ return;
+
+ mutex->owner = NULL;
+ mutex_unlock(&mutex->mutex);
+}
+
+
/*
* Dummy page
*/
* mutex protects scheduled_ibs, ready, alloc_bm
*/
struct radeon_ib_pool {
- struct mutex mutex;
+ struct radeon_mutex mutex;
struct radeon_sa_manager sa_manager;
struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
bool ready;
};
-/*
- * Mutex which allows recursive locking from the same process.
- */
-struct radeon_mutex {
- struct mutex mutex;
- struct task_struct *owner;
- int level;
-};
-
-static inline void radeon_mutex_init(struct radeon_mutex *mutex)
-{
- mutex_init(&mutex->mutex);
- mutex->owner = NULL;
- mutex->level = 0;
-}
-
-static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
-{
- if (mutex_trylock(&mutex->mutex)) {
- /* The mutex was unlocked before, so it's ours now */
- mutex->owner = current;
- } else if (mutex->owner != current) {
- /* Another process locked the mutex, take it */
- mutex_lock(&mutex->mutex);
- mutex->owner = current;
- }
- /* Otherwise the mutex was already locked by this process */
-
- mutex->level++;
-}
-
-static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
-{
- if (--mutex->level > 0)
- return;
-
- mutex->owner = NULL;
- mutex_unlock(&mutex->mutex);
-}
-
-
/*
* Core structure, functions and helpers.
*/
}
obj = (union acpi_object *)buffer.pointer;
- memcpy(bios+offset, obj->buffer.pointer, len);
+ memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
kfree(buffer.pointer);
- return len;
+ return obj->buffer.length;
}
bool radeon_atrm_supported(struct pci_dev *pdev)
ret = radeon_atrm_get_bios_chunk(rdev->bios,
(i * ATRM_BIOS_PAGE),
ATRM_BIOS_PAGE);
- if (ret <= 0)
+ if (ret < ATRM_BIOS_PAGE)
break;
}
/* mutex initialization are all done here so we
* can recall function without having locking issues */
radeon_mutex_init(&rdev->cs_mutex);
- mutex_init(&rdev->ib_pool.mutex);
+ radeon_mutex_init(&rdev->ib_pool.mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(&rdev->ring[i].mutex);
mutex_init(&rdev->dc_hw_i2c_mutex);
radeon_fbdev_set_suspend(rdev, 0);
console_unlock();
- /* init dig PHYs */
- if (rdev->is_atom_bios)
+ /* init dig PHYs, disp eng pll */
+ if (rdev->is_atom_bios) {
radeon_atom_encoder_init(rdev);
+ radeon_atom_dcpll_init(rdev);
+ }
/* reset hpd state */
radeon_hpd_init(rdev);
/* blat the mode back in */
return ret;
}
- /* init dig PHYs */
- if (rdev->is_atom_bios)
+ /* init dig PHYs, disp eng pll */
+ if (rdev->is_atom_bios) {
radeon_atom_encoder_init(rdev);
+ radeon_atom_dcpll_init(rdev);
+ }
/* initialize hpd */
radeon_hpd_init(rdev);
return NULL;
}
+struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct drm_connector *connector;
+ struct radeon_connector *radeon_connector;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ radeon_connector = to_radeon_connector(connector);
+ if (radeon_encoder->devices & radeon_connector->devices)
+ return connector;
+ }
+ return NULL;
+}
+
struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
}
+bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
+ u32 pixel_clock)
+{
+ struct drm_device *dev = encoder->dev;
+ struct radeon_device *rdev = dev->dev_private;
+ struct drm_connector *connector;
+ struct radeon_connector *radeon_connector;
+ struct radeon_connector_atom_dig *dig_connector;
+
+ connector = radeon_get_connector_for_encoder(encoder);
+ /* if we don't have an active device yet, just use one of
+ * the connectors tied to the encoder.
+ */
+ if (!connector)
+ connector = radeon_get_connector_for_encoder_init(encoder);
+ radeon_connector = to_radeon_connector(connector);
+
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_DVII:
+ case DRM_MODE_CONNECTOR_HDMIB:
+ if (radeon_connector->use_digital) {
+ /* HDMI 1.3 supports up to 340 Mhz over single link */
+ if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (pixel_clock > 340000)
+ return true;
+ else
+ return false;
+ } else {
+ if (pixel_clock > 165000)
+ return true;
+ else
+ return false;
+ }
+ } else
+ return false;
+ case DRM_MODE_CONNECTOR_DVID:
+ case DRM_MODE_CONNECTOR_HDMIA:
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ dig_connector = radeon_connector->con_priv;
+ if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+ (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+ return false;
+ else {
+ /* HDMI 1.3 supports up to 340 Mhz over single link */
+ if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (pixel_clock > 340000)
+ return true;
+ else
+ return false;
+ } else {
+ if (pixel_clock > 165000)
+ return true;
+ else
+ return false;
+ }
+ }
+ default:
+ return false;
+ }
+}
+
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
+ i2c->adapter.dev.parent = &dev->pdev->dev;
i2c->dev = dev;
i2c_set_adapdata(&i2c->adapter, i2c);
if (rec->mm_i2c ||
(rdev->pdev->subsystem_device == 0x30c2))
return true;
+ /* Dell RS690 only seems to work with MSIs. */
+ if ((rdev->pdev->device == 0x791f) &&
+ (rdev->pdev->subsystem_vendor == 0x1028) &&
+ (rdev->pdev->subsystem_device == 0x01fc))
+ return true;
+
/* Dell RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x1028) &&
struct backlight_device *bl_dev;
int dpms_mode;
uint8_t backlight_level;
+ int panel_mode;
};
struct radeon_encoder_atom_dac {
extern struct drm_connector *
radeon_get_connector_for_encoder(struct drm_encoder *encoder);
+extern struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder);
+extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
+ u32 pixel_clock);
extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
+extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
+ struct drm_connector *connector);
extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
extern void radeon_atom_encoder_init(struct radeon_device *rdev);
+extern void radeon_atom_dcpll_init(struct radeon_device *rdev);
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
int action, uint8_t lane_num,
uint8_t lane_set);
return r;
}
- mutex_lock(&rdev->ib_pool.mutex);
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
idx = rdev->ib_pool.head_id;
retry:
if (cretry > 5) {
dev_err(rdev->dev, "failed to get an ib after 5 retry\n");
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_fence_unref(&fence);
return -ENOMEM;
}
*/
rdev->ib_pool.head_id = (1 + idx);
rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1);
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
return 0;
}
}
}
idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_fence_unref(&fence);
return r;
}
if (tmp == NULL) {
return;
}
- mutex_lock(&rdev->ib_pool.mutex);
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
if (tmp->fence && !tmp->fence->emitted) {
radeon_sa_bo_free(rdev, &tmp->sa_bo);
radeon_fence_unref(&tmp->fence);
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
}
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
int radeon_ib_pool_init(struct radeon_device *rdev)
{
+ struct radeon_sa_manager tmp;
int i, r;
- mutex_lock(&rdev->ib_pool.mutex);
- if (rdev->ib_pool.ready) {
- mutex_unlock(&rdev->ib_pool.mutex);
- return 0;
- }
-
- r = radeon_sa_bo_manager_init(rdev, &rdev->ib_pool.sa_manager,
+ r = radeon_sa_bo_manager_init(rdev, &tmp,
RADEON_IB_POOL_SIZE*64*1024,
RADEON_GEM_DOMAIN_GTT);
if (r) {
- mutex_unlock(&rdev->ib_pool.mutex);
return r;
}
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
+ if (rdev->ib_pool.ready) {
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_sa_bo_manager_fini(rdev, &tmp);
+ return 0;
+ }
+
+ rdev->ib_pool.sa_manager = tmp;
+ INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo);
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
rdev->ib_pool.ibs[i].fence = NULL;
rdev->ib_pool.ibs[i].idx = i;
if (radeon_debugfs_ring_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for rings !\n");
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
return 0;
}
{
unsigned i;
- mutex_lock(&rdev->ib_pool.mutex);
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
if (rdev->ib_pool.ready) {
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo);
radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager);
rdev->ib_pool.ready = false;
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
}
int radeon_ib_pool_start(struct radeon_device *rdev)
static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
{
drm_sis_private_t *dev_priv;
- int ret;
dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
if (dev_priv == NULL)
dev_priv->chipset = chipset;
idr_init(&dev->object_name_idr);
- return ret;
+ return 0;
}
static int sis_driver_unload(struct drm_device *dev)
}
}
+ if (bdev->driver->move_notify)
+ bdev->driver->move_notify(bo, mem);
+
if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem);
else
ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem);
- if (ret)
- goto out_err;
+ if (ret) {
+ if (bdev->driver->move_notify) {
+ struct ttm_mem_reg tmp_mem = *mem;
+ *mem = bo->mem;
+ bo->mem = tmp_mem;
+ bdev->driver->move_notify(bo, mem);
+ bo->mem = *mem;
+ }
- if (bdev->driver->move_notify)
- bdev->driver->move_notify(bo, mem);
+ goto out_err;
+ }
moved:
if (bo->evicted) {
unsigned int *handle)
{
if (handle)
- handle = 0;
+ *handle = 0;
return 0;
}
return 0;
}
-
+EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
static int __init intel_idle_init(void)
{
This option enables support for on-chip LED drivers on
MAXIM MAX8997 PMIC.
+config LEDS_OT200
+ tristate "LED support for the Bachmann OT200"
+ depends on LEDS_CLASS && HAS_IOMEM
+ help
+ This option enables support for the LEDs on the Bachmann OT200.
+ Say Y to enable LEDs on the Bachmann OT200.
+
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on LEDS_CLASS
obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
+obj-$(CONFIG_LEDS_OT200) += leds-ot200.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
--- /dev/null
+/*
+ * Bachmann ot200 leds driver.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * Christian Gmeiner <christian.gmeiner@gmail.com>
+ *
+ * License: GPL as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+
+struct ot200_led {
+ struct led_classdev cdev;
+ const char *name;
+ unsigned long port;
+ u8 mask;
+};
+
+/*
+ * The device has three leds on the back panel (led_err, led_init and led_run)
+ * and can handle up to seven leds on the front panel.
+ */
+
+static struct ot200_led leds[] = {
+ {
+ .name = "led_run",
+ .port = 0x5a,
+ .mask = BIT(0),
+ },
+ {
+ .name = "led_init",
+ .port = 0x5a,
+ .mask = BIT(1),
+ },
+ {
+ .name = "led_err",
+ .port = 0x5a,
+ .mask = BIT(2),
+ },
+ {
+ .name = "led_1",
+ .port = 0x49,
+ .mask = BIT(7),
+ },
+ {
+ .name = "led_2",
+ .port = 0x49,
+ .mask = BIT(6),
+ },
+ {
+ .name = "led_3",
+ .port = 0x49,
+ .mask = BIT(5),
+ },
+ {
+ .name = "led_4",
+ .port = 0x49,
+ .mask = BIT(4),
+ },
+ {
+ .name = "led_5",
+ .port = 0x49,
+ .mask = BIT(3),
+ },
+ {
+ .name = "led_6",
+ .port = 0x49,
+ .mask = BIT(2),
+ },
+ {
+ .name = "led_7",
+ .port = 0x49,
+ .mask = BIT(1),
+ }
+};
+
+static DEFINE_SPINLOCK(value_lock);
+
+/*
+ * we need to store the current led states, as it is not
+ * possible to read the current led state via inb().
+ */
+static u8 leds_back;
+static u8 leds_front;
+
+static void ot200_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev);
+ u8 *val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&value_lock, flags);
+
+ if (led->port == 0x49)
+ val = &leds_front;
+ else if (led->port == 0x5a)
+ val = &leds_back;
+ else
+ BUG();
+
+ if (value == LED_OFF)
+ *val &= ~led->mask;
+ else
+ *val |= led->mask;
+
+ outb(*val, led->port);
+ spin_unlock_irqrestore(&value_lock, flags);
+}
+
+static int __devinit ot200_led_probe(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(leds); i++) {
+
+ leds[i].cdev.name = leds[i].name;
+ leds[i].cdev.brightness_set = ot200_led_brightness_set;
+
+ ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
+ if (ret < 0)
+ goto err;
+ }
+
+ leds_front = 0; /* turn off all front leds */
+ leds_back = BIT(1); /* turn on init led */
+ outb(leds_front, 0x49);
+ outb(leds_back, 0x5a);
+
+ return 0;
+
+err:
+ for (i = i - 1; i >= 0; i--)
+ led_classdev_unregister(&leds[i].cdev);
+
+ return ret;
+}
+
+static int __devexit ot200_led_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(leds); i++)
+ led_classdev_unregister(&leds[i].cdev);
+
+ return 0;
+}
+
+static struct platform_driver ot200_led_driver = {
+ .probe = ot200_led_probe,
+ .remove = __devexit_p(ot200_led_remove),
+ .driver = {
+ .name = "leds-ot200",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(ot200_led_driver);
+
+MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("ot200 LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-ot200");
/* attach demod */
adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
- &anysee_cxd2820r_config, &adap->dev->i2c_adap,
- NULL);
+ &anysee_cxd2820r_config, &adap->dev->i2c_adap);
state->has_ci = true;
if (ret)
return ret;
+ ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 2)|(0 << 1)|(0 << 0), 0x07);
+ if (ret)
+ return ret;
+
+ ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 2)|(1 << 1)|(1 << 0), 0x07);
+ if (ret)
+ return ret;
+
ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
if (ret)
return ret;
param.flags = 0;
switch (fep->bandwidth_hz) {
+ default:
case 8000000:
- param.bandwidth = 0;
+ param.bandwidth = 8;
break;
case 7000000:
- param.bandwidth = 1;
+ param.bandwidth = 7;
break;
case 6000000:
- param.bandwidth = 2;
+ param.bandwidth = 6;
break;
}
(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
extern struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend *fe
+ struct i2c_adapter *i2c
);
#else
static inline struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend *fe
+ struct i2c_adapter *i2c
)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
/* switch between DVB-T and DVB-T2 when tune fails */
if (priv->last_tune_failed) {
- if (priv->delivery_system == SYS_DVBT)
+ if (priv->delivery_system == SYS_DVBT) {
+ ret = cxd2820r_sleep_t(fe);
+ if (ret)
+ goto error;
+
c->delivery_system = SYS_DVBT2;
- else if (priv->delivery_system == SYS_DVBT2)
+ } else if (priv->delivery_system == SYS_DVBT2) {
+ ret = cxd2820r_sleep_t2(fe);
+ if (ret)
+ goto error;
+
c->delivery_system = SYS_DVBT;
+ }
}
/* set frontend */
.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
/* default: DVB-T/T2 */
.info = {
- .name = "Sony CXD2820R (DVB-T/T2)",
+ .name = "Sony CXD2820R",
.caps = FE_CAN_FEC_1_2 |
FE_CAN_FEC_2_3 |
FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_QAM_16 |
+ FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
+ FE_CAN_QAM_128 |
FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
};
struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
- struct i2c_adapter *i2c,
- struct dvb_frontend *fe)
+ struct i2c_adapter *i2c)
{
struct cxd2820r_priv *priv = NULL;
int ret;
isi->fb_descriptors_phys);
iounmap(isi->regs);
+ clk_unprepare(isi->mck);
clk_put(isi->mck);
+ clk_unprepare(isi->pclk);
clk_put(isi->pclk);
kfree(isi);
if (IS_ERR(pclk))
return PTR_ERR(pclk);
+ ret = clk_prepare(pclk);
+ if (ret)
+ goto err_clk_prepare_pclk;
+
isi = kzalloc(sizeof(struct atmel_isi), GFP_KERNEL);
if (!isi) {
ret = -ENOMEM;
goto err_clk_get;
}
+ ret = clk_prepare(isi->mck);
+ if (ret)
+ goto err_clk_prepare_mck;
+
/* Set ISI_MCK's frequency, it should be faster than pixel clock */
ret = clk_set_rate(isi->mck, pdata->mck_hz);
if (ret < 0)
isi->fb_descriptors_phys);
err_alloc_descriptors:
err_set_mck_rate:
+ clk_unprepare(isi->mck);
+err_clk_prepare_mck:
clk_put(isi->mck);
err_clk_get:
kfree(isi);
err_alloc_isi:
+ clk_unprepare(pclk);
+err_clk_prepare_pclk:
clk_put(pclk);
return ret;
case EM28174_BOARD_PCTV_290E:
dvb->fe[0] = dvb_attach(cxd2820r_attach,
&em28xx_cxd2820r_config,
- &dev->i2c_adap,
- NULL);
+ &dev->i2c_adap);
if (dvb->fe[0]) {
/* FE 0 attach tuner */
if (!dvb_attach(tda18271_attach,
#define to_mcp(d) container_of(d, struct mcp, attached_device)
#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
-static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id,
- const char *codec)
-{
- while (id->name[0]) {
- if (strcmp(codec, id->name) == 0)
- return id;
- id++;
- }
- return NULL;
-}
-
-const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp)
-{
- const struct mcp_driver *driver =
- to_mcp_driver(mcp->attached_device.driver);
-
- return mcp_match_id(driver->id_table, mcp->codec);
-}
-EXPORT_SYMBOL(mcp_get_device_id);
-
static int mcp_bus_match(struct device *dev, struct device_driver *drv)
{
- const struct mcp *mcp = to_mcp(dev);
- const struct mcp_driver *driver = to_mcp_driver(drv);
-
- if (driver->id_table)
- return !!mcp_match_id(driver->id_table, mcp->codec);
-
- return 0;
+ return 1;
}
static int mcp_bus_probe(struct device *dev)
return ret;
}
-static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct mcp *mcp = to_mcp(dev);
-
- add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec);
- return 0;
-}
-
static struct bus_type mcp_bus_type = {
.name = "mcp",
.match = mcp_bus_match,
- .uevent = mcp_bus_uevent,
.probe = mcp_bus_probe,
.remove = mcp_bus_remove,
.suspend = mcp_bus_suspend,
*/
void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
{
- spin_lock_irq(&mcp->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
mcp->ops->set_telecom_divisor(mcp, div);
- spin_unlock_irq(&mcp->lock);
+ spin_unlock_irqrestore(&mcp->lock, flags);
}
EXPORT_SYMBOL(mcp_set_telecom_divisor);
*/
void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
{
- spin_lock_irq(&mcp->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
mcp->ops->set_audio_divisor(mcp, div);
- spin_unlock_irq(&mcp->lock);
+ spin_unlock_irqrestore(&mcp->lock, flags);
}
EXPORT_SYMBOL(mcp_set_audio_divisor);
*/
void mcp_enable(struct mcp *mcp)
{
- spin_lock_irq(&mcp->lock);
+ unsigned long flags;
+ spin_lock_irqsave(&mcp->lock, flags);
if (mcp->use_count++ == 0)
mcp->ops->enable(mcp);
- spin_unlock_irq(&mcp->lock);
+ spin_unlock_irqrestore(&mcp->lock, flags);
}
EXPORT_SYMBOL(mcp_enable);
}
EXPORT_SYMBOL(mcp_host_alloc);
-int mcp_host_register(struct mcp *mcp, void *pdata)
+int mcp_host_register(struct mcp *mcp)
{
- if (!mcp->codec)
- return -EINVAL;
-
- mcp->attached_device.platform_data = pdata;
dev_set_name(&mcp->attached_device, "mcp0");
- request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec);
return device_register(&mcp->attached_device);
}
EXPORT_SYMBOL(mcp_host_register);
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mfd/mcp.h>
-#include <linux/io.h>
#include <mach/dma.h>
#include <mach/hardware.h>
#include <asm/system.h>
#include <mach/mcp.h>
-/* Register offsets */
-#define MCCR0 0x00
-#define MCDR0 0x08
-#define MCDR1 0x0C
-#define MCDR2 0x10
-#define MCSR 0x18
-#define MCCR1 0x00
+#include <mach/assabet.h>
+
struct mcp_sa11x0 {
- u32 mccr0;
- u32 mccr1;
- unsigned char *mccr0_base;
- unsigned char *mccr1_base;
+ u32 mccr0;
+ u32 mccr1;
};
#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
static void
mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
{
- struct mcp_sa11x0 *priv = priv(mcp);
+ unsigned int mccr0;
divisor /= 32;
- priv->mccr0 &= ~0x00007f00;
- priv->mccr0 |= divisor << 8;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ mccr0 = Ser4MCCR0 & ~0x00007f00;
+ mccr0 |= divisor << 8;
+ Ser4MCCR0 = mccr0;
}
static void
mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
{
- struct mcp_sa11x0 *priv = priv(mcp);
+ unsigned int mccr0;
divisor /= 32;
- priv->mccr0 &= ~0x0000007f;
- priv->mccr0 |= divisor;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ mccr0 = Ser4MCCR0 & ~0x0000007f;
+ mccr0 |= divisor;
+ Ser4MCCR0 = mccr0;
}
/*
{
int ret = -ETIME;
int i;
- u32 mcpreg;
- struct mcp_sa11x0 *priv = priv(mcp);
- mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff);
- __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
- mcpreg = __raw_readl(priv->mccr0_base + MCSR);
- if (mcpreg & MCSR_CWC) {
+ if (Ser4MCSR & MCSR_CWC) {
ret = 0;
break;
}
{
int ret = -ETIME;
int i;
- u32 mcpreg;
- struct mcp_sa11x0 *priv = priv(mcp);
- mcpreg = reg << 17 | MCDR2_Rd;
- __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
+ Ser4MCDR2 = reg << 17 | MCDR2_Rd;
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
- mcpreg = __raw_readl(priv->mccr0_base + MCSR);
- if (mcpreg & MCSR_CRC) {
- ret = __raw_readl(priv->mccr0_base + MCDR2)
- & 0xffff;
+ if (Ser4MCSR & MCSR_CRC) {
+ ret = Ser4MCDR2 & 0xffff;
break;
}
}
static void mcp_sa11x0_enable(struct mcp *mcp)
{
- struct mcp_sa11x0 *priv = priv(mcp);
-
- __raw_writel(-1, priv->mccr0_base + MCSR);
- priv->mccr0 |= MCCR0_MCE;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ Ser4MCSR = -1;
+ Ser4MCCR0 |= MCCR0_MCE;
}
static void mcp_sa11x0_disable(struct mcp *mcp)
{
- struct mcp_sa11x0 *priv = priv(mcp);
-
- priv->mccr0 &= ~MCCR0_MCE;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ Ser4MCCR0 &= ~MCCR0_MCE;
}
/*
struct mcp_plat_data *data = pdev->dev.platform_data;
struct mcp *mcp;
int ret;
- struct mcp_sa11x0 *priv;
- struct resource *res_mem0, *res_mem1;
- u32 size0, size1;
if (!data)
return -ENODEV;
- if (!data->codec)
- return -ENODEV;
-
- res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res_mem0)
- return -ENODEV;
- size0 = res_mem0->end - res_mem0->start + 1;
-
- res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res_mem1)
- return -ENODEV;
- size1 = res_mem1->end - res_mem1->start + 1;
-
- if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp"))
+ if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
return -EBUSY;
- if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) {
- ret = -EBUSY;
- goto release;
- }
-
mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
if (!mcp) {
ret = -ENOMEM;
- goto release2;
+ goto release;
}
- priv = priv(mcp);
-
mcp->owner = THIS_MODULE;
mcp->ops = &mcp_sa11x0;
mcp->sclk_rate = data->sclk_rate;
- mcp->dma_audio_rd = DDAR_DevAdd(res_mem0->start + MCDR0)
- + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
- mcp->dma_audio_wr = DDAR_DevAdd(res_mem0->start + MCDR0)
- + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
- mcp->dma_telco_rd = DDAR_DevAdd(res_mem0->start + MCDR1)
- + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
- mcp->dma_telco_wr = DDAR_DevAdd(res_mem0->start + MCDR1)
- + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
- mcp->codec = data->codec;
+ mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
+ mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
+ mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
+ mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
+ mcp->gpio_base = data->gpio_base;
platform_set_drvdata(pdev, mcp);
+ if (machine_is_assabet()) {
+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+ }
+
+ /*
+ * Setup the PPC unit correctly.
+ */
+ PPDR &= ~PPC_RXD4;
+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+ PSDR |= PPC_RXD4;
+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
/*
* Initialise device. Note that we initially
* set the sampling rate to minimum.
*/
- priv->mccr0_base = ioremap(res_mem0->start, size0);
- priv->mccr1_base = ioremap(res_mem1->start, size1);
-
- __raw_writel(-1, priv->mccr0_base + MCSR);
- priv->mccr1 = data->mccr1;
- priv->mccr0 = data->mccr0 | 0x7f7f;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
- __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
+ Ser4MCSR = -1;
+ Ser4MCCR1 = data->mccr1;
+ Ser4MCCR0 = data->mccr0 | 0x7f7f;
/*
* Calculate the read/write timeout (us) from the bit clock
mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
mcp->sclk_rate;
- ret = mcp_host_register(mcp, data->codec_pdata);
+ ret = mcp_host_register(mcp);
if (ret == 0)
goto out;
- release2:
- release_mem_region(res_mem1->start, size1);
release:
- release_mem_region(res_mem0->start, size0);
+ release_mem_region(0x80060000, 0x60);
platform_set_drvdata(pdev, NULL);
out:
return ret;
}
-static int mcp_sa11x0_remove(struct platform_device *pdev)
+static int mcp_sa11x0_remove(struct platform_device *dev)
{
- struct mcp *mcp = platform_get_drvdata(pdev);
- struct mcp_sa11x0 *priv = priv(mcp);
- struct resource *res_mem;
- u32 size;
+ struct mcp *mcp = platform_get_drvdata(dev);
- platform_set_drvdata(pdev, NULL);
+ platform_set_drvdata(dev, NULL);
mcp_host_unregister(mcp);
+ release_mem_region(0x80060000, 0x60);
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res_mem) {
- size = res_mem->end - res_mem->start + 1;
- release_mem_region(res_mem->start, size);
- }
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res_mem) {
- size = res_mem->end - res_mem->start + 1;
- release_mem_region(res_mem->start, size);
- }
- iounmap(priv->mccr0_base);
- iounmap(priv->mccr1_base);
return 0;
}
static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
{
struct mcp *mcp = platform_get_drvdata(dev);
- struct mcp_sa11x0 *priv = priv(mcp);
- u32 mccr0;
- mccr0 = priv->mccr0 & ~MCCR0_MCE;
- __raw_writel(mccr0, priv->mccr0_base + MCCR0);
+ priv(mcp)->mccr0 = Ser4MCCR0;
+ priv(mcp)->mccr1 = Ser4MCCR1;
+ Ser4MCCR0 &= ~MCCR0_MCE;
return 0;
}
static int mcp_sa11x0_resume(struct platform_device *dev)
{
struct mcp *mcp = platform_get_drvdata(dev);
- struct mcp_sa11x0 *priv = priv(mcp);
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
- __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
+ Ser4MCCR1 = priv(mcp)->mccr1;
+ Ser4MCCR0 = priv(mcp)->mccr0;
return 0;
}
.resume = mcp_sa11x0_resume,
.driver = {
.name = "sa11x0-mcp",
- .owner = THIS_MODULE,
},
};
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
-static struct mcp_device_id ucb1x00_id[] = {
- { "ucb1x00", 0 }, /* auto-detection */
- { "ucb1200", UCB_ID_1200 },
- { "ucb1300", UCB_ID_1300 },
- { "tc35143", UCB_ID_TC35143 },
- { }
-};
-MODULE_DEVICE_TABLE(mcp, ucb1x00_id);
-
/**
* ucb1x00_io_set_dir - set IO direction
* @ucb: UCB1x00 structure describing chip
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
unsigned long flags;
+ unsigned old, mask = 1 << offset;
spin_lock_irqsave(&ucb->io_lock, flags);
- ucb->io_dir |= (1 << offset);
- ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
-
+ old = ucb->io_out;
if (value)
- ucb->io_out |= 1 << offset;
+ ucb->io_out |= mask;
else
- ucb->io_out &= ~(1 << offset);
- ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+ ucb->io_out &= ~mask;
+
+ if (old != ucb->io_out)
+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+
+ if (!(ucb->io_dir & mask)) {
+ ucb->io_dir |= mask;
+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+ }
spin_unlock_irqrestore(&ucb->io_lock, flags);
return 0;
static int ucb1x00_probe(struct mcp *mcp)
{
- const struct mcp_device_id *mid;
struct ucb1x00 *ucb;
struct ucb1x00_driver *drv;
- struct ucb1x00_plat_data *pdata;
unsigned int id;
int ret = -ENODEV;
int temp;
mcp_enable(mcp);
id = mcp_reg_read(mcp, UCB_ID);
- mid = mcp_get_device_id(mcp);
- if (mid && mid->driver_data) {
- if (id != mid->driver_data) {
- printk(KERN_WARNING "%s wrong ID %04x found: %04x\n",
- mid->name, (unsigned int) mid->driver_data, id);
- goto err_disable;
- }
- } else {
- mid = &ucb1x00_id[1];
- while (mid->driver_data) {
- if (id == mid->driver_data)
- break;
- mid++;
- }
- printk(KERN_WARNING "%s ID not found: %04x\n",
- ucb1x00_id[0].name, id);
+ if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
goto err_disable;
}
if (!ucb)
goto err_disable;
- pdata = mcp->attached_device.platform_data;
+
ucb->dev.class = &ucb1x00_class;
ucb->dev.parent = &mcp->attached_device;
- dev_set_name(&ucb->dev, mid->name);
+ dev_set_name(&ucb->dev, "ucb1x00");
spin_lock_init(&ucb->lock);
spin_lock_init(&ucb->io_lock);
sema_init(&ucb->adc_sem, 1);
- ucb->id = mid;
+ ucb->id = id;
ucb->mcp = mcp;
ucb->irq = ucb1x00_detect_irq(ucb);
if (ucb->irq == NO_IRQ) {
- printk(KERN_ERR "%s: IRQ probe failed\n", mid->name);
+ printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
ret = -ENODEV;
goto err_free;
}
ucb->gpio.base = -1;
- if (pdata && (pdata->gpio_base >= 0)) {
+ if (mcp->gpio_base != 0) {
ucb->gpio.label = dev_name(&ucb->dev);
- ucb->gpio.base = pdata->gpio_base;
+ ucb->gpio.base = mcp->gpio_base;
ucb->gpio.ngpio = 10;
ucb->gpio.set = ucb1x00_gpio_set;
ucb->gpio.get = ucb1x00_gpio_get;
dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
- mid->name, ucb);
+ "UCB1x00", ucb);
if (ret) {
- printk(KERN_ERR "%s: unable to grab irq%d: %d\n",
- mid->name, ucb->irq, ret);
+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
+ ucb->irq, ret);
goto err_gpio;
}
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev;
+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
.remove = ucb1x00_remove,
.suspend = ucb1x00_suspend,
.resume = ucb1x00_resume,
- .id_table = ucb1x00_id,
};
static int __init ucb1x00_init(void)
u16 x_res;
u16 y_res;
- unsigned int restart:1;
unsigned int adcsync:1;
};
{
struct ucb1x00_ts *ts = _ts;
DECLARE_WAITQUEUE(wait, current);
+ bool frozen, ignore = false;
int valid = 0;
set_freezable();
add_wait_queue(&ts->irq_wait, &wait);
- while (!kthread_should_stop()) {
+ while (!kthread_freezable_should_stop(&frozen)) {
unsigned int x, y, p;
signed long timeout;
- ts->restart = 0;
+ if (frozen)
+ ignore = true;
ucb1x00_adc_enable(ts->ucb);
* space. We therefore leave it to user space
* to do any filtering they please.
*/
- if (!ts->restart) {
+ if (!ignore) {
ucb1x00_ts_evt_add(ts, p, x, y);
valid = 1;
}
timeout = HZ / 100;
}
- try_to_freeze();
-
schedule_timeout(timeout);
}
ucb1x00_disable(ts->ucb);
}
-#ifdef CONFIG_PM
-static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
-{
- struct ucb1x00_ts *ts = dev->priv;
-
- if (ts->rtask != NULL) {
- /*
- * Restart the TS thread to ensure the
- * TS interrupt mode is set up again
- * after sleep.
- */
- ts->restart = 1;
- wake_up(&ts->irq_wait);
- }
- return 0;
-}
-#else
-#define ucb1x00_ts_resume NULL
-#endif
-
/*
* Initialisation.
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
idev->name = "Touchscreen panel";
- idev->id.product = ts->ucb->id->driver_data;
+ idev->id.product = ts->ucb->id;
idev->open = ucb1x00_ts_open;
idev->close = ucb1x00_ts_close;
static struct ucb1x00_driver ucb1x00_ts_driver = {
.add = ucb1x00_ts_add,
.remove = ucb1x00_ts_remove,
- .resume = ucb1x00_ts_resume,
};
static int __init ucb1x00_ts_init(void)
}
}
-/* hw is a boolean parameter that determines whether we should try and
- * set the hw address of the device as well as the hw address of the
- * net_device
- */
-static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
{
struct net_device *dev = slave->dev;
struct sockaddr s_addr;
- if (!hw) {
+ if (slave->bond->params.mode == BOND_MODE_TLB) {
memcpy(dev->dev_addr, addr, dev->addr_len);
return 0;
}
u8 tmp_mac_addr[ETH_ALEN];
memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
- alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
- alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
+ alb_set_slave_mac_addr(slave2, tmp_mac_addr);
}
/* Try setting slave mac to bond address and fall-through
to code handling that situation below... */
- alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, bond->dev->dev_addr);
}
/* The slave's address is equal to the address of the bond.
}
if (free_mac_slave) {
- alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
bond->dev->name, slave->dev->name,
{
int res;
- res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
if (res) {
return res;
}
alb_swap_mac_addr(bond, swap_slave, new_slave);
} else {
/* set the new_slave to the bond mac address */
- alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
}
if (swap_slave) {
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
} else {
- alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
read_lock(&bond->lock);
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
if (ret >= 0) {
- ret &= 0xfff0;
- if (ret == 0x1210)
+ if (ret == 0x1212)
+ return "Marvell 88E6123 (A1)";
+ if (ret == 0x1213)
+ return "Marvell 88E6123 (A2)";
+ if ((ret & 0xfff0) == 0x1210)
return "Marvell 88E6123";
- if (ret == 0x1610)
+
+ if (ret == 0x1612)
+ return "Marvell 88E6161 (A1)";
+ if (ret == 0x1613)
+ return "Marvell 88E6161 (A2)";
+ if ((ret & 0xfff0) == 0x1610)
return "Marvell 88E6161";
- if (ret == 0x1650)
+
+ if (ret == 0x1652)
+ return "Marvell 88E6165 (A1)";
+ if (ret == 0x1653)
+ return "Marvell 88e6165 (A2)";
+ if ((ret & 0xfff0) == 0x1650)
return "Marvell 88E6165";
}
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
int rx_ring_size = 0;
#ifdef BCM_CNIC
- if (IS_MF_ISCSI_SD(bp)) {
+ if (!bp->rx_ring_size && IS_MF_ISCSI_SD(bp)) {
rx_ring_size = MIN_RX_SIZE_NONTPA;
bp->rx_ring_size = rx_ring_size;
} else
struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
- u16 pkt_prod, bd_prod, rx_comp_cons;
+ u16 pkt_prod, bd_prod;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
- rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
- cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
+ cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
case ETH_SS_STATS:
if (is_multi(bp)) {
num_stats = bnx2x_num_stat_queues(bp) *
- BNX2X_NUM_Q_STATS;
- if (!IS_MF_MODE_STAT(bp))
- num_stats += BNX2X_NUM_STATS;
- } else {
- if (IS_MF_MODE_STAT(bp)) {
- num_stats = 0;
- for (i = 0; i < BNX2X_NUM_STATS; i++)
- if (IS_FUNC_STAT(i))
- num_stats++;
- } else
- num_stats = BNX2X_NUM_STATS;
- }
+ BNX2X_NUM_Q_STATS;
+ } else
+ num_stats = 0;
+ if (IS_MF_MODE_STAT(bp)) {
+ for (i = 0; i < BNX2X_NUM_STATS; i++)
+ if (IS_FUNC_STAT(i))
+ num_stats++;
+ } else
+ num_stats += BNX2X_NUM_STATS;
+
return num_stats;
case ETH_SS_TEST:
switch (stringset) {
case ETH_SS_STATS:
+ k = 0;
if (is_multi(bp)) {
- k = 0;
for_each_eth_queue(bp, i) {
memset(queue_name, 0, sizeof(queue_name));
sprintf(queue_name, "%d", i);
queue_name);
k += BNX2X_NUM_Q_STATS;
}
- if (IS_MF_MODE_STAT(bp))
- break;
- for (j = 0; j < BNX2X_NUM_STATS; j++)
- strcpy(buf + (k + j)*ETH_GSTRING_LEN,
- bnx2x_stats_arr[j].string);
- } else {
- for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
- if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
- continue;
- strcpy(buf + j*ETH_GSTRING_LEN,
- bnx2x_stats_arr[i].string);
- j++;
- }
}
+
+
+ for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+ if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
+ continue;
+ strcpy(buf + (k + j)*ETH_GSTRING_LEN,
+ bnx2x_stats_arr[i].string);
+ j++;
+ }
+
break;
case ETH_SS_TEST:
{
struct bnx2x *bp = netdev_priv(dev);
u32 *hw_stats, *offset;
- int i, j, k;
+ int i, j, k = 0;
if (is_multi(bp)) {
- k = 0;
for_each_eth_queue(bp, i) {
hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
}
k += BNX2X_NUM_Q_STATS;
}
- if (IS_MF_MODE_STAT(bp))
- return;
- hw_stats = (u32 *)&bp->eth_stats;
- for (j = 0; j < BNX2X_NUM_STATS; j++) {
- if (bnx2x_stats_arr[j].size == 0) {
- /* skip this counter */
- buf[k + j] = 0;
- continue;
- }
- offset = (hw_stats + bnx2x_stats_arr[j].offset);
- if (bnx2x_stats_arr[j].size == 4) {
- /* 4-byte counter */
- buf[k + j] = (u64) *offset;
- continue;
- }
- /* 8-byte counter */
- buf[k + j] = HILO_U64(*offset, *(offset + 1));
+ }
+
+ hw_stats = (u32 *)&bp->eth_stats;
+ for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+ if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
+ continue;
+ if (bnx2x_stats_arr[i].size == 0) {
+ /* skip this counter */
+ buf[k + j] = 0;
+ j++;
+ continue;
}
- } else {
- hw_stats = (u32 *)&bp->eth_stats;
- for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
- if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
- continue;
- if (bnx2x_stats_arr[i].size == 0) {
- /* skip this counter */
- buf[j] = 0;
- j++;
- continue;
- }
- offset = (hw_stats + bnx2x_stats_arr[i].offset);
- if (bnx2x_stats_arr[i].size == 4) {
- /* 4-byte counter */
- buf[j] = (u64) *offset;
- j++;
- continue;
- }
- /* 8-byte counter */
- buf[j] = HILO_U64(*offset, *(offset + 1));
+ offset = (hw_stats + bnx2x_stats_arr[i].offset);
+ if (bnx2x_stats_arr[i].size == 4) {
+ /* 4-byte counter */
+ buf[k + j] = (u64) *offset;
j++;
+ continue;
}
+ /* 8-byte counter */
+ buf[k + j] = HILO_U64(*offset, *(offset + 1));
+ j++;
}
}
struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j];
BNX2X_ERR("fp%d: rx_bd[%x]=[%x:%x] sw_bd=[%p]\n",
- i, j, rx_bd[1], rx_bd[0], sw_bd->skb);
+ i, j, rx_bd[1], rx_bd[0], sw_bd->data);
}
start = RX_SGE(fp->rx_sge_prod);
{
struct bnx2x *bp;
int rc;
+ bool chip_is_e1x = (board_type == BCM57710 ||
+ board_type == BCM57711 ||
+ board_type == BCM57711E);
SET_NETDEV_DEV(dev, &pdev->dev);
bp = netdev_priv(dev);
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0);
- if (CHIP_IS_E1x(bp)) {
+ if (chip_is_e1x) {
REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0);
* Enable internal target-read (in case we are probed after PF FLR).
* Must be done prior to any BAR read access. Only for 57712 and up
*/
- if (board_type != BCM57710 &&
- board_type != BCM57711 &&
- board_type != BCM57711E)
+ if (!chip_is_e1x)
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
/* Reset the load counter */
int exe_len,
union bnx2x_qable_obj *owner,
exe_q_validate validate,
+ exe_q_remove remove,
exe_q_optimize optimize,
exe_q_execute exec,
exe_q_get get)
/* Owner specific callbacks */
o->validate = validate;
+ o->remove = remove;
o->optimize = optimize;
o->execute = exec;
o->get = get;
}
}
+static int bnx2x_remove_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ int rc = 0;
+
+ /* If consumption wasn't required, nothing to do */
+ if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags))
+ return 0;
+
+ switch (elem->cmd_data.vlan_mac.cmd) {
+ case BNX2X_VLAN_MAC_ADD:
+ case BNX2X_VLAN_MAC_MOVE:
+ rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
+ break;
+ case BNX2X_VLAN_MAC_DEL:
+ rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (rc != true)
+ return -EINVAL;
+
+ return 0;
+}
+
/**
* bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
*
list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
- *vlan_mac_flags)
+ *vlan_mac_flags) {
+ rc = exeq->remove(bp, exeq->owner, exeq_pos);
+ if (rc) {
+ BNX2X_ERR("Failed to remove command\n");
+ return rc;
+ }
list_del(&exeq_pos->link);
+ }
}
spin_unlock_bh(&exeq->lock);
bnx2x_exe_queue_init(bp,
&mac_obj->exe_queue, 1, qable_obj,
bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_mac);
bnx2x_exe_queue_init(bp,
&mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_mac);
bnx2x_exe_queue_init(bp,
&vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan);
bnx2x_exe_queue_init(bp,
&vlan_mac_obj->exe_queue, 1, qable_obj,
bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan_mac);
&vlan_mac_obj->exe_queue,
CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan_mac);
union bnx2x_qable_obj *o,
struct bnx2x_exeq_elem *elem);
+typedef int (*exe_q_remove)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct bnx2x_exeq_elem *elem);
+
/**
* @return positive is entry was optimized, 0 - if not, negative
* in case of an error.
*/
exe_q_validate validate;
+ /**
+ * Called before removing pending commands, cleaning allocated
+ * resources (e.g., credits from validate)
+ */
+ exe_q_remove remove;
/**
* This will try to cancel the current pending commands list
* considering the new command.
*
+ * Returns the number of optimized commands or a negative error code
+ *
* Must run under exe_queue->lock
*/
exe_q_optimize optimize;
iph = ip_hdr(skb);
tcp_opt_len = tcp_optlen(skb);
- if (skb_is_gso_v6(skb)) {
- hdr_len = skb_headlen(skb) - ETH_HLEN;
- } else {
- u32 ip_tcp_len;
-
- ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
- hdr_len = ip_tcp_len + tcp_opt_len;
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;
+ if (!skb_is_gso_v6(skb)) {
iph->check = 0;
iph->tot_len = htons(mss + hdr_len);
}
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.28"
+#define DRV_VERSION "2.1.1.31"
#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
#define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */
#define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */
+#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */
/* Supported devices */
static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
+ { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
{ 0, } /* end of table */
};
return (enic->priv_flags & ENIC_SRIOV_ENABLED) ? 1 : 0;
}
+static int enic_is_sriov_vf(struct enic *enic)
+{
+ return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
+}
+
int enic_is_valid_vf(struct enic *enic, int vf)
{
#ifdef CONFIG_PCI_IOV
if (mtu && mtu != enic->port_mtu) {
enic->port_mtu = mtu;
- if (enic_is_dynamic(enic)) {
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
mtu = max_t(int, ENIC_MIN_MTU,
min_t(int, ENIC_MAX_MTU, mtu));
if (mtu != netdev->mtu)
{
struct enic *enic = netdev_priv(netdev);
- if (enic_is_dynamic(enic)) {
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr))
return -EADDRNOTAVAIL;
} else {
for (i = 0; i < enic->rq_count; i++)
vnic_rq_enable(&enic->rq[i]);
- if (!enic_is_dynamic(enic))
+ if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
enic_dev_add_station_addr(enic);
enic_set_rx_mode(netdev);
netif_carrier_off(netdev);
netif_tx_disable(netdev);
- if (!enic_is_dynamic(enic))
+ if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
enic_dev_del_station_addr(enic);
for (i = 0; i < enic->wq_count; i++) {
if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
return -EINVAL;
- if (enic_is_dynamic(enic))
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
return -EOPNOTSUPP;
if (running)
int using_dac = 0;
unsigned int i;
int err;
- int num_pps = 1;
#ifdef CONFIG_PCI_IOV
int pos = 0;
#endif
+ int num_pps = 1;
/* Allocate net device structure and initialize. Private
* instance data is initialized to zero.
num_pps = enic->num_vfs;
}
}
-
#endif
+
/* Allocate structure for port profiles */
enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL);
if (!enic->pp) {
pr_err("port profile alloc failed, aborting\n");
err = -ENOMEM;
- goto err_out_disable_sriov;
+ goto err_out_disable_sriov_pp;
}
/* Issue device open to get device in known state
err = enic_dev_open(enic);
if (err) {
dev_err(dev, "vNIC dev open failed, aborting\n");
- goto err_out_free_pp;
+ goto err_out_disable_sriov;
}
/* Setup devcmd lock
* called later by an upper layer.
*/
- if (!enic_is_dynamic(enic)) {
+ if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) {
err = vnic_dev_init(enic->vdev, 0);
if (err) {
dev_err(dev, "vNIC dev init failed, aborting\n");
(void)enic_change_mtu(netdev, enic->port_mtu);
#ifdef CONFIG_PCI_IOV
- if (enic_is_dynamic(enic) && pdev->is_virtfn &&
- is_zero_ether_addr(enic->mac_addr))
+ if (enic_is_sriov_vf(enic) && is_zero_ether_addr(enic->mac_addr))
random_ether_addr(enic->mac_addr);
#endif
enic->tx_coalesce_usecs = enic->config.intr_timer_usec;
enic->rx_coalesce_usecs = enic->tx_coalesce_usecs;
- if (enic_is_dynamic(enic))
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
netdev->netdev_ops = &enic_netdev_dynamic_ops;
else
netdev->netdev_ops = &enic_netdev_ops;
enic_dev_deinit(enic);
err_out_dev_close:
vnic_dev_close(enic->vdev);
-err_out_free_pp:
- kfree(enic->pp);
err_out_disable_sriov:
+ kfree(enic->pp);
+err_out_disable_sriov_pp:
#ifdef CONFIG_PCI_IOV
if (enic_sriov_enabled(enic)) {
pci_disable_sriov(pdev);
enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
}
err_out_vnic_unregister:
- vnic_dev_unregister(enic->vdev);
#endif
+ vnic_dev_unregister(enic->vdev);
err_out_iounmap:
enic_iounmap(enic);
err_out_release_regions:
static u32 be_num_rxqs_want(struct be_adapter *adapter)
{
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- !sriov_enabled(adapter) && be_physfn(adapter) &&
- !be_is_mc(adapter)) {
+ !sriov_enabled(adapter) && be_physfn(adapter)) {
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
} else {
dev_warn(&adapter->pdev->dev,
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mii.h>
#include <linux/module.h>
################################################################################
#
# Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2011 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
* Writes value at the given offset in the register array which stores
* the VLAN filter table.
**/
-void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
{
int i;
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2011 Intel Corporation.
+ Copyright(c) 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
char igb_driver_version[] = DRV_VERSION;
static const char igb_driver_string[] =
"Intel(R) Gigabit Ethernet Network Driver";
-static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation.";
+static const char igb_copyright[] = "Copyright (c) 2007-2012 Intel Corporation.";
static const struct e1000_info *igb_info_tbl[] = {
[board_82575] = &e1000_82575_info,
}
}
-void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
- u32 type_tucmd, u32 mss_l4len_idx)
+static void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
+ u32 type_tucmd, u32 mss_l4len_idx)
{
struct e1000_adv_tx_context_desc *context_desc;
u16 i = tx_ring->next_to_use;
return IRQ_HANDLED;
}
-void igb_ring_irq_enable(struct igb_q_vector *q_vector)
+static void igb_ring_irq_enable(struct igb_q_vector *q_vector)
{
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
void igbvf_set_ethtool_ops(struct net_device *netdev)
{
- /* have to "undeclare" const on this struct to remove warnings */
- SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
+ SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops);
}
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- igbvf_irq_disable(adapter);
-
- if (!test_bit(__IGBVF_DOWN, &adapter->state))
- igbvf_irq_enable(adapter);
-
if (hw->mac.ops.set_vfta(hw, vid, false)) {
dev_err(&adapter->pdev->dev,
"Failed to remove vlan id %d\n", vid);
/* Receive DMA Registers */
#define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \
- (0x0D000 + ((_i - 64) * 0x40)))
+ (0x0D000 + (((_i) - 64) * 0x40)))
#define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \
- (0x0D004 + ((_i - 64) * 0x40)))
+ (0x0D004 + (((_i) - 64) * 0x40)))
#define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \
- (0x0D008 + ((_i - 64) * 0x40)))
+ (0x0D008 + (((_i) - 64) * 0x40)))
#define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \
- (0x0D010 + ((_i - 64) * 0x40)))
+ (0x0D010 + (((_i) - 64) * 0x40)))
#define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \
- (0x0D018 + ((_i - 64) * 0x40)))
+ (0x0D018 + (((_i) - 64) * 0x40)))
#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \
- (0x0D028 + ((_i - 64) * 0x40)))
+ (0x0D028 + (((_i) - 64) * 0x40)))
#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
- (0x0D02C + ((_i - 64) * 0x40)))
+ (0x0D02C + (((_i) - 64) * 0x40)))
#define IXGBE_RSCDBU 0x03028
#define IXGBE_RDDCC 0x02F20
#define IXGBE_RXMEMWRAP 0x03190
*/
#define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
(((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
- (0x0D014 + ((_i - 64) * 0x40))))
+ (0x0D014 + (((_i) - 64) * 0x40))))
/*
* Rx DCA Control Register:
* 00-15 : 0x02200 + n*4
*/
#define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
(((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
- (0x0D00C + ((_i - 64) * 0x40))))
+ (0x0D00C + (((_i) - 64) * 0x40))))
#define IXGBE_RDRXCTL 0x02F00
#define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4))
/* 8 of these 0x03C00 - 0x03C1C */
#define IXGBE_WUPL 0x05900
#define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */
-#define IXGBE_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flex host filter table */
-#define IXGBE_FHFT_EXT(_n) (0x09800 + (_n * 0x100)) /* Ext Flexible Host
- * Filter Table */
+#define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */
+#define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100)) /* Ext Flexible Host
+ * Filter Table */
#define IXGBE_FLEXIBLE_FILTER_COUNT_MAX 4
#define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX 2
#define IXGBE_LED_BLINK_BASE 0x00000080
#define IXGBE_LED_MODE_MASK_BASE 0x0000000F
#define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i)))
-#define IXGBE_LED_MODE_SHIFT(_i) (8*(_i))
+#define IXGBE_LED_MODE_SHIFT(_i) (8 * (_i))
#define IXGBE_LED_IVRT(_i) IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i)
#define IXGBE_LED_BLINK(_i) IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i)
#define IXGBE_LED_MODE_MASK(_i) IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i)
/* SR-IOV specific macros */
#define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4)
-#define IXGBE_MBVFICR(_i) (0x00710 + (_i * 4))
-#define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600))
-#define IXGBE_VFLREC(_i) (0x00700 + (_i * 4))
+#define IXGBE_MBVFICR(_i) (0x00710 + ((_i) * 4))
+#define IXGBE_VFLRE(_i) ((((_i) & 1) ? 0x001C0 : 0x00600))
+#define IXGBE_VFLREC(_i) (0x00700 + ((_i) * 4))
enum ixgbe_fdir_pballoc_type {
IXGBE_FDIR_PBALLOC_NONE = 0,
offsetof(struct ixgbevf_adapter, m), \
offsetof(struct ixgbevf_adapter, b), \
offsetof(struct ixgbevf_adapter, r)
-static struct ixgbe_stats ixgbe_gstrings_stats[] = {
+
+static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc,
stats.saved_reset_vfgprc)},
{"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc,
return 0;
}
-static struct ethtool_ops ixgbevf_ethtool_ops = {
+static const struct ethtool_ops ixgbevf_ethtool_ops = {
.get_settings = ixgbevf_get_settings,
.get_drvinfo = ixgbevf_get_drvinfo,
.get_regs_len = ixgbevf_get_regs_len,
board_X540_vf,
};
-extern struct ixgbevf_info ixgbevf_82599_vf_info;
-extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
+extern const struct ixgbevf_info ixgbevf_82599_vf_info;
+extern const struct ixgbevf_info ixgbevf_X540_vf_info;
+extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
/* needed by ethtool.c */
-extern char ixgbevf_driver_name[];
+extern const char ixgbevf_driver_name[];
extern const char ixgbevf_driver_version[];
extern int ixgbevf_up(struct ixgbevf_adapter *adapter);
#include "ixgbevf.h"
-char ixgbevf_driver_name[] = "ixgbevf";
+const char ixgbevf_driver_name[] = "ixgbevf";
static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr;
u32 msg;
+ bool got_ack = false;
eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS);
IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr);
- if (!hw->mbx.ops.check_for_ack(hw)) {
- /*
- * checking for the ack clears the PFACK bit. Place
- * it back in the v2p_mailbox cache so that anyone
- * polling for an ack will not miss it. Also
- * avoid the read below because the code to read
- * the mailbox will also clear the ack bit. This was
- * causing lost acks. Just cache the bit and exit
- * the IRQ handler.
- */
- hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
- goto out;
- }
+ if (!hw->mbx.ops.check_for_ack(hw))
+ got_ack = true;
- /* Not an ack interrupt, go ahead and read the message */
- hw->mbx.ops.read(hw, &msg, 1);
+ if (!hw->mbx.ops.check_for_msg(hw)) {
+ hw->mbx.ops.read(hw, &msg, 1);
- if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
- mod_timer(&adapter->watchdog_timer,
- round_jiffies(jiffies + 1));
+ if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + 1));
+ if (msg & IXGBE_VT_MSGTYPE_NACK)
+ pr_warn("Last Request of type %2.2x to PF Nacked\n",
+ msg & 0xFF);
+ goto out;
+ }
+
+ /*
+ * checking for the ack clears the PFACK bit. Place
+ * it back in the v2p_mailbox cache so that anyone
+ * polling for an ack will not miss it
+ */
+ if (got_ack)
+ hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
out:
return IRQ_HANDLED;
}
*******************************************************************************/
#include "mbx.h"
+#include "ixgbevf.h"
/**
* ixgbevf_poll_for_msg - Wait for message notification
return 0;
}
-struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
+const struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
.init_params = ixgbevf_init_mbx_params_vf,
.read = ixgbevf_read_mbx_vf,
.write = ixgbevf_write_mbx_vf,
*******************************************************************************/
#include "vf.h"
+#include "ixgbevf.h"
/**
* ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
return 0;
}
-static struct ixgbe_mac_operations ixgbevf_mac_ops = {
+static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
.init_hw = ixgbevf_init_hw_vf,
.reset_hw = ixgbevf_reset_hw_vf,
.start_hw = ixgbevf_start_hw_vf,
.set_vfta = ixgbevf_set_vfta_vf,
};
-struct ixgbevf_info ixgbevf_82599_vf_info = {
+const struct ixgbevf_info ixgbevf_82599_vf_info = {
.mac = ixgbe_mac_82599_vf,
.mac_ops = &ixgbevf_mac_ops,
};
-struct ixgbevf_info ixgbevf_X540_vf_info = {
+const struct ixgbevf_info ixgbevf_X540_vf_info = {
.mac = ixgbe_mac_X540_vf,
.mac_ops = &ixgbevf_mac_ops,
};
struct ixgbevf_info {
enum ixgbe_mac_type mac;
- struct ixgbe_mac_operations *mac_ops;
+ const struct ixgbe_mac_operations *mac_ops;
};
#endif /* __IXGBE_VF_H__ */
#define INT_MASK 0x0068
#define INT_MASK_EXT 0x006c
#define TX_FIFO_URGENT_THRESHOLD 0x0074
+#define RX_DISCARD_FRAME_CNT 0x0084
+#define RX_OVERRUN_FRAME_CNT 0x0088
#define TXQ_FIX_PRIO_CONF_MOVED 0x00dc
#define TX_BW_RATE_MOVED 0x00e0
#define TX_BW_MTU_MOVED 0x00e8
u32 bad_crc_event;
u32 collision;
u32 late_collision;
+ /* Non MIB hardware counters */
+ u32 rx_discard;
+ u32 rx_overrun;
};
struct lro_counters {
for (i = 0; i < 0x80; i += 4)
mib_read(mp, i);
+
+ /* Clear non MIB hw counters also */
+ rdlp(mp, RX_DISCARD_FRAME_CNT);
+ rdlp(mp, RX_OVERRUN_FRAME_CNT);
}
static void mib_counters_update(struct mv643xx_eth_private *mp)
p->bad_crc_event += mib_read(mp, 0x74);
p->collision += mib_read(mp, 0x78);
p->late_collision += mib_read(mp, 0x7c);
+ /* Non MIB hardware counters */
+ p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);
+ p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);
spin_unlock_bh(&mp->mib_counters_lock);
mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
MIBSTAT(bad_crc_event),
MIBSTAT(collision),
MIBSTAT(late_collision),
+ MIBSTAT(rx_discard),
+ MIBSTAT(rx_overrun),
LROSTAT(lro_aggregated),
LROSTAT(lro_flushed),
LROSTAT(lro_no_desc),
}
/* Allocate and setup a new buffer for receiving */
-static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
- struct sk_buff *skb, unsigned int bufsize)
+static int skge_rx_setup(struct pci_dev *pdev,
+ struct skge_element *e,
+ struct sk_buff *skb, unsigned int bufsize)
{
struct skge_rx_desc *rd = e->desc;
- u64 map;
+ dma_addr_t map;
- map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
+ map = pci_map_single(pdev, skb->data, bufsize,
PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, map))
+ goto mapping_error;
- rd->dma_lo = map;
- rd->dma_hi = map >> 32;
+ rd->dma_lo = lower_32_bits(map);
+ rd->dma_hi = upper_32_bits(map);
e->skb = skb;
rd->csum1_start = ETH_HLEN;
rd->csum2_start = ETH_HLEN;
rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, bufsize);
+ return 0;
+
+mapping_error:
+ if (net_ratelimit())
+ dev_warn(&pdev->dev, "%s: rx mapping error\n",
+ skb->dev->name);
+ return -EIO;
}
/* Resume receiving using existing skb,
return -ENOMEM;
skb_reserve(skb, NET_IP_ALIGN);
- skge_rx_setup(skge, e, skb, skge->rx_buf_size);
+ if (skge_rx_setup(skge->hw->pdev, e, skb, skge->rx_buf_size)) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+
} while ((e = e->next) != ring->start);
ring->to_clean = ring->start;
}
/* Initialize MAC */
+ netif_carrier_off(dev);
spin_lock_bh(&hw->phy_lock);
if (is_genesis(hw))
genesis_mac_init(hw, port);
struct skge_tx_desc *td;
int i;
u32 control, len;
- u64 map;
+ dma_addr_t map;
if (skb_padto(skb, ETH_ZLEN))
return NETDEV_TX_OK;
e->skb = skb;
len = skb_headlen(skb);
map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(hw->pdev, map))
+ goto mapping_error;
+
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, len);
- td->dma_lo = map;
- td->dma_hi = map >> 32;
+ td->dma_lo = lower_32_bits(map);
+ td->dma_hi = upper_32_bits(map);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const int offset = skb_checksum_start_offset(skb);
map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
skb_frag_size(frag), DMA_TO_DEVICE);
+ if (dma_mapping_error(&hw->pdev->dev, map))
+ goto mapping_unwind;
e = e->next;
e->skb = skb;
tf = e->desc;
BUG_ON(tf->control & BMU_OWN);
- tf->dma_lo = map;
- tf->dma_hi = (u64) map >> 32;
+ tf->dma_lo = lower_32_bits(map);
+ tf->dma_hi = upper_32_bits(map);
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, skb_frag_size(frag));
td->control = BMU_OWN | BMU_SW | BMU_STF | control | len;
wmb();
+ netdev_sent_queue(dev, skb->len);
+
skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev,
}
return NETDEV_TX_OK;
+
+mapping_unwind:
+ /* unroll any pages that were already mapped. */
+ if (e != skge->tx_ring.to_use) {
+ struct skge_element *u;
+
+ for (u = skge->tx_ring.to_use->next; u != e; u = u->next)
+ pci_unmap_page(hw->pdev, dma_unmap_addr(u, mapaddr),
+ dma_unmap_len(u, maplen),
+ PCI_DMA_TODEVICE);
+ e = skge->tx_ring.to_use;
+ }
+ /* undo the mapping for the skb header */
+ pci_unmap_single(hw->pdev, dma_unmap_addr(e, mapaddr),
+ dma_unmap_len(e, maplen),
+ PCI_DMA_TODEVICE);
+mapping_error:
+ /* mapping error causes error message and packet to be discarded. */
+ if (net_ratelimit())
+ dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
}
/* Free resources associated with this reing element */
-static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
- u32 control)
+static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e,
+ u32 control)
{
- struct pci_dev *pdev = skge->hw->pdev;
-
/* skb header vs. fragment */
if (control & BMU_STF)
pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr),
pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr),
dma_unmap_len(e, maplen),
PCI_DMA_TODEVICE);
-
- if (control & BMU_EOF) {
- netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev,
- "tx done slot %td\n", e - skge->tx_ring.start);
-
- dev_kfree_skb(e->skb);
- }
}
/* Free all buffers in transmit ring */
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
struct skge_tx_desc *td = e->desc;
- skge_tx_free(skge, e, td->control);
+
+ skge_tx_unmap(skge->hw->pdev, e, td->control);
+
+ if (td->control & BMU_EOF)
+ dev_kfree_skb(e->skb);
td->control = 0;
}
+ netdev_reset_queue(dev);
skge->tx_ring.to_clean = e;
}
if (!nskb)
goto resubmit;
+ if (unlikely(skge_rx_setup(skge->hw->pdev, e, nskb, skge->rx_buf_size))) {
+ dev_kfree_skb(nskb);
+ goto resubmit;
+ }
+
pci_unmap_single(skge->hw->pdev,
dma_unmap_addr(e, mapaddr),
dma_unmap_len(e, maplen),
PCI_DMA_FROMDEVICE);
skb = e->skb;
prefetch(skb->data);
- skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
}
skb_put(skb, len);
struct skge_port *skge = netdev_priv(dev);
struct skge_ring *ring = &skge->tx_ring;
struct skge_element *e;
+ unsigned int bytes_compl = 0, pkts_compl = 0;
skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
if (control & BMU_OWN)
break;
- skge_tx_free(skge, e, control);
+ skge_tx_unmap(skge->hw->pdev, e, control);
+
+ if (control & BMU_EOF) {
+ netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev,
+ "tx done slot %td\n",
+ e - skge->tx_ring.start);
+
+ pkts_compl++;
+ bytes_compl += e->skb->len;
+
+ dev_kfree_skb(e->skb);
+ }
}
+ netdev_completed_queue(dev, pkts_compl, bytes_compl);
skge->tx_ring.to_clean = e;
/* Can run lockless until we need to synchronize to restart queue. */
u32 reply;
u32 slave_status = 0;
u8 is_going_down = 0;
+ int i;
slave_state[slave].comm_toggle ^= 1;
reply = (u32) slave_state[slave].comm_toggle << 31;
if (cmd == MLX4_COMM_CMD_RESET) {
mlx4_warn(dev, "Received reset from slave:%d\n", slave);
slave_state[slave].active = false;
+ for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
+ slave_state[slave].event_eq[i].eqn = -1;
+ slave_state[slave].event_eq[i].token = 0;
+ }
/*check if we are in the middle of FLR process,
if so return "retry" status to the slave*/
if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_slave_state *s_state;
- int i, err, port;
+ int i, j, err, port;
priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
&priv->mfunc.vhcr_dma,
for (i = 0; i < dev->num_slaves; ++i) {
s_state = &priv->mfunc.master.slave_state[i];
s_state->last_cmd = MLX4_COMM_CMD_RESET;
+ for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j)
+ s_state->event_eq[j].eqn = -1;
__raw_writel((__force u32) 0,
&priv->mfunc.comm[i].slave_write);
__raw_writel((__force u32) 0,
static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int cq_num)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function, cq_num, 0,
+ return mlx4_cmd(dev, mailbox->dma, cq_num, 0,
MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int cq_num)
{
- return mlx4_cmd_box(dev, dev->caps.function, mailbox ? mailbox->dma : 0,
+ return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
cq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
+ int bit_count = hweight64(priv->stats_bitmap);
switch (sset) {
case ETH_SS_STATS:
- return NUM_ALL_STATS +
+ return (priv->stats_bitmap ? bit_count : NUM_ALL_STATS) +
(priv->tx_ring_num + priv->rx_ring_num) * 2;
case ETH_SS_TEST:
return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int index = 0;
- int i;
+ int i, j = 0;
spin_lock_bh(&priv->stats_lock);
- for (i = 0; i < NUM_MAIN_STATS; i++)
- data[index++] = ((unsigned long *) &priv->stats)[i];
- for (i = 0; i < NUM_PORT_STATS; i++)
- data[index++] = ((unsigned long *) &priv->port_stats)[i];
+ if (!(priv->stats_bitmap)) {
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ data[index++] =
+ ((unsigned long *) &priv->stats)[i];
+ for (i = 0; i < NUM_PORT_STATS; i++)
+ data[index++] =
+ ((unsigned long *) &priv->port_stats)[i];
+ for (i = 0; i < NUM_PKT_STATS; i++)
+ data[index++] =
+ ((unsigned long *) &priv->pkstats)[i];
+ } else {
+ for (i = 0; i < NUM_MAIN_STATS; i++) {
+ if ((priv->stats_bitmap >> j) & 1)
+ data[index++] =
+ ((unsigned long *) &priv->stats)[i];
+ j++;
+ }
+ for (i = 0; i < NUM_PORT_STATS; i++) {
+ if ((priv->stats_bitmap >> j) & 1)
+ data[index++] =
+ ((unsigned long *) &priv->port_stats)[i];
+ j++;
+ }
+ }
for (i = 0; i < priv->tx_ring_num; i++) {
data[index++] = priv->tx_ring[i].packets;
data[index++] = priv->tx_ring[i].bytes;
data[index++] = priv->rx_ring[i].packets;
data[index++] = priv->rx_ring[i].bytes;
}
- for (i = 0; i < NUM_PKT_STATS; i++)
- data[index++] = ((unsigned long *) &priv->pkstats)[i];
spin_unlock_bh(&priv->stats_lock);
}
case ETH_SS_STATS:
/* Add main counters */
- for (i = 0; i < NUM_MAIN_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
- for (i = 0; i< NUM_PORT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + NUM_MAIN_STATS]);
+ if (!priv->stats_bitmap) {
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i]);
+ for (i = 0; i < NUM_PORT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i +
+ NUM_MAIN_STATS]);
+ for (i = 0; i < NUM_PKT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i +
+ NUM_MAIN_STATS +
+ NUM_PORT_STATS]);
+ } else
+ for (i = 0; i < NUM_MAIN_STATS + NUM_PORT_STATS; i++) {
+ if ((priv->stats_bitmap >> i) & 1) {
+ strcpy(data +
+ (index++) * ETH_GSTRING_LEN,
+ main_strings[i]);
+ }
+ if (!(priv->stats_bitmap >> i))
+ break;
+ }
for (i = 0; i < priv->tx_ring_num; i++) {
sprintf(data + (index++) * ETH_GSTRING_LEN,
"tx%d_packets", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_bytes", i);
}
- for (i = 0; i< NUM_PKT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
break;
}
}
param->tx_pending = priv->tx_ring[0].size;
}
+static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ return priv->rx_ring_num;
+}
+
+static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+ int rss_rings;
+ size_t n = priv->rx_ring_num;
+ int err = 0;
+
+ rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
+
+ while (n--) {
+ ring_index[n] = rss_map->qps[n % rss_rings].qpn -
+ rss_map->base_qpn;
+ }
+
+ return err;
+}
+
+static int mlx4_en_set_rxfh_indir(struct net_device *dev,
+ const u32 *ring_index)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int port_up = 0;
+ int err = 0;
+ int i;
+ int rss_rings = 0;
+
+ /* Calculate RSS table size and make sure flows are spread evenly
+ * between rings
+ */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (i > 0 && !ring_index[i] && !rss_rings)
+ rss_rings = i;
+
+ if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
+ return -EINVAL;
+ }
+
+ if (!rss_rings)
+ rss_rings = priv->rx_ring_num;
+
+ /* RSS table size must be an order of 2 */
+ if (!is_power_of_2(rss_rings))
+ return -EINVAL;
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(dev);
+ }
+
+ priv->prof->rss_rings = rss_rings;
+
+ if (port_up) {
+ err = mlx4_en_start_port(dev);
+ if (err)
+ en_err(priv, "Failed starting port\n");
+ }
+
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
+
+static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int err = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = priv->rx_ring_num;
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings,
.set_pauseparam = mlx4_en_set_pauseparam,
.get_ringparam = mlx4_en_get_ringparam,
.set_ringparam = mlx4_en_set_ringparam,
+ .get_rxnfc = mlx4_en_get_rxnfc,
+ .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+ .get_rxfh_indir = mlx4_en_get_rxfh_indir,
+ .set_rxfh_indir = mlx4_en_set_rxfh_indir,
};
* Device scope module parameters
*/
-
-/* Enable RSS TCP traffic */
-MLX4_EN_PARM_INT(tcp_rss, 1,
- "Enable RSS for incomming TCP traffic or disabled (0)");
/* Enable RSS UDP traffic */
MLX4_EN_PARM_INT(udp_rss, 1,
"Enable RSS for incomming UDP traffic or disabled (0)");
struct mlx4_en_profile *params = &mdev->profile;
int i;
- params->tcp_rss = tcp_rss;
params->udp_rss = udp_rss;
if (params->udp_rss && !(mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
(!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+ params->prof[i].rss_rings = 0;
}
return 0;
/* Schedule multicast task to populate multicast list */
queue_work(mdev->workqueue, &priv->mcast_task);
+ mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap);
+
priv->port_up = true;
netif_tx_start_all_queues(dev);
return 0;
mutex_unlock(&mdev->state_lock);
}
-
-static int mlx4_en_open(struct net_device *dev)
+static void mlx4_en_clear_stats(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
int i;
- int err = 0;
-
- mutex_lock(&mdev->state_lock);
-
- if (!mdev->device_up) {
- en_err(priv, "Cannot open - device down/disabled\n");
- err = -EBUSY;
- goto out;
- }
- /* Reset HW statistics and performance counters */
if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
en_dbg(HW, priv, "Failed dumping statistics\n");
memset(&priv->stats, 0, sizeof(priv->stats));
memset(&priv->pstats, 0, sizeof(priv->pstats));
+ memset(&priv->pkstats, 0, sizeof(priv->pkstats));
+ memset(&priv->port_stats, 0, sizeof(priv->port_stats));
for (i = 0; i < priv->tx_ring_num; i++) {
priv->tx_ring[i].bytes = 0;
priv->tx_ring[i].packets = 0;
+ priv->tx_ring[i].tx_csum = 0;
}
for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_ring[i].bytes = 0;
priv->rx_ring[i].packets = 0;
+ priv->rx_ring[i].csum_ok = 0;
+ priv->rx_ring[i].csum_none = 0;
+ }
+}
+
+static int mlx4_en_open(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err = 0;
+
+ mutex_lock(&mdev->state_lock);
+
+ if (!mdev->device_up) {
+ en_err(priv, "Cannot open - device down/disabled\n");
+ err = -EBUSY;
+ goto out;
}
+ /* Reset HW statistics and SW counters */
+ mlx4_en_clear_stats(dev);
+
err = mlx4_en_start_port(dev);
if (err)
en_err(priv, "Failed starting port:%d\n", priv->port);
struct mlx4_en_rss_map *rss_map = &priv->rss_map;
struct mlx4_qp_context context;
struct mlx4_rss_context *rss_context;
+ int rss_rings;
void *ptr;
u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
MLX4_RSS_TCP_IPV6);
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
priv->rx_ring[0].cqn, &context);
+ if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
+ rss_rings = priv->rx_ring_num;
+ else
+ rss_rings = priv->prof->rss_rings;
+
ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
+ MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
rss_context = ptr;
- rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
+ rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
if (priv->mdev->profile.udp_rss) {
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_slave_event_eq_info *event_eq =
- &priv->mfunc.master.slave_state[slave].event_eq;
+ priv->mfunc.master.slave_state[slave].event_eq;
u32 in_modifier = vhcr->in_modifier;
u32 eqn = in_modifier & 0x1FF;
u64 in_param = vhcr->in_param;
int err = 0;
+ int i;
if (slave == dev->caps.function)
err = mlx4_cmd(dev, in_param, (in_modifier & 0x80000000) | eqn,
0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
- if (!err) {
- if (in_modifier >> 31) {
- /* unmap */
- event_eq->event_type &= ~in_param;
- } else {
- event_eq->eqn = eqn;
- event_eq->event_type = in_param;
- }
- }
+ if (!err)
+ for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i)
+ if (in_param & (1LL << i))
+ event_eq[i].eqn = in_modifier >> 31 ? -1 : eqn;
+
return err;
}
static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int eq_num)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function, eq_num, 0,
+ return mlx4_cmd(dev, mailbox->dma, eq_num, 0,
MLX4_CMD_SW2HW_EQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int eq_num)
{
- return mlx4_cmd_box(dev, dev->caps.function, mailbox->dma, eq_num,
+ return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num,
0, MLX4_CMD_HW2SW_EQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
#define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0
#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1
-#define QUERY_FUNC_CAP_FUNCTION_OFFSET 0x3
#define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4
#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10
#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14
field = 1 << 7; /* enable only ethernet interface */
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
- field = slave;
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FUNCTION_OFFSET);
-
field = dev->caps.num_ports;
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
goto out;
}
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_FUNCTION_OFFSET);
- func_cap->function = field;
-
MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
func_cap->num_ports = field;
};
struct mlx4_func_cap {
- u8 function;
u8 num_ports;
u8 flags;
u32 pf_context_behaviour;
.num_cq = 1 << 16,
.num_mcg = 1 << 13,
.num_mpt = 1 << 19,
- .num_mtt = 1 << 20,
+ .num_mtt = 1 << 20, /* It is really num mtt segements */
};
static int log_num_mac = 7;
return -ENOSYS;
}
- dev->caps.function = func_cap.function;
dev->caps.num_ports = func_cap.num_ports;
dev->caps.num_qps = func_cap.qp_quota;
dev->caps.num_srqs = func_cap.srq_quota;
};
struct mlx4_slave_event_eq_info {
- u32 eqn;
+ int eqn;
u16 token;
- u64 event_type;
};
struct mlx4_profile {
struct list_head duplicates;
};
+#define MLX4_EVENT_TYPES_NUM 64
+
struct mlx4_slave_state {
u8 comm_toggle;
u8 last_cmd;
struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
struct list_head mcast_filters[MLX4_MAX_PORTS + 1];
struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1];
- struct mlx4_slave_event_eq_info event_eq;
+ /* event type to eq number lookup */
+ struct mlx4_slave_event_eq_info event_eq[MLX4_EVENT_TYPES_NUM];
u16 eq_pi;
u16 eq_ci;
spinlock_t lock;
u8 rx_ppp;
u8 tx_pause;
u8 tx_ppp;
+ int rss_rings;
};
struct mlx4_en_profile {
int rss_xor;
- int tcp_rss;
int udp_rss;
u8 rss_mask;
u32 active_ports;
struct mlx4_en_perf_stats pstats;
struct mlx4_en_pkt_stats pkstats;
struct mlx4_en_port_stats port_stats;
+ u64 stats_bitmap;
char *mc_addrs;
int mc_addrs_cnt;
struct mlx4_en_stat_out_mbox hw_stats;
static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int mpt_index)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function , mpt_index,
+ return mlx4_cmd(dev, mailbox->dma, mpt_index,
0, MLX4_CMD_SW2HW_MPT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_WRAPPED);
}
*pdn = mlx4_bitmap_alloc(&priv->pd_bitmap);
if (*pdn == -1)
return -ENOMEM;
- if (mlx4_is_mfunc(dev))
- *pdn |= (dev->caps.function + 1) << NOT_MASKED_PD_BITS;
+
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
#define MLX4_VLAN_VALID (1u << 31)
#define MLX4_VLAN_MASK 0xfff
+#define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL
+#define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL
+#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL
+#define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL
+
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
{
int i;
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd)
{
+ if (slave != dev->caps.function)
+ return 0;
return mlx4_common_dump_eth_stats(dev, slave,
vhcr->in_modifier, outbox);
}
+
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap)
+{
+ if (!mlx4_is_mfunc(dev)) {
+ *stats_bitmap = 0;
+ return;
+ }
+
+ *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK |
+ MLX4_STATS_TRAFFIC_DROPS_MASK |
+ MLX4_STATS_PORT_COUNTERS_MASK);
+
+ if (mlx4_is_master(dev))
+ *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK;
+}
+EXPORT_SYMBOL(mlx4_set_stats_bitmap);
profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
profile[MLX4_RES_DMPT].num = request->num_mpt;
profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
- profile[MLX4_RES_MTT].num = request->num_mtt;
+ profile[MLX4_RES_MTT].num = request->num_mtt * (1 << log_mtts_per_seg);
profile[MLX4_RES_MCG].num = request->num_mcg;
for (i = 0; i < MLX4_RES_NUM; ++i) {
((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn =
cpu_to_be32(qp->qpn);
- ret = mlx4_cmd(dev, mailbox->dma | dev->caps.function,
+ ret = mlx4_cmd(dev, mailbox->dma,
qp->qpn | (!!sqd_event << 31),
new_state == MLX4_QP_STATE_RST ? 2 : 0,
op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native);
return be32_to_cpu(mpt->mtt_sz);
}
-static int mr_get_pdn(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->pd_flags) & 0xffffff;
-}
-
static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
{
return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
return total_pages;
}
-static int qp_get_pdn(struct mlx4_qp_context *qpc)
-{
- return be32_to_cpu(qpc->pd) & 0xffffff;
-}
-
-static int pdn2slave(int pdn)
-{
- return (pdn >> NOT_MASKED_PD_BITS) - 1;
-}
-
static int check_mtt_range(struct mlx4_dev *dev, int slave, int start,
int size, struct res_mtt *mtt)
{
mpt->mtt = mtt;
}
- if (pdn2slave(mr_get_pdn(inbox->buf)) != slave) {
- err = -EPERM;
- goto ex_put;
- }
-
err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
if (err)
goto ex_put;
if (err)
goto ex_put_mtt;
- if (pdn2slave(qp_get_pdn(qpc)) != slave) {
- err = -EPERM;
- goto ex_put_mtt;
- }
-
err = get_res(dev, slave, rcqn, RES_CQ, &rcq);
if (err)
goto ex_put_mtt;
if (!priv->mfunc.master.slave_state)
return -EINVAL;
- event_eq = &priv->mfunc.master.slave_state[slave].event_eq;
+ event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
/* Create the event only if the slave is registered */
- if ((event_eq->event_type & (1 << eqe->type)) == 0)
+ if (event_eq->eqn < 0)
return 0;
mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
return err;
}
-static int srq_get_pdn(struct mlx4_srq_context *srqc)
-{
- return be32_to_cpu(srqc->pd) & 0xffffff;
-}
-
static int srq_get_mtt_size(struct mlx4_srq_context *srqc)
{
int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;
if (err)
goto ex_put_mtt;
- if (pdn2slave(srq_get_pdn(srqc)) != slave) {
- err = -EPERM;
- goto ex_put_mtt;
- }
-
err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
if (err)
goto ex_put_mtt;
static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int srq_num)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function, srq_num, 0,
+ return mlx4_cmd(dev, mailbox->dma, srq_num, 0,
MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
int err;
+ /* Ensure we have a valid MAC */
+ if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+ pr_err("Error: Invalid MAC address\n");
+ return -EINVAL;
+ }
+
/* hardware has been reset, we need to reload some things */
pch_gbe_set_multi(netdev);
memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->dev_addr)) {
- dev_err(&pdev->dev, "Invalid MAC Address\n");
- ret = -EIO;
- goto err_free_adapter;
+ /*
+ * If the MAC is invalid (or just missing), display a warning
+ * but do not abort setting up the device. pch_gbe_up will
+ * prevent the interface from being brought up until a valid MAC
+ * is set.
+ */
+ dev_err(&pdev->dev, "Invalid MAC address, "
+ "interface disabled.\n");
}
setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
(unsigned long)adapter);
else
irqlist = priv->mii_irq;
- new_bus->name = "STMMAC MII Bus";
+ new_bus->name = "stmmac";
new_bus->read = &stmmac_mdio_read;
new_bus->write = &stmmac_mdio_write;
new_bus->reset = &stmmac_mdio_reset;
#define STMMAC_DEVICE_ID 0x1108
static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
- {
- PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, {
- }
+ {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+ {}
};
MODULE_DEVICE_TABLE(pci, stmmac_id_table);
nvdev = hv_get_drvdata(ndevctx->device_ctx);
if (nvdev == NULL)
- return;
+ goto out;
rdev = nvdev->extension;
if (rdev == NULL)
- return;
+ goto out;
if (net->flags & IFF_PROMISC)
rndis_filter_set_packet_filter(rdev,
NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED);
+out:
kfree(w);
}
skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
if (!skb)
return RX_HANDLER_CONSUMED;
+ eth = eth_hdr(skb);
src = macvlan_hash_lookup(port, eth->h_source);
if (!src)
/* frame comes from an external address */
/**
* mdiobus_alloc_size - allocate a mii_bus structure
+ * @size: extra amount of memory to allocate for private storage.
+ * If non-zero, then bus->priv is points to that memory.
*
* Description: called by a bus driver to allocate an mii_bus
* structure to fill in.
- *
- * 'size' is an an extra amount of memory to allocate for private storage.
- * If non-zero, then bus->priv is points to that memory.
*/
struct mii_bus *mdiobus_alloc_size(size_t size)
{
return NULL;
}
-int team_options_register(struct team *team,
- const struct team_option *option,
- size_t option_count)
+int __team_options_register(struct team *team,
+ const struct team_option *option,
+ size_t option_count)
{
int i;
struct team_option **dst_opts;
}
}
- for (i = 0; i < option_count; i++)
+ for (i = 0; i < option_count; i++) {
+ dst_opts[i]->changed = true;
+ dst_opts[i]->removed = false;
list_add_tail(&dst_opts[i]->list, &team->option_list);
+ }
kfree(dst_opts);
return 0;
return err;
}
-EXPORT_SYMBOL(team_options_register);
+static void __team_options_mark_removed(struct team *team,
+ const struct team_option *option,
+ size_t option_count)
+{
+ int i;
+
+ for (i = 0; i < option_count; i++, option++) {
+ struct team_option *del_opt;
-static void __team_options_change_check(struct team *team,
- struct team_option *changed_option);
+ del_opt = __team_find_option(team, option->name);
+ if (del_opt) {
+ del_opt->changed = true;
+ del_opt->removed = true;
+ }
+ }
+}
static void __team_options_unregister(struct team *team,
const struct team_option *option,
}
}
+static void __team_options_change_check(struct team *team);
+
+int team_options_register(struct team *team,
+ const struct team_option *option,
+ size_t option_count)
+{
+ int err;
+
+ err = __team_options_register(team, option, option_count);
+ if (err)
+ return err;
+ __team_options_change_check(team);
+ return 0;
+}
+EXPORT_SYMBOL(team_options_register);
+
void team_options_unregister(struct team *team,
const struct team_option *option,
size_t option_count)
{
+ __team_options_mark_removed(team, option, option_count);
+ __team_options_change_check(team);
__team_options_unregister(team, option, option_count);
- __team_options_change_check(team, NULL);
}
EXPORT_SYMBOL(team_options_unregister);
if (err)
return err;
- __team_options_change_check(team, option);
+ option->changed = true;
+ __team_options_change_check(team);
return err;
}
return -ENOENT;
}
+ port->removed = true;
__team_port_change_check(port, false);
team_port_list_del_port(team, port);
team_adjust_ops(team);
return err;
}
-static int team_nl_fill_options_get_changed(struct sk_buff *skb,
- u32 pid, u32 seq, int flags,
- struct team *team,
- struct team_option *changed_option)
+static int team_nl_fill_options_get(struct sk_buff *skb,
+ u32 pid, u32 seq, int flags,
+ struct team *team, bool fillall)
{
struct nlattr *option_list;
void *hdr;
struct nlattr *option_item;
long arg;
+ /* Include only changed options if fill all mode is not on */
+ if (!fillall && !option->changed)
+ continue;
option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
if (!option_item)
goto nla_put_failure;
NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name);
- if (option == changed_option)
+ if (option->changed) {
NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED);
+ option->changed = false;
+ }
+ if (option->removed)
+ NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED);
switch (option->type) {
case TEAM_OPTION_TYPE_U32:
NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32);
return -EMSGSIZE;
}
-static int team_nl_fill_options_get(struct sk_buff *skb,
- struct genl_info *info, int flags,
- struct team *team)
+static int team_nl_fill_options_get_all(struct sk_buff *skb,
+ struct genl_info *info, int flags,
+ struct team *team)
{
- return team_nl_fill_options_get_changed(skb, info->snd_pid,
- info->snd_seq, NLM_F_ACK,
- team, NULL);
+ return team_nl_fill_options_get(skb, info->snd_pid,
+ info->snd_seq, NLM_F_ACK,
+ team, true);
}
static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
if (!team)
return -EINVAL;
- err = team_nl_send_generic(info, team, team_nl_fill_options_get);
+ err = team_nl_send_generic(info, team, team_nl_fill_options_get_all);
team_nl_team_put(team);
return err;
}
-static int team_nl_fill_port_list_get_changed(struct sk_buff *skb,
- u32 pid, u32 seq, int flags,
- struct team *team,
- struct team_port *changed_port)
+static int team_nl_fill_port_list_get(struct sk_buff *skb,
+ u32 pid, u32 seq, int flags,
+ struct team *team,
+ bool fillall)
{
struct nlattr *port_list;
void *hdr;
list_for_each_entry(port, &team->port_list, list) {
struct nlattr *port_item;
+ /* Include only changed ports if fill all mode is not on */
+ if (!fillall && !port->changed)
+ continue;
port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT);
if (!port_item)
goto nla_put_failure;
NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex);
- if (port == changed_port)
+ if (port->changed) {
NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED);
+ port->changed = false;
+ }
+ if (port->removed)
+ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED);
if (port->linkup)
NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP);
NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed);
return -EMSGSIZE;
}
-static int team_nl_fill_port_list_get(struct sk_buff *skb,
- struct genl_info *info, int flags,
- struct team *team)
+static int team_nl_fill_port_list_get_all(struct sk_buff *skb,
+ struct genl_info *info, int flags,
+ struct team *team)
{
- return team_nl_fill_port_list_get_changed(skb, info->snd_pid,
- info->snd_seq, NLM_F_ACK,
- team, NULL);
+ return team_nl_fill_port_list_get(skb, info->snd_pid,
+ info->snd_seq, NLM_F_ACK,
+ team, true);
}
static int team_nl_cmd_port_list_get(struct sk_buff *skb,
if (!team)
return -EINVAL;
- err = team_nl_send_generic(info, team, team_nl_fill_port_list_get);
+ err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all);
team_nl_team_put(team);
.name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
};
-static int team_nl_send_event_options_get(struct team *team,
- struct team_option *changed_option)
+static int team_nl_send_event_options_get(struct team *team)
{
struct sk_buff *skb;
int err;
if (!skb)
return -ENOMEM;
- err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team,
- changed_option);
+ err = team_nl_fill_options_get(skb, 0, 0, 0, team, false);
if (err < 0)
goto err_fill;
return err;
}
-static int team_nl_send_event_port_list_get(struct team_port *port)
+static int team_nl_send_event_port_list_get(struct team *team)
{
struct sk_buff *skb;
int err;
- struct net *net = dev_net(port->team->dev);
+ struct net *net = dev_net(team->dev);
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb)
return -ENOMEM;
- err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0,
- port->team, port);
+ err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false);
if (err < 0)
goto err_fill;
* Change checkers
******************/
-static void __team_options_change_check(struct team *team,
- struct team_option *changed_option)
+static void __team_options_change_check(struct team *team)
{
int err;
- err = team_nl_send_event_options_get(team, changed_option);
+ err = team_nl_send_event_options_get(team);
if (err)
netdev_warn(team->dev, "Failed to send options change via netlink\n");
}
{
int err;
- if (port->linkup == linkup)
+ if (!port->removed && port->linkup == linkup)
return;
+ port->changed = true;
port->linkup = linkup;
if (linkup) {
struct ethtool_cmd ecmd;
port->duplex = 0;
send_event:
- err = team_nl_send_event_port_list_get(port);
+ err = team_nl_send_event_port_list_get(port->team);
if (err)
netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n",
port->dev->name);
depends on B43 && BCMA
default y
+config B43_BCMA_EXTRA
+ bool "Hardware support that overlaps with the brcmsmac driver"
+ depends on B43_BCMA
+ default n if BRCMSMAC || BRCMSMAC_MODULE
+ default y
+
config B43_SSB
bool
depends on B43 && SSB
#ifdef CONFIG_B43_BCMA
static const struct bcma_device_id b43_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+#ifdef CONFIG_B43_BCMA_EXTRA
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+#endif
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
BCMA_CORETABLE_END
};
void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
{
+ int timeout = 20;
+
/* flush packet queue when requested */
if (drop)
brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
/* wait for queue and DMA fifos to run dry */
- while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) {
brcms_msleep(wlc->wl, 1);
+
+ if (--timeout == 0)
+ break;
+ }
+
+ WARN_ON_ONCE(timeout == 0);
}
void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
}
#endif
- spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
/* saved interrupt in inta variable now we can reset trans_pcie->inta */
trans_pcie->inta = 0;
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
IWL_ERR(trans, "Hardware error detected. Restarting.\n");
#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
-#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256)
struct netfront_stats {
u64 rx_packets;
/**
* pci_intx_mask_supported - probe for INTx masking support
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
*
* Check if the device dev support INTx masking via the config space
* command word.
/**
* pci_check_and_mask_intx - mask INTx on pending interrupt
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
*
* Check if the device dev has its INTx line asserted, mask it and
* return true in that case. False is returned if not interrupt was
/**
* pci_check_and_mask_intx - unmask INTx of no interrupt is pending
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
*
* Check if the device dev has its INTx line asserted, unmask it if not
* and return true. False is returned and the mask remains active if
dev_set_drvdata(&dev->dev, NULL);
- for (; next = s->next, s; s = next) {
+ for (; s; s = next) {
+ next = s->next;
soc_pcmcia_remove_one(&s->soc);
kfree(s);
}
static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
{
- static struct dentry *device_root;
+ struct dentry *device_root;
device_root = debugfs_create_dir(dev_name(pctldev->dev),
debugfs_root);
+ pctldev->device_root = device_root;
+
if (IS_ERR(device_root) || !device_root) {
pr_warn("failed to create debugfs directory for %s\n",
dev_name(pctldev->dev));
pinconf_init_device_debugfs(device_root, pctldev);
}
+static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
+{
+ debugfs_remove_recursive(pctldev->device_root);
+}
+
static void pinctrl_init_debugfs(void)
{
debugfs_root = debugfs_create_dir("pinctrl", NULL);
{
}
+static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
+{
+}
+
#endif
/**
if (pctldesc->name == NULL)
return NULL;
+ pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
+ if (pctldev == NULL)
+ return NULL;
+
+ /* Initialize pin control device struct */
+ pctldev->owner = pctldesc->owner;
+ pctldev->desc = pctldesc;
+ pctldev->driver_data = driver_data;
+ INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
+ spin_lock_init(&pctldev->pin_desc_tree_lock);
+ INIT_LIST_HEAD(&pctldev->gpio_ranges);
+ mutex_init(&pctldev->gpio_ranges_lock);
+ pctldev->dev = dev;
+
/* If we're implementing pinmuxing, check the ops for sanity */
if (pctldesc->pmxops) {
- ret = pinmux_check_ops(pctldesc->pmxops);
+ ret = pinmux_check_ops(pctldev);
if (ret) {
pr_err("%s pinmux ops lacks necessary functions\n",
pctldesc->name);
- return NULL;
+ goto out_err;
}
}
/* If we're implementing pinconfig, check the ops for sanity */
if (pctldesc->confops) {
- ret = pinconf_check_ops(pctldesc->confops);
+ ret = pinconf_check_ops(pctldev);
if (ret) {
pr_err("%s pin config ops lacks necessary functions\n",
pctldesc->name);
- return NULL;
+ goto out_err;
}
}
- pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
- if (pctldev == NULL)
- return NULL;
-
- /* Initialize pin control device struct */
- pctldev->owner = pctldesc->owner;
- pctldev->desc = pctldesc;
- pctldev->driver_data = driver_data;
- INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
- spin_lock_init(&pctldev->pin_desc_tree_lock);
- INIT_LIST_HEAD(&pctldev->gpio_ranges);
- mutex_init(&pctldev->gpio_ranges_lock);
- pctldev->dev = dev;
-
/* Register all the pins */
pr_debug("try to register %d pins on %s...\n",
pctldesc->npins, pctldesc->name);
if (pctldev == NULL)
return;
+ pinctrl_remove_device_debugfs(pctldev);
pinmux_unhog_maps(pctldev);
/* TODO: check that no pinmuxes are still active? */
mutex_lock(&pinctrldev_list_mutex);
struct device *dev;
struct module *owner;
void *driver_data;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *device_root;
+#endif
#ifdef CONFIG_PINMUX
struct mutex pinmux_hogs_lock;
struct list_head pinmux_hogs;
}
EXPORT_SYMBOL(pin_config_group_set);
-int pinconf_check_ops(const struct pinconf_ops *ops)
+int pinconf_check_ops(struct pinctrl_dev *pctldev)
{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+
/* We must be able to read out pin status */
if (!ops->pin_config_get && !ops->pin_config_group_get)
return -EINVAL;
seq_puts(s, "Format: pin (name): pinmux setting array\n");
/* The pin number can be retrived from the pin controller descriptor */
- for (i = 0; pin < pctldev->desc->npins; i++) {
+ for (i = 0; i < pctldev->desc->npins; i++) {
struct pin_desc *desc;
pin = pctldev->desc->pins[i].number;
#ifdef CONFIG_PINCONF
-int pinconf_check_ops(const struct pinconf_ops *ops);
+int pinconf_check_ops(struct pinctrl_dev *pctldev);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
#else
-static inline int pinconf_check_ops(const struct pinconf_ops *ops)
+static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
{
return 0;
}
* @dev: the device using this pinmux
* @usecount: the number of active users of this mux setting, used to keep
* track of nested use cases
- * @pins: an array of discrete physical pins used in this mapping, taken
- * from the global pin enumeration space (copied from pinmux map)
- * @num_pins: the number of pins in this mapping array, i.e. the number of
- * elements in .pins so we can iterate over that array (copied from
- * pinmux map)
* @pctldev: pin control device handling this pinmux
* @func_selector: the function selector for the pinmux device handling
* this pinmux
status = 0;
if (status)
- dev_err(pctldev->dev, "->request on device %s failed "
- "for pin %d\n",
+ dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
pctldev->desc->name, pin);
out_free_pin:
if (status) {
/* First sanity check the new mapping */
for (i = 0; i < num_maps; i++) {
if (!maps[i].name) {
- pr_err("failed to register map %d: "
- "no map name given\n", i);
+ pr_err("failed to register map %d: no map name given\n",
+ i);
return -EINVAL;
}
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
- pr_err("failed to register map %s (%d): "
- "no pin control device given\n",
+ pr_err("failed to register map %s (%d): no pin control device given\n",
maps[i].name, i);
return -EINVAL;
}
if (!maps[i].function) {
- pr_err("failed to register map %s (%d): "
- "no function ID given\n", maps[i].name, i);
+ pr_err("failed to register map %s (%d): no function ID given\n",
+ maps[i].name, i);
return -EINVAL;
}
}
/**
- * acquire_pins() - acquire all the pins for a certain funcion on a pinmux
+ * acquire_pins() - acquire all the pins for a certain function on a pinmux
* @pctldev: the device to take the pins on
* @func_selector: the function selector to acquire the pins for
* @group_selector: the group selector containing the pins to acquire
ret = pin_request(pctldev, pins[i], func, NULL);
if (ret) {
dev_err(pctldev->dev,
- "could not get pin %d for function %s "
- "on device %s - conflicting mux mappings?\n",
+ "could not get pin %d for function %s on device %s - conflicting mux mappings?\n",
pins[i], func ? : "(undefined)",
pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
/**
* release_pins() - release pins taken by earlier acquirement
- * @pctldev: the device to free the pinx on
+ * @pctldev: the device to free the pins on
* @group_selector: the group selector containing the pins to free
*/
static void release_pins(struct pinctrl_dev *pctldev,
ret = pctlops->get_group_pins(pctldev, group_selector,
&pins, &num_pins);
if (ret) {
- dev_err(pctldev->dev, "could not get pins to release for "
- "group selector %d\n",
+ dev_err(pctldev->dev, "could not get pins to release for group selector %d\n",
group_selector);
return;
}
ret = pinctrl_get_group_selector(pctldev, groups[0]);
if (ret < 0) {
dev_err(pctldev->dev,
- "function %s wants group %s but the pin "
- "controller does not seem to have that group\n",
+ "function %s wants group %s but the pin controller does not seem to have that group\n",
pmxops->get_function_name(pctldev, func_selector),
groups[0]);
return ret;
if (num_groups > 1)
dev_dbg(pctldev->dev,
- "function %s support more than one group, "
- "default-selecting first group %s (%d)\n",
+ "function %s support more than one group, default-selecting first group %s (%d)\n",
pmxops->get_function_name(pctldev, func_selector),
groups[0],
ret);
if (pmx->pctldev && pmx->pctldev != pctldev) {
dev_err(pctldev->dev,
- "different pin control devices given for device %s, "
- "function %s\n",
- devname,
- map->function);
+ "different pin control devices given for device %s, function %s\n",
+ devname, map->function);
return -EINVAL;
}
pmx->dev = dev;
*/
struct pinmux *pinmux_get(struct device *dev, const char *name)
{
-
struct pinmux_map const *map = NULL;
struct pinctrl_dev *pctldev = NULL;
const char *devname = NULL;
else if (map->ctrl_dev_name)
devname = map->ctrl_dev_name;
- pr_warning("could not find a pinctrl device for pinmux "
- "function %s, fishy, they shall all have one\n",
+ pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n",
map->function);
pr_warning("given pinctrl device name: %s",
devname ? devname : "UNDEFINED");
}
EXPORT_SYMBOL_GPL(pinmux_disable);
-int pinmux_check_ops(const struct pinmux_ops *ops)
+int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ unsigned selector = 0;
+
/* Check that we implement required operations */
if (!ops->list_functions ||
!ops->get_function_name ||
!ops->disable)
return -EINVAL;
+ /* Check that all functions registered have names */
+ while (ops->list_functions(pctldev, selector) >= 0) {
+ const char *fname = ops->get_function_name(pctldev,
+ selector);
+ if (!fname) {
+ pr_err("pinmux ops has no name for function%u\n",
+ selector);
+ return -EINVAL;
+ }
+ selector++;
+ }
+
return 0;
}
* without any problems, so then we can hog pinmuxes for
* all devices that just want a static pin mux at this point.
*/
- dev_err(pctldev->dev, "map %s wants to hog a non-system "
- "pinmux, this is not going to work\n", map->name);
+ dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n",
+ map->name);
return -EINVAL;
}
for (i = 0; i < pinmux_maps_num; i++) {
struct pinmux_map const *map = &pinmux_maps[i];
- if (((map->ctrl_dev == dev) ||
- !strcmp(map->ctrl_dev_name, devname)) &&
- map->hog_on_boot) {
+ if (!map->hog_on_boot)
+ continue;
+
+ if ((map->ctrl_dev == dev) ||
+ (map->ctrl_dev_name &&
+ !strcmp(map->ctrl_dev_name, devname))) {
/* OK time to hog! */
ret = pinmux_hog_map(pctldev, map);
if (ret)
seq_printf(s, "device: %s function: %s (%u),",
pinctrl_dev_get_name(pmx->pctldev),
- pmxops->get_function_name(pctldev, pmx->func_selector),
+ pmxops->get_function_name(pctldev,
+ pmx->func_selector),
pmx->func_selector);
seq_printf(s, " groups: [");
list_for_each_entry(grp, &pmx->groups, node) {
seq_printf(s, " %s (%u)",
- pctlops->get_group_name(pctldev, grp->group_selector),
+ pctlops->get_group_name(pctldev,
+ grp->group_selector),
grp->group_selector);
}
seq_printf(s, " ]");
*/
#ifdef CONFIG_PINMUX
-int pinmux_check_ops(const struct pinmux_ops *ops);
+int pinmux_check_ops(struct pinctrl_dev *pctldev);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
void pinmux_init_debugfs(struct dentry *subsys_root);
#else
-static inline int pinmux_check_ops(const struct pinmux_ops *ops)
+static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
return 0;
}
* @dev: struct device for the regulator
* @init_data: platform provided init data, passed through by driver
* @driver_data: private regulator data
+ * @of_node: OpenFirmware node to parse for device tree bindings (may be
+ * NULL).
*
* Called by regulator drivers to register a regulator.
* Returns 0 on success.
if (constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
/* Only one voltage? Then make sure it's set. */
- if (constraints->min_uV == constraints->max_uV)
+ if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
constraints->apply_uV = true;
uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL);
config RTC_DRV_SA1100
tristate "SA11x0/PXA2xx"
- depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
+ depends on ARCH_SA1100 || ARCH_PXA
help
If you say Y here you will get access to the real time clock
built into your SA11x0 or PXA2xx CPU.
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
+#include <linux/string.h>
#include <linux/pm.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/bitops.h>
#include <mach/hardware.h>
#include <asm/irq.h>
+#ifdef CONFIG_ARCH_PXA
+#include <mach/regs-rtc.h>
+#endif
+
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
-#define RTC_FREQ 1024
-
-#define RCNR 0x00 /* RTC Count Register */
-#define RTAR 0x04 /* RTC Alarm Register */
-#define RTSR 0x08 /* RTC Status Register */
-#define RTTR 0x0c /* RTC Timer Trim Register */
-
-#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
-#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
-#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
-#define RTSR_AL (1 << 0) /* RTC alarm detected */
-
-#define rtc_readl(sa1100_rtc, reg) \
- readl_relaxed((sa1100_rtc)->base + (reg))
-#define rtc_writel(sa1100_rtc, reg, value) \
- writel_relaxed((value), (sa1100_rtc)->base + (reg))
-
-struct sa1100_rtc {
- struct resource *ress;
- void __iomem *base;
- struct clk *clk;
- int irq_1Hz;
- int irq_Alrm;
- struct rtc_device *rtc;
- spinlock_t lock; /* Protects this structure */
-};
+
+static const unsigned long RTC_FREQ = 1024;
+static struct rtc_time rtc_alarm;
+static DEFINE_SPINLOCK(sa1100_rtc_lock);
+
+static inline int rtc_periodic_alarm(struct rtc_time *tm)
+{
+ return (tm->tm_year == -1) ||
+ ((unsigned)tm->tm_mon >= 12) ||
+ ((unsigned)(tm->tm_mday - 1) >= 31) ||
+ ((unsigned)tm->tm_hour > 23) ||
+ ((unsigned)tm->tm_min > 59) ||
+ ((unsigned)tm->tm_sec > 59);
+}
+
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
}
}
+static int rtc_update_alarm(struct rtc_time *alrm)
+{
+ struct rtc_time alarm_tm, now_tm;
+ unsigned long now, time;
+ int ret;
+
+ do {
+ now = RCNR;
+ rtc_time_to_tm(now, &now_tm);
+ rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
+ ret = rtc_tm_to_time(&alarm_tm, &time);
+ if (ret != 0)
+ break;
+
+ RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
+ RTAR = time;
+ } while (now != RCNR);
+
+ return ret;
+}
+
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = to_platform_device(dev_id);
- struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
unsigned int rtsr;
unsigned long events = 0;
- spin_lock(&sa1100_rtc->lock);
+ spin_lock(&sa1100_rtc_lock);
+ rtsr = RTSR;
/* clear interrupt sources */
- rtsr = rtc_readl(sa1100_rtc, RTSR);
- rtc_writel(sa1100_rtc, RTSR, 0);
-
+ RTSR = 0;
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_probe(). */
if (rtsr & (RTSR_ALE | RTSR_HZE)) {
/* This is the original code, before there was the if test
* above. This code does not clear interrupts that were not
* enabled. */
- rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2));
+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
} else {
/* For some reason, it is possible to enter this routine
* without interruptions enabled, it has been tested with
* This situation leads to an infinite "loop" of interrupt
* routine calling and as a result the processor seems to
* lock on its first call to open(). */
- rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+ RTSR = RTSR_AL | RTSR_HZ;
}
/* clear alarm interrupt if it has occurred */
if (rtsr & RTSR_AL)
rtsr &= ~RTSR_ALE;
- rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE));
+ RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
/* update irq data & counter */
if (rtsr & RTSR_AL)
if (rtsr & RTSR_HZ)
events |= RTC_UF | RTC_IRQF;
- rtc_update_irq(sa1100_rtc->rtc, 1, events);
+ rtc_update_irq(rtc, 1, events);
- spin_unlock(&sa1100_rtc->lock);
+ if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
+ rtc_update_alarm(&rtc_alarm);
+
+ spin_unlock(&sa1100_rtc_lock);
return IRQ_HANDLED;
}
static int sa1100_rtc_open(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
int ret;
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct rtc_device *rtc = platform_get_drvdata(plat_dev);
- ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt,
- IRQF_DISABLED, "rtc 1Hz", dev);
+ ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
+ "rtc 1Hz", dev);
if (ret) {
- dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
goto fail_ui;
}
- ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt,
- IRQF_DISABLED, "rtc Alrm", dev);
+ ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
+ "rtc Alrm", dev);
if (ret) {
- dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
goto fail_ai;
}
- sa1100_rtc->rtc->max_user_freq = RTC_FREQ;
- rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ);
+ rtc->max_user_freq = RTC_FREQ;
+ rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
return 0;
fail_ai:
- free_irq(sa1100_rtc->irq_1Hz, dev);
+ free_irq(IRQ_RTC1Hz, dev);
fail_ui:
return ret;
}
static void sa1100_rtc_release(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
- spin_lock_irq(&sa1100_rtc->lock);
- rtc_writel(sa1100_rtc, RTSR, 0);
- spin_unlock_irq(&sa1100_rtc->lock);
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR = 0;
+ spin_unlock_irq(&sa1100_rtc_lock);
- free_irq(sa1100_rtc->irq_Alrm, dev);
- free_irq(sa1100_rtc->irq_1Hz, dev);
+ free_irq(IRQ_RTCAlrm, dev);
+ free_irq(IRQ_RTC1Hz, dev);
}
static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
- unsigned int rtsr;
-
- spin_lock_irq(&sa1100_rtc->lock);
-
- rtsr = rtc_readl(sa1100_rtc, RTSR);
+ spin_lock_irq(&sa1100_rtc_lock);
if (enabled)
- rtsr |= RTSR_ALE;
+ RTSR |= RTSR_ALE;
else
- rtsr &= ~RTSR_ALE;
- rtc_writel(sa1100_rtc, RTSR, rtsr);
-
- spin_unlock_irq(&sa1100_rtc->lock);
+ RTSR &= ~RTSR_ALE;
+ spin_unlock_irq(&sa1100_rtc_lock);
return 0;
}
static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
- rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm);
+ rtc_time_to_tm(RCNR, tm);
return 0;
}
static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
unsigned long time;
int ret;
ret = rtc_tm_to_time(tm, &time);
if (ret == 0)
- rtc_writel(sa1100_rtc, RCNR, time);
+ RCNR = time;
return ret;
}
static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
- unsigned long time;
- unsigned int rtsr;
+ u32 rtsr;
- time = rtc_readl(sa1100_rtc, RCNR);
- rtc_time_to_tm(time, &alrm->time);
- rtsr = rtc_readl(sa1100_rtc, RTSR);
+ memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
+ rtsr = RTSR;
alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
return 0;
static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
- struct rtc_time now_tm, alarm_tm;
- unsigned long time, alarm;
- unsigned int rtsr;
-
- spin_lock_irq(&sa1100_rtc->lock);
-
- time = rtc_readl(sa1100_rtc, RCNR);
- rtc_time_to_tm(time, &now_tm);
- rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
- rtc_tm_to_time(&alarm_tm, &alarm);
- rtc_writel(sa1100_rtc, RTAR, alarm);
-
- rtsr = rtc_readl(sa1100_rtc, RTSR);
- if (alrm->enabled)
- rtsr |= RTSR_ALE;
- else
- rtsr &= ~RTSR_ALE;
- rtc_writel(sa1100_rtc, RTSR, rtsr);
+ int ret;
- spin_unlock_irq(&sa1100_rtc->lock);
+ spin_lock_irq(&sa1100_rtc_lock);
+ ret = rtc_update_alarm(&alrm->time);
+ if (ret == 0) {
+ if (alrm->enabled)
+ RTSR |= RTSR_ALE;
+ else
+ RTSR &= ~RTSR_ALE;
+ }
+ spin_unlock_irq(&sa1100_rtc_lock);
- return 0;
+ return ret;
}
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
+ seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
+ seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
- seq_printf(seq, "trim/divider\t\t: 0x%08x\n",
- rtc_readl(sa1100_rtc, RTTR));
- seq_printf(seq, "RTSR\t\t\t: 0x%08x\n",
- rtc_readl(sa1100_rtc, RTSR));
return 0;
}
static int sa1100_rtc_probe(struct platform_device *pdev)
{
- struct sa1100_rtc *sa1100_rtc;
- unsigned int rttr;
- int ret;
-
- sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
- if (!sa1100_rtc)
- return -ENOMEM;
-
- spin_lock_init(&sa1100_rtc->lock);
- platform_set_drvdata(pdev, sa1100_rtc);
-
- ret = -ENXIO;
- sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!sa1100_rtc->ress) {
- dev_err(&pdev->dev, "No I/O memory resource defined\n");
- goto err_ress;
- }
-
- sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0);
- if (sa1100_rtc->irq_1Hz < 0) {
- dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n");
- goto err_ress;
- }
- sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1);
- if (sa1100_rtc->irq_Alrm < 0) {
- dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
- goto err_ress;
- }
-
- ret = -ENOMEM;
- sa1100_rtc->base = ioremap(sa1100_rtc->ress->start,
- resource_size(sa1100_rtc->ress));
- if (!sa1100_rtc->base) {
- dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n");
- goto err_map;
- }
-
- sa1100_rtc->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(sa1100_rtc->clk)) {
- dev_err(&pdev->dev, "failed to find rtc clock source\n");
- ret = PTR_ERR(sa1100_rtc->clk);
- goto err_clk;
- }
- clk_prepare(sa1100_rtc->clk);
- clk_enable(sa1100_rtc->clk);
+ struct rtc_device *rtc;
/*
* According to the manual we should be able to let RTTR be zero
* If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock.
*/
- if (rtc_readl(sa1100_rtc, RTTR) == 0) {
- rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
- rtc_writel(sa1100_rtc, RTTR, rttr);
- dev_warn(&pdev->dev, "warning: initializing default clock"
- " divider/trim value\n");
+ if (RTTR == 0) {
+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+ dev_warn(&pdev->dev, "warning: "
+ "initializing default clock divider/trim value\n");
/* The current RTC value probably doesn't make sense either */
- rtc_writel(sa1100_rtc, RCNR, 0);
+ RCNR = 0;
}
device_init_wakeup(&pdev->dev, 1);
- sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
- &sa1100_rtc_ops, THIS_MODULE);
- if (IS_ERR(sa1100_rtc->rtc)) {
- dev_err(&pdev->dev, "Failed to register RTC device -> %d\n",
- ret);
- goto err_rtc_reg;
- }
+ rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
+ THIS_MODULE);
+
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ platform_set_drvdata(pdev, rtc);
+
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_interrupt().
*
*
* Notice that clearing bit 1 and 0 is accomplished by writting ONES to
* the corresponding bits in RTSR. */
- rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+ RTSR = RTSR_AL | RTSR_HZ;
return 0;
-
-err_rtc_reg:
-err_clk:
- iounmap(sa1100_rtc->base);
-err_ress:
-err_map:
- kfree(sa1100_rtc);
- return ret;
}
static int sa1100_rtc_remove(struct platform_device *pdev)
{
- struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
- rtc_device_unregister(sa1100_rtc->rtc);
- clk_disable(sa1100_rtc->clk);
- clk_unprepare(sa1100_rtc->clk);
- iounmap(sa1100_rtc->base);
return 0;
}
#ifdef CONFIG_PM
static int sa1100_rtc_suspend(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
if (device_may_wakeup(dev))
- enable_irq_wake(sa1100_rtc->irq_Alrm);
+ enable_irq_wake(IRQ_RTCAlrm);
return 0;
}
static int sa1100_rtc_resume(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
if (device_may_wakeup(dev))
- disable_irq_wake(sa1100_rtc->irq_Alrm);
+ disable_irq_wake(IRQ_RTCAlrm);
return 0;
}
device->path_data.tbvpm |= eventlpm;
dasd_schedule_device_bh(device);
}
+ if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+ DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+ "Pathgroup re-established\n");
+ if (device->discipline->kick_validate)
+ device->discipline->kick_validate(device);
+ }
}
dasd_put_device(device);
}
unsigned long flags;
struct alias_server *server, *newserver;
struct alias_lcu *lcu, *newlcu;
- int is_lcu_known;
struct dasd_uid uid;
private = (struct dasd_eckd_private *) device->private;
device->discipline->get_uid(device, &uid);
spin_lock_irqsave(&aliastree.lock, flags);
- is_lcu_known = 1;
server = _find_server(&uid);
if (!server) {
spin_unlock_irqrestore(&aliastree.lock, flags);
if (!server) {
list_add(&newserver->server, &aliastree.serverlist);
server = newserver;
- is_lcu_known = 0;
} else {
/* someone was faster */
_free_server(newserver);
if (!lcu) {
list_add(&newlcu->lcu, &server->lculist);
lcu = newlcu;
- is_lcu_known = 0;
} else {
/* someone was faster */
_free_lcu(newlcu);
}
- is_lcu_known = 0;
}
spin_lock(&lcu->lock);
list_add(&device->alias_list, &lcu->inactive_devices);
spin_unlock(&lcu->lock);
spin_unlock_irqrestore(&aliastree.lock, flags);
- return is_lcu_known;
-}
-
-/*
- * The first device to be registered on an LCU will have to do
- * some additional setup steps to configure that LCU on the
- * storage server. All further devices should wait with their
- * initialization until the first device is done.
- * To synchronize this work, the first device will call
- * dasd_alias_lcu_setup_complete when it is done, and all
- * other devices will wait for it with dasd_alias_wait_for_lcu_setup.
- */
-void dasd_alias_lcu_setup_complete(struct dasd_device *device)
-{
- unsigned long flags;
- struct alias_server *server;
- struct alias_lcu *lcu;
- struct dasd_uid uid;
-
- device->discipline->get_uid(device, &uid);
- lcu = NULL;
- spin_lock_irqsave(&aliastree.lock, flags);
- server = _find_server(&uid);
- if (server)
- lcu = _find_lcu(server, &uid);
- spin_unlock_irqrestore(&aliastree.lock, flags);
- if (!lcu) {
- DBF_EVENT_DEVID(DBF_ERR, device->cdev,
- "could not find lcu for %04x %02x",
- uid.ssid, uid.real_unit_addr);
- WARN_ON(1);
- return;
- }
- complete_all(&lcu->lcu_setup);
-}
-
-void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
-{
- unsigned long flags;
- struct alias_server *server;
- struct alias_lcu *lcu;
- struct dasd_uid uid;
-
- device->discipline->get_uid(device, &uid);
- lcu = NULL;
- spin_lock_irqsave(&aliastree.lock, flags);
- server = _find_server(&uid);
- if (server)
- lcu = _find_lcu(server, &uid);
- spin_unlock_irqrestore(&aliastree.lock, flags);
- if (!lcu) {
- DBF_EVENT_DEVID(DBF_ERR, device->cdev,
- "could not find lcu for %04x %02x",
- uid.ssid, uid.real_unit_addr);
- WARN_ON(1);
- return;
- }
- wait_for_completion(&lcu->lcu_setup);
+ return 0;
}
/*
struct dasd_eckd_private *private;
int enable_pav;
+ private = (struct dasd_eckd_private *) device->private;
+ if (private->uid.type == UA_BASE_PAV_ALIAS ||
+ private->uid.type == UA_HYPER_PAV_ALIAS)
+ return;
if (dasd_nopav || MACHINE_IS_VM)
enable_pav = 0;
else
/* may be requested feature is not available on server,
* therefore just report error and go ahead */
- private = (struct dasd_eckd_private *) device->private;
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
"returned rc=%d", private->uid.ssid, rc);
}
+/*
+ * worker to do a validate server in case of a lost pathgroup
+ */
+static void dasd_eckd_do_validate_server(struct work_struct *work)
+{
+ struct dasd_device *device = container_of(work, struct dasd_device,
+ kick_validate);
+ dasd_eckd_validate_server(device);
+ dasd_put_device(device);
+}
+
+static void dasd_eckd_kick_validate_server(struct dasd_device *device)
+{
+ dasd_get_device(device);
+ /* queue call to do_validate_server to the kernel event daemon. */
+ schedule_work(&device->kick_validate);
+}
+
static u32 get_fcx_max_data(struct dasd_device *device)
{
#if defined(CONFIG_64BIT)
struct dasd_eckd_private *private;
struct dasd_block *block;
struct dasd_uid temp_uid;
- int is_known, rc, i;
+ int rc, i;
int readonly;
unsigned long value;
+ /* setup work queue for validate server*/
+ INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server);
+
if (!ccw_device_is_pathgroup(device->cdev)) {
dev_warn(&device->cdev->dev,
"A channel path group could not be established\n");
block->base = device;
}
- /* register lcu with alias handling, enable PAV if this is a new lcu */
- is_known = dasd_alias_make_device_known_to_lcu(device);
- if (is_known < 0) {
- rc = is_known;
+ /* register lcu with alias handling, enable PAV */
+ rc = dasd_alias_make_device_known_to_lcu(device);
+ if (rc)
goto out_err2;
- }
- /*
- * dasd_eckd_validate_server is done on the first device that
- * is found for an LCU. All later other devices have to wait
- * for it, so they will read the correct feature codes.
- */
- if (!is_known) {
- dasd_eckd_validate_server(device);
- dasd_alias_lcu_setup_complete(device);
- } else
- dasd_alias_wait_for_lcu_setup(device);
+
+ dasd_eckd_validate_server(device);
/* device may report different configuration data after LCU setup */
rc = dasd_eckd_read_conf(device);
{
struct dasd_eckd_private *private;
struct dasd_eckd_characteristics temp_rdc_data;
- int is_known, rc;
+ int rc;
struct dasd_uid temp_uid;
unsigned long flags;
goto out_err;
/* register lcu with alias handling, enable PAV if this is a new lcu */
- is_known = dasd_alias_make_device_known_to_lcu(device);
- if (is_known < 0)
- return is_known;
- if (!is_known) {
- dasd_eckd_validate_server(device);
- dasd_alias_lcu_setup_complete(device);
- } else
- dasd_alias_wait_for_lcu_setup(device);
+ rc = dasd_alias_make_device_known_to_lcu(device);
+ if (rc)
+ return rc;
+ dasd_eckd_validate_server(device);
/* RE-Read Configuration Data */
rc = dasd_eckd_read_conf(device);
.restore = dasd_eckd_restore_device,
.reload = dasd_eckd_reload_device,
.get_uid = dasd_eckd_get_uid,
+ .kick_validate = dasd_eckd_kick_validate_server,
};
static int __init
int (*reload) (struct dasd_device *);
int (*get_uid) (struct dasd_device *, struct dasd_uid *);
+ void (*kick_validate) (struct dasd_device *);
};
extern struct dasd_discipline *dasd_diag_discipline_pointer;
struct work_struct kick_work;
struct work_struct restore_device;
struct work_struct reload_device;
+ struct work_struct kick_validate;
struct timer_list timer;
debug_info_t *debug_area;
esp_chips[dev->id] = esp;
mb();
if (esp_chips[!dev->id] == NULL) {
- err = request_irq(host->irq, mac_scsi_esp_intr, 0,
- "Mac ESP", NULL);
+ err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
if (err < 0) {
esp_chips[dev->id] = NULL;
goto fail_free_priv;
printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
- /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
- disable_irq(IRQ_MAC_SCSI);
-
/* get in phase */
NCR5380_write( TARGET_COMMAND_REG,
PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
barrier();
- /* switch on SCSI IRQ again */
- enable_irq(IRQ_MAC_SCSI);
-
printk(KERN_INFO " done\n" );
}
#endif
.name = THERMAL_GENL_MCAST_GROUP_NAME,
};
-int generate_netlink_event(u32 orig, enum events event)
+int thermal_generate_netlink_event(u32 orig, enum events event)
{
struct sk_buff *skb;
struct nlattr *attr;
return result;
}
-EXPORT_SYMBOL(generate_netlink_event);
+EXPORT_SYMBOL(thermal_generate_netlink_event);
static int genetlink_init(void)
{
+++ /dev/null
-/*
- * Driver for 8250/16550-type serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King.
- *
- * 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.
- *
- * A note about mapbase / membase
- *
- * mapbase is the physical address of the IO port.
- * membase is an 'ioremapped' cookie.
- */
-
-#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/ratelimit.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/nmi.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "8250.h"
-
-#ifdef CONFIG_SPARC
-#include "suncore.h"
-#endif
-
-/*
- * Configuration:
- * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
- * is unsafe when used on edge-triggered interrupts.
- */
-static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
-
-static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
-
-static struct uart_driver serial8250_reg;
-
-static int serial_index(struct uart_port *port)
-{
- return (serial8250_reg.minor - 64) + port->line;
-}
-
-static unsigned int skip_txen_test; /* force skip of txen test at init time */
-
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
-#define PASS_LIMIT 512
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-
-/*
- * We default to IRQ0 for the "no irq" hack. Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define CONFIG_SERIAL_DETECT_IRQ 1
-#endif
-#ifdef CONFIG_SERIAL_8250_MANY_PORTS
-#define CONFIG_SERIAL_MANY_PORTS 1
-#endif
-
-/*
- * HUB6 is always on. This will be removed once the header
- * files have been cleaned.
- */
-#define CONFIG_HUB6 1
-
-#include <asm/serial.h>
-/*
- * SERIAL_PORT_DFNS tells us about built-in ports that have no
- * standard enumeration mechanism. Platforms that can find all
- * serial ports via mechanisms like ACPI or PCI need not supply it.
- */
-#ifndef SERIAL_PORT_DFNS
-#define SERIAL_PORT_DFNS
-#endif
-
-static const struct old_serial_port old_serial_port[] = {
- SERIAL_PORT_DFNS /* defined in asm/serial.h */
-};
-
-#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
-
-#ifdef CONFIG_SERIAL_8250_RSA
-
-#define PORT_RSA_MAX 4
-static unsigned long probe_rsa[PORT_RSA_MAX];
-static unsigned int probe_rsa_count;
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-struct irq_info {
- struct hlist_node node;
- int irq;
- spinlock_t lock; /* Protects list not the hash */
- struct list_head *head;
-};
-
-#define NR_IRQ_HASH 32 /* Can be adjusted later */
-static struct hlist_head irq_lists[NR_IRQ_HASH];
-static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial8250_config uart_config[] = {
- [PORT_UNKNOWN] = {
- .name = "unknown",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_8250] = {
- .name = "8250",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16450] = {
- .name = "16450",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16550] = {
- .name = "16550",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16550A] = {
- .name = "16550A",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_CIRRUS] = {
- .name = "Cirrus",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16650] = {
- .name = "ST16650",
- .fifo_size = 1,
- .tx_loadsz = 1,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16650V2] = {
- .name = "ST16650V2",
- .fifo_size = 32,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_00,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16750] = {
- .name = "TI16750",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
- UART_FCR7_64BYTE,
- .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
- },
- [PORT_STARTECH] = {
- .name = "Startech",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16C950] = {
- .name = "16C950/954",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- /* UART_CAP_EFR breaks billionon CF bluetooth card. */
- .flags = UART_CAP_FIFO | UART_CAP_SLEEP,
- },
- [PORT_16654] = {
- .name = "ST16654",
- .fifo_size = 64,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16850] = {
- .name = "XR16850",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_RSA] = {
- .name = "RSA",
- .fifo_size = 2048,
- .tx_loadsz = 2048,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
- .flags = UART_CAP_FIFO,
- },
- [PORT_NS16550A] = {
- .name = "NS16550A",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_NATSEMI,
- },
- [PORT_XSCALE] = {
- .name = "XScale",
- .fifo_size = 32,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
- },
- [PORT_RM9000] = {
- .name = "RM9000",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_OCTEON] = {
- .name = "OCTEON",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_AR7] = {
- .name = "AR7",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_U6_16550A] = {
- .name = "U6_16550A",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_TEGRA] = {
- .name = "Tegra",
- .fifo_size = 32,
- .tx_loadsz = 8,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_01,
- .flags = UART_CAP_FIFO | UART_CAP_RTOIE,
- },
- [PORT_XR17D15X] = {
- .name = "XR17D15X",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
- },
-};
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-
-/* Au1x00 UART hardware has a weird register layout */
-static const u8 au_io_in_map[] = {
- [UART_RX] = 0,
- [UART_IER] = 2,
- [UART_IIR] = 3,
- [UART_LCR] = 5,
- [UART_MCR] = 6,
- [UART_LSR] = 7,
- [UART_MSR] = 8,
-};
-
-static const u8 au_io_out_map[] = {
- [UART_TX] = 1,
- [UART_IER] = 2,
- [UART_FCR] = 4,
- [UART_LCR] = 5,
- [UART_MCR] = 6,
-};
-
-/* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_AU)
- return offset;
- return au_io_in_map[offset];
-}
-
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_AU)
- return offset;
- return au_io_out_map[offset];
-}
-
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-
-static const u8
- regmap_in[8] = {
- [UART_RX] = 0x00,
- [UART_IER] = 0x0c,
- [UART_IIR] = 0x14,
- [UART_LCR] = 0x1c,
- [UART_MCR] = 0x20,
- [UART_LSR] = 0x24,
- [UART_MSR] = 0x28,
- [UART_SCR] = 0x2c
- },
- regmap_out[8] = {
- [UART_TX] = 0x04,
- [UART_IER] = 0x0c,
- [UART_FCR] = 0x18,
- [UART_LCR] = 0x1c,
- [UART_MCR] = 0x20,
- [UART_LSR] = 0x24,
- [UART_MSR] = 0x28,
- [UART_SCR] = 0x2c
- };
-
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_RM9000)
- return offset;
- return regmap_in[offset];
-}
-
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
-{
- if (p->iotype != UPIO_RM9000)
- return offset;
- return regmap_out[offset];
-}
-
-#else
-
-/* sane hardware needs no mapping */
-#define map_8250_in_reg(up, offset) (offset)
-#define map_8250_out_reg(up, offset) (offset)
-
-#endif
-
-static unsigned int hub6_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- return inb(p->iobase + 1);
-}
-
-static void hub6_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- outb(value, p->iobase + 1);
-}
-
-static unsigned int mem_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return readb(p->membase + offset);
-}
-
-static void mem_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- writeb(value, p->membase + offset);
-}
-
-static void mem32_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- writel(value, p->membase + offset);
-}
-
-static unsigned int mem32_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return readl(p->membase + offset);
-}
-
-static unsigned int au_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return __raw_readl(p->membase + offset);
-}
-
-static void au_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- __raw_writel(value, p->membase + offset);
-}
-
-static unsigned int io_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return inb(p->iobase + offset);
-}
-
-static void io_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- outb(value, p->iobase + offset);
-}
-
-static int serial8250_default_handle_irq(struct uart_port *port);
-
-static void set_io_from_upio(struct uart_port *p)
-{
- struct uart_8250_port *up =
- container_of(p, struct uart_8250_port, port);
- switch (p->iotype) {
- case UPIO_HUB6:
- p->serial_in = hub6_serial_in;
- p->serial_out = hub6_serial_out;
- break;
-
- case UPIO_MEM:
- p->serial_in = mem_serial_in;
- p->serial_out = mem_serial_out;
- break;
-
- case UPIO_RM9000:
- case UPIO_MEM32:
- p->serial_in = mem32_serial_in;
- p->serial_out = mem32_serial_out;
- break;
-
- case UPIO_AU:
- p->serial_in = au_serial_in;
- p->serial_out = au_serial_out;
- break;
-
- default:
- p->serial_in = io_serial_in;
- p->serial_out = io_serial_out;
- break;
- }
- /* Remember loaded iotype */
- up->cur_iotype = p->iotype;
- p->handle_irq = serial8250_default_handle_irq;
-}
-
-static void
-serial_out_sync(struct uart_8250_port *up, int offset, int value)
-{
- struct uart_port *p = &up->port;
- switch (p->iotype) {
- case UPIO_MEM:
- case UPIO_MEM32:
- case UPIO_AU:
- p->serial_out(p, offset, value);
- p->serial_in(p, UART_LCR); /* safe, no side-effects */
- break;
- default:
- p->serial_out(p, offset, value);
- }
-}
-
-#define serial_in(up, offset) \
- (up->port.serial_in(&(up)->port, (offset)))
-#define serial_out(up, offset, value) \
- (up->port.serial_out(&(up)->port, (offset), (value)))
-/*
- * We used to support using pause I/O for certain machines. We
- * haven't supported this for a while, but just in case it's badly
- * needed for certain old 386 machines, I've left these #define's
- * in....
- */
-#define serial_inp(up, offset) serial_in(up, offset)
-#define serial_outp(up, offset, value) serial_out(up, offset, value)
-
-/* Uart divisor latch read */
-static inline int _serial_dl_read(struct uart_8250_port *up)
-{
- return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
-}
-
-/* Uart divisor latch write */
-static inline void _serial_dl_write(struct uart_8250_port *up, int value)
-{
- serial_outp(up, UART_DLL, value & 0xff);
- serial_outp(up, UART_DLM, value >> 8 & 0xff);
-}
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-/* Au1x00 haven't got a standard divisor latch */
-static int serial_dl_read(struct uart_8250_port *up)
-{
- if (up->port.iotype == UPIO_AU)
- return __raw_readl(up->port.membase + 0x28);
- else
- return _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
- if (up->port.iotype == UPIO_AU)
- __raw_writel(value, up->port.membase + 0x28);
- else
- _serial_dl_write(up, value);
-}
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-static int serial_dl_read(struct uart_8250_port *up)
-{
- return (up->port.iotype == UPIO_RM9000) ?
- (((__raw_readl(up->port.membase + 0x10) << 8) |
- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
- _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
- if (up->port.iotype == UPIO_RM9000) {
- __raw_writel(value, up->port.membase + 0x08);
- __raw_writel(value >> 8, up->port.membase + 0x10);
- } else {
- _serial_dl_write(up, value);
- }
-}
-#else
-#define serial_dl_read(up) _serial_dl_read(up)
-#define serial_dl_write(up, value) _serial_dl_write(up, value)
-#endif
-
-/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-{
- serial_out(up, UART_SCR, offset);
- serial_out(up, UART_ICR, value);
-}
-
-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-{
- unsigned int value;
-
- serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
- serial_out(up, UART_SCR, offset);
- value = serial_in(up, UART_ICR);
- serial_icr_write(up, UART_ACR, up->acr);
-
- return value;
-}
-
-/*
- * FIFO support.
- */
-static void serial8250_clear_fifos(struct uart_8250_port *p)
-{
- if (p->capabilities & UART_CAP_FIFO) {
- serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(p, UART_FCR, 0);
- }
-}
-
-/*
- * IER sleep support. UARTs which have EFRs need the "extended
- * capability" bit enabled. Note that on XR16C850s, we need to
- * reset LCR to write to IER.
- */
-static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
-{
- if (p->capabilities & UART_CAP_SLEEP) {
- if (p->capabilities & UART_CAP_EFR) {
- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(p, UART_EFR, UART_EFR_ECB);
- serial_outp(p, UART_LCR, 0);
- }
- serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
- if (p->capabilities & UART_CAP_EFR) {
- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(p, UART_EFR, 0);
- serial_outp(p, UART_LCR, 0);
- }
- }
-}
-
-#ifdef CONFIG_SERIAL_8250_RSA
-/*
- * Attempts to turn on the RSA FIFO. Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __enable_rsa(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- mode = serial_inp(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
-
- if (!result) {
- serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
- mode = serial_inp(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
- return result;
-}
-
-static void enable_rsa(struct uart_8250_port *up)
-{
- if (up->port.type == PORT_RSA) {
- if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
- __enable_rsa(up);
- spin_unlock_irq(&up->port.lock);
- }
- if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
- serial_outp(up, UART_RSA_FRR, 0);
- }
-}
-
-/*
- * Attempts to turn off the RSA FIFO. Returns zero on failure.
- * It is unknown why interrupts were disabled in here. However,
- * the caller is expected to preserve this behaviour by grabbing
- * the spinlock before calling this function.
- */
-static void disable_rsa(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- if (up->port.type == PORT_RSA &&
- up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
-
- mode = serial_inp(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
-
- if (!result) {
- serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
- mode = serial_inp(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
- spin_unlock_irq(&up->port.lock);
- }
-}
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-/*
- * This is a quickie test to see how big the FIFO is.
- * It doesn't work at all the time, more's the pity.
- */
-static int size_fifo(struct uart_8250_port *up)
-{
- unsigned char old_fcr, old_mcr, old_lcr;
- unsigned short old_dl;
- int count;
-
- old_lcr = serial_inp(up, UART_LCR);
- serial_outp(up, UART_LCR, 0);
- old_fcr = serial_inp(up, UART_FCR);
- old_mcr = serial_inp(up, UART_MCR);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_MCR, UART_MCR_LOOP);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- old_dl = serial_dl_read(up);
- serial_dl_write(up, 0x0001);
- serial_outp(up, UART_LCR, 0x03);
- for (count = 0; count < 256; count++)
- serial_outp(up, UART_TX, count);
- mdelay(20);/* FIXME - schedule_timeout */
- for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
- (count < 256); count++)
- serial_inp(up, UART_RX);
- serial_outp(up, UART_FCR, old_fcr);
- serial_outp(up, UART_MCR, old_mcr);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_dl_write(up, old_dl);
- serial_outp(up, UART_LCR, old_lcr);
-
- return count;
-}
-
-/*
- * Read UART ID using the divisor method - set DLL and DLM to zero
- * and the revision will be in DLL and device type in DLM. We
- * preserve the device state across this.
- */
-static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
-{
- unsigned char old_dll, old_dlm, old_lcr;
- unsigned int id;
-
- old_lcr = serial_inp(p, UART_LCR);
- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
-
- old_dll = serial_inp(p, UART_DLL);
- old_dlm = serial_inp(p, UART_DLM);
-
- serial_outp(p, UART_DLL, 0);
- serial_outp(p, UART_DLM, 0);
-
- id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
-
- serial_outp(p, UART_DLL, old_dll);
- serial_outp(p, UART_DLM, old_dlm);
- serial_outp(p, UART_LCR, old_lcr);
-
- return id;
-}
-
-/*
- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
- * When this function is called we know it is at least a StarTech
- * 16650 V2, but it might be one of several StarTech UARTs, or one of
- * its clones. (We treat the broken original StarTech 16650 V1 as a
- * 16550, and why not? Startech doesn't seem to even acknowledge its
- * existence.)
- *
- * What evil have men's minds wrought...
- */
-static void autoconfig_has_efr(struct uart_8250_port *up)
-{
- unsigned int id1, id2, id3, rev;
-
- /*
- * Everything with an EFR has SLEEP
- */
- up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-
- /*
- * First we check to see if it's an Oxford Semiconductor UART.
- *
- * If we have to do this here because some non-National
- * Semiconductor clone chips lock up if you try writing to the
- * LSR register (which serial_icr_read does)
- */
-
- /*
- * Check for Oxford Semiconductor 16C950.
- *
- * EFR [4] must be set else this test fails.
- *
- * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
- * claims that it's needed for 952 dual UART's (which are not
- * recommended for new designs).
- */
- up->acr = 0;
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
- serial_out(up, UART_LCR, 0x00);
- id1 = serial_icr_read(up, UART_ID1);
- id2 = serial_icr_read(up, UART_ID2);
- id3 = serial_icr_read(up, UART_ID3);
- rev = serial_icr_read(up, UART_REV);
-
- DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-
- if (id1 == 0x16 && id2 == 0xC9 &&
- (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
- up->port.type = PORT_16C950;
-
- /*
- * Enable work around for the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
- */
- if (id3 == 0x52 && rev == 0x01)
- up->bugs |= UART_BUG_QUOT;
- return;
- }
-
- /*
- * We check for a XR16C850 by setting DLL and DLM to 0, and then
- * reading back DLL and DLM. The chip type depends on the DLM
- * value read back:
- * 0x10 - XR16C850 and the DLL contains the chip revision.
- * 0x12 - XR16C2850.
- * 0x14 - XR16C854.
- */
- id1 = autoconfig_read_divisor_id(up);
- DEBUG_AUTOCONF("850id=%04x ", id1);
-
- id2 = id1 >> 8;
- if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
- up->port.type = PORT_16850;
- return;
- }
-
- /*
- * It wasn't an XR16C850.
- *
- * We distinguish between the '654 and the '650 by counting
- * how many bytes are in the FIFO. I'm using this for now,
- * since that's the technique that was sent to me in the
- * serial driver update, but I'm not convinced this works.
- * I've had problems doing this in the past. -TYT
- */
- if (size_fifo(up) == 64)
- up->port.type = PORT_16654;
- else
- up->port.type = PORT_16650V2;
-}
-
-/*
- * We detected a chip without a FIFO. Only two fall into
- * this category - the original 8250 and the 16450. The
- * 16450 has a scratch register (accessible with LCR=0)
- */
-static void autoconfig_8250(struct uart_8250_port *up)
-{
- unsigned char scratch, status1, status2;
-
- up->port.type = PORT_8250;
-
- scratch = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, 0xa5);
- status1 = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, 0x5a);
- status2 = serial_in(up, UART_SCR);
- serial_outp(up, UART_SCR, scratch);
-
- if (status1 == 0xa5 && status2 == 0x5a)
- up->port.type = PORT_16450;
-}
-
-static int broken_efr(struct uart_8250_port *up)
-{
- /*
- * Exar ST16C2550 "A2" devices incorrectly detect as
- * having an EFR, and report an ID of 0x0201. See
- * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
- */
- if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
- return 1;
-
- return 0;
-}
-
-static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
-{
- unsigned char status;
-
- status = serial_in(up, 0x04); /* EXCR2 */
-#define PRESL(x) ((x) & 0x30)
- if (PRESL(status) == 0x10) {
- /* already in high speed mode */
- return 0;
- } else {
- status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
- status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
- serial_outp(up, 0x04, status);
- }
- return 1;
-}
-
-/*
- * We know that the chip has FIFOs. Does it have an EFR? The
- * EFR is located in the same register position as the IIR and
- * we know the top two bits of the IIR are currently set. The
- * EFR should contain zero. Try to read the EFR.
- */
-static void autoconfig_16550a(struct uart_8250_port *up)
-{
- unsigned char status1, status2;
- unsigned int iersave;
-
- up->port.type = PORT_16550A;
- up->capabilities |= UART_CAP_FIFO;
-
- /*
- * Check for presence of the EFR when DLAB is set.
- * Only ST16C650V1 UARTs pass this test.
- */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- if (serial_in(up, UART_EFR) == 0) {
- serial_outp(up, UART_EFR, 0xA8);
- if (serial_in(up, UART_EFR) != 0) {
- DEBUG_AUTOCONF("EFRv1 ");
- up->port.type = PORT_16650;
- up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
- } else {
- DEBUG_AUTOCONF("Motorola 8xxx DUART ");
- }
- serial_outp(up, UART_EFR, 0);
- return;
- }
-
- /*
- * Maybe it requires 0xbf to be written to the LCR.
- * (other ST16C650V2 UARTs, TI16C752A, etc)
- */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
- DEBUG_AUTOCONF("EFRv2 ");
- autoconfig_has_efr(up);
- return;
- }
-
- /*
- * Check for a National Semiconductor SuperIO chip.
- * Attempt to switch to bank 2, read the value of the LOOP bit
- * from EXCR1. Switch back to bank 0, change it in MCR. Then
- * switch back to bank 2, read it from EXCR1 again and check
- * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
- */
- serial_outp(up, UART_LCR, 0);
- status1 = serial_in(up, UART_MCR);
- serial_outp(up, UART_LCR, 0xE0);
- status2 = serial_in(up, 0x02); /* EXCR1 */
-
- if (!((status2 ^ status1) & UART_MCR_LOOP)) {
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
- serial_outp(up, UART_LCR, 0xE0);
- status2 = serial_in(up, 0x02); /* EXCR1 */
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_MCR, status1);
-
- if ((status2 ^ status1) & UART_MCR_LOOP) {
- unsigned short quot;
-
- serial_outp(up, UART_LCR, 0xE0);
-
- quot = serial_dl_read(up);
- quot <<= 3;
-
- if (ns16550a_goto_highspeed(up))
- serial_dl_write(up, quot);
-
- serial_outp(up, UART_LCR, 0);
-
- up->port.uartclk = 921600*16;
- up->port.type = PORT_NS16550A;
- up->capabilities |= UART_NATSEMI;
- return;
- }
- }
-
- /*
- * No EFR. Try to detect a TI16750, which only sets bit 5 of
- * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
- * Try setting it with and without DLAB set. Cheap clones
- * set bit 5 without DLAB set.
- */
- serial_outp(up, UART_LCR, 0);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- status1 = serial_in(up, UART_IIR) >> 5;
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- status2 = serial_in(up, UART_IIR) >> 5;
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_LCR, 0);
-
- DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-
- if (status1 == 6 && status2 == 7) {
- up->port.type = PORT_16750;
- up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
- return;
- }
-
- /*
- * Try writing and reading the UART_IER_UUE bit (b6).
- * If it works, this is probably one of the Xscale platform's
- * internal UARTs.
- * We're going to explicitly set the UUE bit to 0 before
- * trying to write and read a 1 just to make sure it's not
- * already a 1 and maybe locked there before we even start start.
- */
- iersave = serial_in(up, UART_IER);
- serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
- if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
- /*
- * OK it's in a known zero state, try writing and reading
- * without disturbing the current state of the other bits.
- */
- serial_outp(up, UART_IER, iersave | UART_IER_UUE);
- if (serial_in(up, UART_IER) & UART_IER_UUE) {
- /*
- * It's an Xscale.
- * We'll leave the UART_IER_UUE bit set to 1 (enabled).
- */
- DEBUG_AUTOCONF("Xscale ");
- up->port.type = PORT_XSCALE;
- up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
- return;
- }
- } else {
- /*
- * If we got here we couldn't force the IER_UUE bit to 0.
- * Log it and continue.
- */
- DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
- }
- serial_outp(up, UART_IER, iersave);
-
- /*
- * Exar uarts have EFR in a weird location
- */
- if (up->port.flags & UPF_EXAR_EFR) {
- up->port.type = PORT_XR17D15X;
- up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
- }
-
- /*
- * We distinguish between 16550A and U6 16550A by counting
- * how many bytes are in the FIFO.
- */
- if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
- up->port.type = PORT_U6_16550A;
- up->capabilities |= UART_CAP_AFE;
- }
-}
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port. It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A. The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-{
- unsigned char status1, scratch, scratch2, scratch3;
- unsigned char save_lcr, save_mcr;
- unsigned long flags;
-
- if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
- return;
-
- DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
- serial_index(&up->port), up->port.iobase, up->port.membase);
-
- /*
- * We really do need global IRQs disabled here - we're going to
- * be frobbing the chips IRQ enable register to see if it exists.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->capabilities = 0;
- up->bugs = 0;
-
- if (!(up->port.flags & UPF_BUGGY_UART)) {
- /*
- * Do a simple existence test first; if we fail this,
- * there's no point trying anything else.
- *
- * 0x80 is used as a nonsense port to prevent against
- * false positives due to ISA bus float. The
- * assumption is that 0x80 is a non-existent port;
- * which should be safe since include/asm/io.h also
- * makes this assumption.
- *
- * Note: this is safe as long as MCR bit 4 is clear
- * and the device is in "PC" mode.
- */
- scratch = serial_inp(up, UART_IER);
- serial_outp(up, UART_IER, 0);
-#ifdef __i386__
- outb(0xff, 0x080);
-#endif
- /*
- * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
- * 16C754B) allow only to modify them if an EFR bit is set.
- */
- scratch2 = serial_inp(up, UART_IER) & 0x0f;
- serial_outp(up, UART_IER, 0x0F);
-#ifdef __i386__
- outb(0, 0x080);
-#endif
- scratch3 = serial_inp(up, UART_IER) & 0x0f;
- serial_outp(up, UART_IER, scratch);
- if (scratch2 != 0 || scratch3 != 0x0F) {
- /*
- * We failed; there's nothing here
- */
- DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
- scratch2, scratch3);
- goto out;
- }
- }
-
- save_mcr = serial_in(up, UART_MCR);
- save_lcr = serial_in(up, UART_LCR);
-
- /*
- * Check to see if a UART is really there. Certain broken
- * internal modems based on the Rockwell chipset fail this
- * test, because they apparently don't implement the loopback
- * test mode. So this test is skipped on the COM 1 through
- * COM 4 ports. This *should* be safe, since no board
- * manufacturer would be stupid enough to design a board
- * that conflicts with COM 1-4 --- we hope!
- */
- if (!(up->port.flags & UPF_SKIP_TEST)) {
- serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
- status1 = serial_inp(up, UART_MSR) & 0xF0;
- serial_outp(up, UART_MCR, save_mcr);
- if (status1 != 0x90) {
- DEBUG_AUTOCONF("LOOP test failed (%02x) ",
- status1);
- goto out;
- }
- }
-
- /*
- * We're pretty sure there's a port here. Lets find out what
- * type of port it is. The IIR top two bits allows us to find
- * out if it's 8250 or 16450, 16550, 16550A or later. This
- * determines what we test for next.
- *
- * We also initialise the EFR (if any) to zero for later. The
- * EFR occupies the same register location as the FCR and IIR.
- */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(up, UART_EFR, 0);
- serial_outp(up, UART_LCR, 0);
-
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- scratch = serial_in(up, UART_IIR) >> 6;
-
- DEBUG_AUTOCONF("iir=%d ", scratch);
-
- switch (scratch) {
- case 0:
- autoconfig_8250(up);
- break;
- case 1:
- up->port.type = PORT_UNKNOWN;
- break;
- case 2:
- up->port.type = PORT_16550;
- break;
- case 3:
- autoconfig_16550a(up);
- break;
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Only probe for RSA ports if we got the region.
- */
- if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
- int i;
-
- for (i = 0 ; i < probe_rsa_count; ++i) {
- if (probe_rsa[i] == up->port.iobase &&
- __enable_rsa(up)) {
- up->port.type = PORT_RSA;
- break;
- }
- }
- }
-#endif
-
- serial_outp(up, UART_LCR, save_lcr);
-
- if (up->capabilities != uart_config[up->port.type].flags) {
- printk(KERN_WARNING
- "ttyS%d: detected caps %08x should be %08x\n",
- serial_index(&up->port), up->capabilities,
- uart_config[up->port.type].flags);
- }
-
- up->port.fifosize = uart_config[up->port.type].fifo_size;
- up->capabilities = uart_config[up->port.type].flags;
- up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
-
- if (up->port.type == PORT_UNKNOWN)
- goto out;
-
- /*
- * Reset the UART.
- */
-#ifdef CONFIG_SERIAL_8250_RSA
- if (up->port.type == PORT_RSA)
- serial_outp(up, UART_RSA_FRR, 0);
-#endif
- serial_outp(up, UART_MCR, save_mcr);
- serial8250_clear_fifos(up);
- serial_in(up, UART_RX);
- if (up->capabilities & UART_CAP_UUE)
- serial_outp(up, UART_IER, UART_IER_UUE);
- else
- serial_outp(up, UART_IER, 0);
-
- out:
- spin_unlock_irqrestore(&up->port.lock, flags);
- DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-}
-
-static void autoconfig_irq(struct uart_8250_port *up)
-{
- unsigned char save_mcr, save_ier;
- unsigned char save_ICP = 0;
- unsigned int ICP = 0;
- unsigned long irqs;
- int irq;
-
- if (up->port.flags & UPF_FOURPORT) {
- ICP = (up->port.iobase & 0xfe0) | 0x1f;
- save_ICP = inb_p(ICP);
- outb_p(0x80, ICP);
- (void) inb_p(ICP);
- }
-
- /* forget possible initially masked and pending IRQ */
- probe_irq_off(probe_irq_on());
- save_mcr = serial_inp(up, UART_MCR);
- save_ier = serial_inp(up, UART_IER);
- serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
- irqs = probe_irq_on();
- serial_outp(up, UART_MCR, 0);
- udelay(10);
- if (up->port.flags & UPF_FOURPORT) {
- serial_outp(up, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS);
- } else {
- serial_outp(up, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
- }
- serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
- (void)serial_inp(up, UART_LSR);
- (void)serial_inp(up, UART_RX);
- (void)serial_inp(up, UART_IIR);
- (void)serial_inp(up, UART_MSR);
- serial_outp(up, UART_TX, 0xFF);
- udelay(20);
- irq = probe_irq_off(irqs);
-
- serial_outp(up, UART_MCR, save_mcr);
- serial_outp(up, UART_IER, save_ier);
-
- if (up->port.flags & UPF_FOURPORT)
- outb_p(save_ICP, ICP);
-
- up->port.irq = (irq > 0) ? irq : 0;
-}
-
-static inline void __stop_tx(struct uart_8250_port *p)
-{
- if (p->ier & UART_IER_THRI) {
- p->ier &= ~UART_IER_THRI;
- serial_out(p, UART_IER, p->ier);
- }
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- __stop_tx(up);
-
- /*
- * We really want to stop the transmitter from sending.
- */
- if (up->port.type == PORT_16C950) {
- up->acr |= UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void serial8250_start_tx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
-
- if (up->bugs & UART_BUG_TXEN) {
- unsigned char lsr;
- lsr = serial_in(up, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- if ((up->port.type == PORT_RM9000) ?
- (lsr & UART_LSR_THRE) :
- (lsr & UART_LSR_TEMT))
- serial8250_tx_chars(up);
- }
- }
-
- /*
- * Re-enable the transmitter if we disabled it.
- */
- if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
- up->acr &= ~UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- /* no MSR capabilities */
- if (up->bugs & UART_BUG_NOMSR)
- return;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-/*
- * Clear the Tegra rx fifo after a break
- *
- * FIXME: This needs to become a port specific callback once we have a
- * framework for this
- */
-static void clear_rx_fifo(struct uart_8250_port *up)
-{
- unsigned int status, tmout = 10000;
- do {
- status = serial_in(up, UART_LSR);
- if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
- status = serial_in(up, UART_RX);
- else
- break;
- if (--tmout == 0)
- break;
- udelay(1);
- } while (1);
-}
-
-/*
- * serial8250_rx_chars: processes according to the passed in LSR
- * value, and returns the remaining LSR bits not handled
- * by this Rx routine.
- */
-unsigned char
-serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch;
- int max_count = 256;
- char flag;
-
- do {
- if (likely(lsr & UART_LSR_DR))
- ch = serial_inp(up, UART_RX);
- else
- /*
- * Intel 82571 has a Serial Over Lan device that will
- * set UART_LSR_BI without setting UART_LSR_DR when
- * it receives a break. To avoid reading from the
- * receive buffer without UART_LSR_DR bit set, we
- * just force the read character to be 0
- */
- ch = 0;
-
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- lsr |= up->lsr_saved_flags;
- up->lsr_saved_flags = 0;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- /*
- * For statistics only
- */
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * If tegra port then clear the rx fifo to
- * accept another break/character.
- */
- if (up->port.type == PORT_TEGRA)
- clear_rx_fifo(up);
-
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (lsr & UART_LSR_PE)
- up->port.icount.parity++;
- else if (lsr & UART_LSR_FE)
- up->port.icount.frame++;
- if (lsr & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- lsr &= up->port.read_status_mask;
-
- if (lsr & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
-
- uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
-
-ignore_char:
- lsr = serial_inp(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
- return lsr;
-}
-EXPORT_SYMBOL_GPL(serial8250_rx_chars);
-
-void serial8250_tx_chars(struct uart_8250_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_outp(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_tx_stopped(&up->port)) {
- serial8250_stop_tx(&up->port);
- return;
- }
- if (uart_circ_empty(xmit)) {
- __stop_tx(up);
- return;
- }
-
- count = up->tx_loadsz;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- DEBUG_INTR("THRE...");
-
- if (uart_circ_empty(xmit))
- __stop_tx(up);
-}
-EXPORT_SYMBOL_GPL(serial8250_tx_chars);
-
-unsigned int serial8250_modem_status(struct uart_8250_port *up)
-{
- unsigned int status = serial_in(up, UART_MSR);
-
- status |= up->msr_saved_flags;
- up->msr_saved_flags = 0;
- if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
- up->port.state != NULL) {
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
- }
-
- return status;
-}
-EXPORT_SYMBOL_GPL(serial8250_modem_status);
-
-/*
- * This handles the interrupt from one port.
- */
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
-{
- unsigned char status;
- unsigned long flags;
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- if (iir & UART_IIR_NO_INT)
- return 0;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- status = serial_inp(up, UART_LSR);
-
- DEBUG_INTR("status = %x...", status);
-
- if (status & (UART_LSR_DR | UART_LSR_BI))
- status = serial8250_rx_chars(up, status);
- serial8250_modem_status(up);
- if (status & UART_LSR_THRE)
- serial8250_tx_chars(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
- return 1;
-}
-EXPORT_SYMBOL_GPL(serial8250_handle_irq);
-
-static int serial8250_default_handle_irq(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned int iir = serial_in(up, UART_IIR);
-
- return serial8250_handle_irq(port, iir);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts. (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
-{
- struct irq_info *i = dev_id;
- struct list_head *l, *end = NULL;
- int pass_counter = 0, handled = 0;
-
- DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-
- spin_lock(&i->lock);
-
- l = i->head;
- do {
- struct uart_8250_port *up;
- struct uart_port *port;
- bool skip;
-
- up = list_entry(l, struct uart_8250_port, list);
- port = &up->port;
- skip = pass_counter && up->port.flags & UPF_IIR_ONCE;
-
- if (!skip && port->handle_irq(port)) {
- handled = 1;
- end = NULL;
- } else if (end == NULL)
- end = l;
-
- l = l->next;
-
- if (l == i->head && pass_counter++ > PASS_LIMIT) {
- /* If we hit this, we're dead. */
- printk_ratelimited(KERN_ERR
- "serial8250: too much work for irq%d\n", irq);
- break;
- }
- } while (l != end);
-
- spin_unlock(&i->lock);
-
- DEBUG_INTR("end.\n");
-
- return IRQ_RETVAL(handled);
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning. Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-{
- spin_lock_irq(&i->lock);
-
- if (!list_empty(i->head)) {
- if (i->head == &up->list)
- i->head = i->head->next;
- list_del(&up->list);
- } else {
- BUG_ON(i->head != &up->list);
- i->head = NULL;
- }
- spin_unlock_irq(&i->lock);
- /* List empty so throw away the hash node */
- if (i->head == NULL) {
- hlist_del(&i->node);
- kfree(i);
- }
-}
-
-static int serial_link_irq_chain(struct uart_8250_port *up)
-{
- struct hlist_head *h;
- struct hlist_node *n;
- struct irq_info *i;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-
- mutex_lock(&hash_mutex);
-
- h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
- hlist_for_each(n, h) {
- i = hlist_entry(n, struct irq_info, node);
- if (i->irq == up->port.irq)
- break;
- }
-
- if (n == NULL) {
- i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
- if (i == NULL) {
- mutex_unlock(&hash_mutex);
- return -ENOMEM;
- }
- spin_lock_init(&i->lock);
- i->irq = up->port.irq;
- hlist_add_head(&i->node, h);
- }
- mutex_unlock(&hash_mutex);
-
- spin_lock_irq(&i->lock);
-
- if (i->head) {
- list_add(&up->list, i->head);
- spin_unlock_irq(&i->lock);
-
- ret = 0;
- } else {
- INIT_LIST_HEAD(&up->list);
- i->head = &up->list;
- spin_unlock_irq(&i->lock);
- irq_flags |= up->port.irqflags;
- ret = request_irq(up->port.irq, serial8250_interrupt,
- irq_flags, "serial", i);
- if (ret < 0)
- serial_do_unlink(i, up);
- }
-
- return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_8250_port *up)
-{
- struct irq_info *i;
- struct hlist_node *n;
- struct hlist_head *h;
-
- mutex_lock(&hash_mutex);
-
- h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
- hlist_for_each(n, h) {
- i = hlist_entry(n, struct irq_info, node);
- if (i->irq == up->port.irq)
- break;
- }
-
- BUG_ON(n == NULL);
- BUG_ON(i->head == NULL);
-
- if (list_empty(i->head))
- free_irq(up->port.irq, i);
-
- serial_do_unlink(i, up);
- mutex_unlock(&hash_mutex);
-}
-
-/*
- * This function is used to handle ports that do not have an
- * interrupt. This doesn't work very well for 16450's, but gives
- * barely passable results for a 16550A. (Although at the expense
- * of much CPU overhead).
- */
-static void serial8250_timeout(unsigned long data)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)data;
-
- up->port.handle_irq(&up->port);
- mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
-}
-
-static void serial8250_backup_timeout(unsigned long data)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int iir, ier = 0, lsr;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Must disable interrupts or else we risk racing with the interrupt
- * based handler.
- */
- if (is_real_interrupt(up->port.irq)) {
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
- }
-
- iir = serial_in(up, UART_IIR);
-
- /*
- * This should be a safe test for anyone who doesn't trust the
- * IIR bits on their UART, but it's specifically designed for
- * the "Diva" UART used on the management processor on many HP
- * ia64 and parisc boxes.
- */
- lsr = serial_in(up, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
- (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
- (lsr & UART_LSR_THRE)) {
- iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
- iir |= UART_IIR_THRI;
- }
-
- if (!(iir & UART_IIR_NO_INT))
- serial8250_tx_chars(up);
-
- if (is_real_interrupt(up->port.irq))
- serial_out(up, UART_IER, ier);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /* Standard timer interval plus 0.2s to keep the port running */
- mod_timer(&up->timer,
- jiffies + uart_poll_timeout(&up->port) + HZ / 5);
-}
-
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
- unsigned int lsr;
-
- spin_lock_irqsave(&up->port.lock, flags);
- lsr = serial_in(up, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned int status;
- unsigned int ret;
-
- status = serial8250_modem_status(up);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- for (;;) {
- status = serial_in(up, UART_LSR);
-
- up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
-
- if ((status & bits) == bits)
- break;
- if (--tmout == 0)
- break;
- udelay(1);
- }
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- unsigned int tmout;
- for (tmout = 1000000; tmout; tmout--) {
- unsigned int msr = serial_in(up, UART_MSR);
- up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
- if (msr & UART_MSR_CTS)
- break;
- udelay(1);
- touch_nmi_watchdog();
- }
- }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial8250_get_poll_char(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned char lsr = serial_inp(up, UART_LSR);
-
- if (!(lsr & UART_LSR_DR))
- return NO_POLL_CHAR;
-
- return serial_inp(up, UART_RX);
-}
-
-
-static void serial8250_put_poll_char(struct uart_port *port,
- unsigned char c)
-{
- unsigned int ier;
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- if (up->capabilities & UART_CAP_UUE)
- serial_out(up, UART_IER, UART_IER_UUE);
- else
- serial_out(up, UART_IER, 0);
-
- wait_for_xmitr(up, BOTH_EMPTY);
- /*
- * Send the character out.
- * If a LF, also do CR...
- */
- serial_out(up, UART_TX, c);
- if (c == 10) {
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_out(up, UART_TX, 13);
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int serial8250_startup(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
- unsigned char lsr, iir;
- int retval;
-
- up->port.fifosize = uart_config[up->port.type].fifo_size;
- up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
- up->capabilities = uart_config[up->port.type].flags;
- up->mcr = 0;
-
- if (up->port.iotype != up->cur_iotype)
- set_io_from_upio(port);
-
- if (up->port.type == PORT_16C950) {
- /* Wake up and initialize UART */
- up->acr = 0;
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(up, UART_EFR, UART_EFR_ECB);
- serial_outp(up, UART_IER, 0);
- serial_outp(up, UART_LCR, 0);
- serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_outp(up, UART_EFR, UART_EFR_ECB);
- serial_outp(up, UART_LCR, 0);
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * If this is an RSA port, see if we can kick it up to the
- * higher speed clock.
- */
- enable_rsa(up);
-#endif
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- serial8250_clear_fifos(up);
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- /*
- * At this point, there's no way the LSR could still be 0xff;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (!(up->port.flags & UPF_BUGGY_UART) &&
- (serial_inp(up, UART_LSR) == 0xff)) {
- printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
- serial_index(&up->port));
- return -ENODEV;
- }
-
- /*
- * For a XR16C850, we need to set the trigger levels
- */
- if (up->port.type == PORT_16850) {
- unsigned char fctr;
-
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
- serial_outp(up, UART_TRG, UART_TRG_96);
- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
- serial_outp(up, UART_TRG, UART_TRG_96);
-
- serial_outp(up, UART_LCR, 0);
- }
-
- if (is_real_interrupt(up->port.irq)) {
- unsigned char iir1;
- /*
- * Test for UARTs that do not reassert THRE when the
- * transmitter is idle and the interrupt has already
- * been cleared. Real 16550s should always reassert
- * this interrupt whenever the transmitter is idle and
- * the interrupt is enabled. Delays are necessary to
- * allow register changes to become visible.
- */
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.irqflags & IRQF_SHARED)
- disable_irq_nosync(up->port.irq);
-
- wait_for_xmitr(up, UART_LSR_THRE);
- serial_out_sync(up, UART_IER, UART_IER_THRI);
- udelay(1); /* allow THRE to set */
- iir1 = serial_in(up, UART_IIR);
- serial_out(up, UART_IER, 0);
- serial_out_sync(up, UART_IER, UART_IER_THRI);
- udelay(1); /* allow a working UART time to re-assert THRE */
- iir = serial_in(up, UART_IIR);
- serial_out(up, UART_IER, 0);
-
- if (up->port.irqflags & IRQF_SHARED)
- enable_irq(up->port.irq);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * If the interrupt is not reasserted, setup a timer to
- * kick the UART on a regular basis.
- */
- if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
- up->bugs |= UART_BUG_THRE;
- pr_debug("ttyS%d - using backup timer\n",
- serial_index(port));
- }
- }
-
- /*
- * The above check will only give an accurate result the first time
- * the port is opened so this value needs to be preserved.
- */
- if (up->bugs & UART_BUG_THRE) {
- up->timer.function = serial8250_backup_timeout;
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies +
- uart_poll_timeout(port) + HZ / 5);
- }
-
- /*
- * If the "interrupt" for this port doesn't correspond with any
- * hardware interrupt, we use a timer-based system. The original
- * driver used to do this with IRQ0.
- */
- if (!is_real_interrupt(up->port.irq)) {
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
- } else {
- retval = serial_link_irq_chain(up);
- if (retval)
- return retval;
- }
-
- /*
- * Now, initialize the UART
- */
- serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- if (!is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT1;
- } else
- /*
- * Most PC uarts need OUT2 raised to enable interrupts.
- */
- if (is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
-
- /* Serial over Lan (SoL) hack:
- Intel 8257x Gigabit ethernet chips have a
- 16550 emulation, to be used for Serial Over Lan.
- Those chips take a longer time than a normal
- serial device to signalize that a transmission
- data was queued. Due to that, the above test generally
- fails. One solution would be to delay the reading of
- iir. However, this is not reliable, since the timeout
- is variable. So, let's just don't test if we receive
- TX irq. This way, we'll never enable UART_BUG_TXEN.
- */
- if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
- goto dont_test_tx_en;
-
- /*
- * Do a quick test to see if we receive an
- * interrupt when we enable the TX irq.
- */
- serial_outp(up, UART_IER, UART_IER_THRI);
- lsr = serial_in(up, UART_LSR);
- iir = serial_in(up, UART_IIR);
- serial_outp(up, UART_IER, 0);
-
- if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
- if (!(up->bugs & UART_BUG_TXEN)) {
- up->bugs |= UART_BUG_TXEN;
- pr_debug("ttyS%d - enabling bad tx status workarounds\n",
- serial_index(port));
- }
- } else {
- up->bugs &= ~UART_BUG_TXEN;
- }
-
-dont_test_tx_en:
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Clear the interrupt registers again for luck, and clear the
- * saved flags to avoid getting false values from polling
- * routines or the previous session.
- */
- serial_inp(up, UART_LSR);
- serial_inp(up, UART_RX);
- serial_inp(up, UART_IIR);
- serial_inp(up, UART_MSR);
- up->lsr_saved_flags = 0;
- up->msr_saved_flags = 0;
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_outp(up, UART_IER, up->ier);
-
- if (up->port.flags & UPF_FOURPORT) {
- unsigned int icp;
- /*
- * Enable interrupts on the AST Fourport board
- */
- icp = (up->port.iobase & 0xfe0) | 0x01f;
- outb_p(0x80, icp);
- (void) inb_p(icp);
- }
-
- return 0;
-}
-
-static void serial8250_shutdown(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned long flags;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_outp(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- /* reset interrupts on the AST Fourport board */
- inb((up->port.iobase & 0xfe0) | 0x1f);
- up->port.mctrl |= TIOCM_OUT1;
- } else
- up->port.mctrl &= ~TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
- serial8250_clear_fifos(up);
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Reset the RSA board back to 115kbps compat mode.
- */
- disable_rsa(up);
-#endif
-
- /*
- * Read data port to reset things, and then unlink from
- * the IRQ chain.
- */
- (void) serial_in(up, UART_RX);
-
- del_timer_sync(&up->timer);
- up->timer.function = serial8250_timeout;
- if (is_real_interrupt(up->port.irq))
- serial_unlink_irq_chain(up);
-}
-
-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int quot;
-
- /*
- * Handle magic divisors for baud rates above baud_base on
- * SMSC SuperIO chips.
- */
- if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/4))
- quot = 0x8001;
- else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/8))
- quot = 0x8002;
- else
- quot = uart_get_divisor(port, baud);
-
- return quot;
-}
-
-void
-serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- unsigned char cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
- quot = serial8250_get_divisor(port, baud);
-
- /*
- * Oxford Semi 952 rev B workaround
- */
- if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
- quot++;
-
- if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
- if (baud < 2400)
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
- else
- fcr = uart_config[up->port.type].fcr;
- }
-
- /*
- * MCR-based auto flow control. When AFE is enabled, RTS will be
- * deasserted when the receive FIFO contains more characters than
- * the trigger, or the MCR RTS bit is cleared. In the case where
- * the remote UART is not using CTS auto flow control, we must
- * have sufficient FIFO entries for the latency of the remote
- * UART to respond. IOW, at least 32 bytes of FIFO.
- */
- if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
- up->mcr &= ~UART_MCR_AFE;
- if (termios->c_cflag & CRTSCTS)
- up->mcr |= UART_MCR_AFE;
- }
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (!(up->bugs & UART_BUG_NOMSR) &&
- UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
- if (up->capabilities & UART_CAP_UUE)
- up->ier |= UART_IER_UUE;
- if (up->capabilities & UART_CAP_RTOIE)
- up->ier |= UART_IER_RTOIE;
-
- serial_out(up, UART_IER, up->ier);
-
- if (up->capabilities & UART_CAP_EFR) {
- unsigned char efr = 0;
- /*
- * TI16C752/Startech hardware flow control. FIXME:
- * - TI16C752 requires control thresholds to be set.
- * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
- */
- if (termios->c_cflag & CRTSCTS)
- efr |= UART_EFR_CTS;
-
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- if (up->port.flags & UPF_EXAR_EFR)
- serial_outp(up, UART_XR_EFR, efr);
- else
- serial_outp(up, UART_EFR, efr);
- }
-
-#ifdef CONFIG_ARCH_OMAP
- /* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (cpu_is_omap1510() && is_omap_port(up)) {
- if (baud == 115200) {
- quot = 1;
- serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
- } else
- serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
- }
-#endif
-
- if (up->capabilities & UART_NATSEMI) {
- /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
- serial_outp(up, UART_LCR, 0xe0);
- } else {
- serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
- }
-
- serial_dl_write(up, quot);
-
- /*
- * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
- * is written without DLAB set, this mode will be disabled.
- */
- if (up->port.type == PORT_16750)
- serial_outp(up, UART_FCR, fcr);
-
- serial_outp(up, UART_LCR, cval); /* reset DLAB */
- up->lcr = cval; /* Save LCR */
- if (up->port.type != PORT_16750) {
- if (fcr & UART_FCR_ENABLE_FIFO) {
- /* emulated UARTs (Lucent Venus 167x) need two steps */
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- }
- serial_outp(up, UART_FCR, fcr); /* set fcr */
- }
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
- /* Don't rewrite B0 */
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, baud, baud);
-}
-EXPORT_SYMBOL(serial8250_do_set_termios);
-
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- if (port->set_termios)
- port->set_termios(port, termios, old);
- else
- serial8250_do_set_termios(port, termios, old);
-}
-
-static void
-serial8250_set_ldisc(struct uart_port *port, int new)
-{
- if (new == N_PPS) {
- port->flags |= UPF_HARDPPS_CD;
- serial8250_enable_ms(port);
- } else
- port->flags &= ~UPF_HARDPPS_CD;
-}
-
-
-void serial8250_do_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_8250_port *p =
- container_of(port, struct uart_8250_port, port);
-
- serial8250_set_sleep(p, state != 0);
-}
-EXPORT_SYMBOL(serial8250_do_pm);
-
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- if (port->pm)
- port->pm(port, state, oldstate);
- else
- serial8250_do_pm(port, state, oldstate);
-}
-
-static unsigned int serial8250_port_size(struct uart_8250_port *pt)
-{
- if (pt->port.iotype == UPIO_AU)
- return 0x1000;
-#ifdef CONFIG_ARCH_OMAP
- if (is_omap_port(pt))
- return 0x16 << pt->port.regshift;
-#endif
- return 8 << pt->port.regshift;
-}
-
-/*
- * Resource handling.
- */
-static int serial8250_request_std_resource(struct uart_8250_port *up)
-{
- unsigned int size = serial8250_port_size(up);
- int ret = 0;
-
- switch (up->port.iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM:
- if (!up->port.mapbase)
- break;
-
- if (!request_mem_region(up->port.mapbase, size, "serial")) {
- ret = -EBUSY;
- break;
- }
-
- if (up->port.flags & UPF_IOREMAP) {
- up->port.membase = ioremap_nocache(up->port.mapbase,
- size);
- if (!up->port.membase) {
- release_mem_region(up->port.mapbase, size);
- ret = -ENOMEM;
- }
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- if (!request_region(up->port.iobase, size, "serial"))
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-static void serial8250_release_std_resource(struct uart_8250_port *up)
-{
- unsigned int size = serial8250_port_size(up);
-
- switch (up->port.iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM:
- if (!up->port.mapbase)
- break;
-
- if (up->port.flags & UPF_IOREMAP) {
- iounmap(up->port.membase);
- up->port.membase = NULL;
- }
-
- release_mem_region(up->port.mapbase, size);
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- release_region(up->port.iobase, size);
- break;
- }
-}
-
-static int serial8250_request_rsa_resource(struct uart_8250_port *up)
-{
- unsigned long start = UART_RSA_BASE << up->port.regshift;
- unsigned int size = 8 << up->port.regshift;
- int ret = -EINVAL;
-
- switch (up->port.iotype) {
- case UPIO_HUB6:
- case UPIO_PORT:
- start += up->port.iobase;
- if (request_region(start, size, "serial-rsa"))
- ret = 0;
- else
- ret = -EBUSY;
- break;
- }
-
- return ret;
-}
-
-static void serial8250_release_rsa_resource(struct uart_8250_port *up)
-{
- unsigned long offset = UART_RSA_BASE << up->port.regshift;
- unsigned int size = 8 << up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_HUB6:
- case UPIO_PORT:
- release_region(up->port.iobase + offset, size);
- break;
- }
-}
-
-static void serial8250_release_port(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- serial8250_release_std_resource(up);
- if (up->port.type == PORT_RSA)
- serial8250_release_rsa_resource(up);
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- int ret = 0;
-
- ret = serial8250_request_std_resource(up);
- if (ret == 0 && up->port.type == PORT_RSA) {
- ret = serial8250_request_rsa_resource(up);
- if (ret < 0)
- serial8250_release_std_resource(up);
- }
-
- return ret;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
- int probeflags = PROBE_ANY;
- int ret;
-
- /*
- * Find the region that we can probe for. This in turn
- * tells us whether we can probe for the type of port.
- */
- ret = serial8250_request_std_resource(up);
- if (ret < 0)
- return;
-
- ret = serial8250_request_rsa_resource(up);
- if (ret < 0)
- probeflags &= ~PROBE_RSA;
-
- if (up->port.iotype != up->cur_iotype)
- set_io_from_upio(port);
-
- if (flags & UART_CONFIG_TYPE)
- autoconfig(up, probeflags);
-
- /* if access method is AU, it is a 16550 with a quirk */
- if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
- up->bugs |= UART_BUG_NOMSR;
-
- if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
- autoconfig_irq(up);
-
- if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
- serial8250_release_rsa_resource(up);
- if (up->port.type == PORT_UNKNOWN)
- serial8250_release_std_resource(up);
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
- ser->type == PORT_STARTECH)
- return -EINVAL;
- return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops serial8250_pops = {
- .tx_empty = serial8250_tx_empty,
- .set_mctrl = serial8250_set_mctrl,
- .get_mctrl = serial8250_get_mctrl,
- .stop_tx = serial8250_stop_tx,
- .start_tx = serial8250_start_tx,
- .stop_rx = serial8250_stop_rx,
- .enable_ms = serial8250_enable_ms,
- .break_ctl = serial8250_break_ctl,
- .startup = serial8250_startup,
- .shutdown = serial8250_shutdown,
- .set_termios = serial8250_set_termios,
- .set_ldisc = serial8250_set_ldisc,
- .pm = serial8250_pm,
- .type = serial8250_type,
- .release_port = serial8250_release_port,
- .request_port = serial8250_request_port,
- .config_port = serial8250_config_port,
- .verify_port = serial8250_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = serial8250_get_poll_char,
- .poll_put_char = serial8250_put_poll_char,
-#endif
-};
-
-static struct uart_8250_port serial8250_ports[UART_NR];
-
-static void (*serial8250_isa_config)(int port, struct uart_port *up,
- unsigned short *capabilities);
-
-void serial8250_set_isa_configurator(
- void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
-{
- serial8250_isa_config = v;
-}
-EXPORT_SYMBOL(serial8250_set_isa_configurator);
-
-static void __init serial8250_isa_init_ports(void)
-{
- struct uart_8250_port *up;
- static int first = 1;
- int i, irqflag = 0;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- up->port.line = i;
- spin_lock_init(&up->port.lock);
-
- init_timer(&up->timer);
- up->timer.function = serial8250_timeout;
-
- /*
- * ALPHA_KLUDGE_MCR needs to be killed.
- */
- up->mcr_mask = ~ALPHA_KLUDGE_MCR;
- up->mcr_force = ALPHA_KLUDGE_MCR;
-
- up->port.ops = &serial8250_pops;
- }
-
- if (share_irqs)
- irqflag = IRQF_SHARED;
-
- for (i = 0, up = serial8250_ports;
- i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
- i++, up++) {
- up->port.iobase = old_serial_port[i].port;
- up->port.irq = irq_canonicalize(old_serial_port[i].irq);
- up->port.irqflags = old_serial_port[i].irqflags;
- up->port.uartclk = old_serial_port[i].baud_base * 16;
- up->port.flags = old_serial_port[i].flags;
- up->port.hub6 = old_serial_port[i].hub6;
- up->port.membase = old_serial_port[i].iomem_base;
- up->port.iotype = old_serial_port[i].io_type;
- up->port.regshift = old_serial_port[i].iomem_reg_shift;
- set_io_from_upio(&up->port);
- up->port.irqflags |= irqflag;
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(i, &up->port, &up->capabilities);
-
- }
-}
-
-static void
-serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
-{
- up->port.type = type;
- up->port.fifosize = uart_config[type].fifo_size;
- up->capabilities = uart_config[type].flags;
- up->tx_loadsz = uart_config[type].tx_loadsz;
-}
-
-static void __init
-serial8250_register_ports(struct uart_driver *drv, struct device *dev)
-{
- int i;
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
- up->cur_iotype = 0xFF;
- }
-
- serial8250_isa_init_ports();
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- up->port.dev = dev;
-
- if (up->port.flags & UPF_FIXED_TYPE)
- serial8250_init_fixed_type_port(up, up->port.type);
-
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-
-static void serial8250_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- wait_for_xmitr(up, UART_LSR_THRE);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_8250_port *up = &serial8250_ports[co->index];
- unsigned long flags;
- unsigned int ier;
- int locked = 1;
-
- touch_nmi_watchdog();
-
- local_irq_save(flags);
- if (up->port.sysrq) {
- /* serial8250_handle_irq() already took the lock */
- locked = 0;
- } else if (oops_in_progress) {
- locked = spin_trylock(&up->port.lock);
- } else
- spin_lock(&up->port.lock);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
-
- if (up->capabilities & UART_CAP_UUE)
- serial_out(up, UART_IER, UART_IER_UUE);
- else
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, serial8250_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_out(up, UART_IER, ier);
-
- /*
- * The receive handling will happen properly because the
- * receive ready bit will still be set; it is not cleared
- * on read. However, modem control will not, we must
- * call it if we have saved something in the saved flags
- * while processing with interrupts off.
- */
- if (up->msr_saved_flags)
- serial8250_modem_status(up);
-
- if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
-}
-
-static int __init serial8250_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= nr_uarts)
- co->index = 0;
- port = &serial8250_ports[co->index].port;
- if (!port->iobase && !port->membase)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static int serial8250_console_early_setup(void)
-{
- return serial8250_find_port_for_earlycon();
-}
-
-static struct console serial8250_console = {
- .name = "ttyS",
- .write = serial8250_console_write,
- .device = uart_console_device,
- .setup = serial8250_console_setup,
- .early_setup = serial8250_console_early_setup,
- .flags = CON_PRINTBUFFER | CON_ANYTIME,
- .index = -1,
- .data = &serial8250_reg,
-};
-
-static int __init serial8250_console_init(void)
-{
- if (nr_uarts > UART_NR)
- nr_uarts = UART_NR;
-
- serial8250_isa_init_ports();
- register_console(&serial8250_console);
- return 0;
-}
-console_initcall(serial8250_console_init);
-
-int serial8250_find_port(struct uart_port *p)
-{
- int line;
- struct uart_port *port;
-
- for (line = 0; line < nr_uarts; line++) {
- port = &serial8250_ports[line].port;
- if (uart_match_port(p, port))
- return line;
- }
- return -ENODEV;
-}
-
-#define SERIAL8250_CONSOLE &serial8250_console
-#else
-#define SERIAL8250_CONSOLE NULL
-#endif
-
-static struct uart_driver serial8250_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .cons = SERIAL8250_CONSOLE,
-};
-
-/*
- * early_serial_setup - early registration for 8250 ports
- *
- * Setup an 8250 port structure prior to console initialisation. Use
- * after console initialisation will cause undefined behaviour.
- */
-int __init early_serial_setup(struct uart_port *port)
-{
- struct uart_port *p;
-
- if (port->line >= ARRAY_SIZE(serial8250_ports))
- return -ENODEV;
-
- serial8250_isa_init_ports();
- p = &serial8250_ports[port->line].port;
- p->iobase = port->iobase;
- p->membase = port->membase;
- p->irq = port->irq;
- p->irqflags = port->irqflags;
- p->uartclk = port->uartclk;
- p->fifosize = port->fifosize;
- p->regshift = port->regshift;
- p->iotype = port->iotype;
- p->flags = port->flags;
- p->mapbase = port->mapbase;
- p->private_data = port->private_data;
- p->type = port->type;
- p->line = port->line;
-
- set_io_from_upio(p);
- if (port->serial_in)
- p->serial_in = port->serial_in;
- if (port->serial_out)
- p->serial_out = port->serial_out;
- if (port->handle_irq)
- p->handle_irq = port->handle_irq;
- else
- p->handle_irq = serial8250_default_handle_irq;
-
- return 0;
-}
-
-/**
- * serial8250_suspend_port - suspend one serial port
- * @line: serial line number
- *
- * Suspend one serial port.
- */
-void serial8250_suspend_port(int line)
-{
- uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-/**
- * serial8250_resume_port - resume one serial port
- * @line: serial line number
- *
- * Resume one serial port.
- */
-void serial8250_resume_port(int line)
-{
- struct uart_8250_port *up = &serial8250_ports[line];
-
- if (up->capabilities & UART_NATSEMI) {
- /* Ensure it's still in high speed mode */
- serial_outp(up, UART_LCR, 0xE0);
-
- ns16550a_goto_highspeed(up);
-
- serial_outp(up, UART_LCR, 0);
- up->port.uartclk = 921600*16;
- }
- uart_resume_port(&serial8250_reg, &up->port);
-}
-
-/*
- * Register a set of serial devices attached to a platform device. The
- * list is terminated with a zero flags entry, which means we expect
- * all entries to have at least UPF_BOOT_AUTOCONF set.
- */
-static int __devinit serial8250_probe(struct platform_device *dev)
-{
- struct plat_serial8250_port *p = dev->dev.platform_data;
- struct uart_port port;
- int ret, i, irqflag = 0;
-
- memset(&port, 0, sizeof(struct uart_port));
-
- if (share_irqs)
- irqflag = IRQF_SHARED;
-
- for (i = 0; p && p->flags != 0; p++, i++) {
- port.iobase = p->iobase;
- port.membase = p->membase;
- port.irq = p->irq;
- port.irqflags = p->irqflags;
- port.uartclk = p->uartclk;
- port.regshift = p->regshift;
- port.iotype = p->iotype;
- port.flags = p->flags;
- port.mapbase = p->mapbase;
- port.hub6 = p->hub6;
- port.private_data = p->private_data;
- port.type = p->type;
- port.serial_in = p->serial_in;
- port.serial_out = p->serial_out;
- port.handle_irq = p->handle_irq;
- port.set_termios = p->set_termios;
- port.pm = p->pm;
- port.dev = &dev->dev;
- port.irqflags |= irqflag;
- ret = serial8250_register_port(&port);
- if (ret < 0) {
- dev_err(&dev->dev, "unable to register port at index %d "
- "(IO%lx MEM%llx IRQ%d): %d\n", i,
- p->iobase, (unsigned long long)p->mapbase,
- p->irq, ret);
- }
- }
- return 0;
-}
-
-/*
- * Remove serial ports registered against a platform device.
- */
-static int __devexit serial8250_remove(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- if (up->port.dev == &dev->dev)
- serial8250_unregister_port(i);
- }
- return 0;
-}
-
-static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- uart_suspend_port(&serial8250_reg, &up->port);
- }
-
- return 0;
-}
-
-static int serial8250_resume(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- serial8250_resume_port(i);
- }
-
- return 0;
-}
-
-static struct platform_driver serial8250_isa_driver = {
- .probe = serial8250_probe,
- .remove = __devexit_p(serial8250_remove),
- .suspend = serial8250_suspend,
- .resume = serial8250_resume,
- .driver = {
- .name = "serial8250",
- .owner = THIS_MODULE,
- },
-};
-
-/*
- * This "device" covers _all_ ISA 8250-compatible serial devices listed
- * in the table in include/asm/serial.h
- */
-static struct platform_device *serial8250_isa_devs;
-
-/*
- * serial8250_register_port and serial8250_unregister_port allows for
- * 16x50 serial ports to be configured at run-time, to support PCMCIA
- * modems and PCI multiport cards.
- */
-static DEFINE_MUTEX(serial_mutex);
-
-static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
-{
- int i;
-
- /*
- * First, find a port entry which matches.
- */
- for (i = 0; i < nr_uarts; i++)
- if (uart_match_port(&serial8250_ports[i].port, port))
- return &serial8250_ports[i];
-
- /*
- * We didn't find a matching entry, so look for the first
- * free entry. We look for one which hasn't been previously
- * used (indicated by zero iobase).
- */
- for (i = 0; i < nr_uarts; i++)
- if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
- serial8250_ports[i].port.iobase == 0)
- return &serial8250_ports[i];
-
- /*
- * That also failed. Last resort is to find any entry which
- * doesn't have a real port associated with it.
- */
- for (i = 0; i < nr_uarts; i++)
- if (serial8250_ports[i].port.type == PORT_UNKNOWN)
- return &serial8250_ports[i];
-
- return NULL;
-}
-
-/**
- * serial8250_register_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use, it is hung up and unregistered
- * first.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
- struct uart_8250_port *uart;
- int ret = -ENOSPC;
-
- if (port->uartclk == 0)
- return -EINVAL;
-
- mutex_lock(&serial_mutex);
-
- uart = serial8250_find_match_or_unused(port);
- if (uart) {
- uart_remove_one_port(&serial8250_reg, &uart->port);
-
- uart->port.iobase = port->iobase;
- uart->port.membase = port->membase;
- uart->port.irq = port->irq;
- uart->port.irqflags = port->irqflags;
- uart->port.uartclk = port->uartclk;
- uart->port.fifosize = port->fifosize;
- uart->port.regshift = port->regshift;
- uart->port.iotype = port->iotype;
- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
- uart->port.mapbase = port->mapbase;
- uart->port.private_data = port->private_data;
- if (port->dev)
- uart->port.dev = port->dev;
-
- if (port->flags & UPF_FIXED_TYPE)
- serial8250_init_fixed_type_port(uart, port->type);
-
- set_io_from_upio(&uart->port);
- /* Possibly override default I/O functions. */
- if (port->serial_in)
- uart->port.serial_in = port->serial_in;
- if (port->serial_out)
- uart->port.serial_out = port->serial_out;
- if (port->handle_irq)
- uart->port.handle_irq = port->handle_irq;
- /* Possibly override set_termios call */
- if (port->set_termios)
- uart->port.set_termios = port->set_termios;
- if (port->pm)
- uart->port.pm = port->pm;
-
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(0, &uart->port,
- &uart->capabilities);
-
- ret = uart_add_one_port(&serial8250_reg, &uart->port);
- if (ret == 0)
- ret = uart->port.line;
- }
- mutex_unlock(&serial_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
-/**
- * serial8250_unregister_port - remove a 16x50 serial port at runtime
- * @line: serial line number
- *
- * Remove one serial port. This may not be called from interrupt
- * context. We hand the port back to the our control.
- */
-void serial8250_unregister_port(int line)
-{
- struct uart_8250_port *uart = &serial8250_ports[line];
-
- mutex_lock(&serial_mutex);
- uart_remove_one_port(&serial8250_reg, &uart->port);
- if (serial8250_isa_devs) {
- uart->port.flags &= ~UPF_BOOT_AUTOCONF;
- uart->port.type = PORT_UNKNOWN;
- uart->port.dev = &serial8250_isa_devs->dev;
- uart->capabilities = uart_config[uart->port.type].flags;
- uart_add_one_port(&serial8250_reg, &uart->port);
- } else {
- uart->port.dev = NULL;
- }
- mutex_unlock(&serial_mutex);
-}
-EXPORT_SYMBOL(serial8250_unregister_port);
-
-static int __init serial8250_init(void)
-{
- int ret;
-
- if (nr_uarts > UART_NR)
- nr_uarts = UART_NR;
-
- printk(KERN_INFO "Serial: 8250/16550 driver, "
- "%d ports, IRQ sharing %sabled\n", nr_uarts,
- share_irqs ? "en" : "dis");
-
-#ifdef CONFIG_SPARC
- ret = sunserial_register_minors(&serial8250_reg, UART_NR);
-#else
- serial8250_reg.nr = UART_NR;
- ret = uart_register_driver(&serial8250_reg);
-#endif
- if (ret)
- goto out;
-
- serial8250_isa_devs = platform_device_alloc("serial8250",
- PLAT8250_DEV_LEGACY);
- if (!serial8250_isa_devs) {
- ret = -ENOMEM;
- goto unreg_uart_drv;
- }
-
- ret = platform_device_add(serial8250_isa_devs);
- if (ret)
- goto put_dev;
-
- serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
-
- ret = platform_driver_register(&serial8250_isa_driver);
- if (ret == 0)
- goto out;
-
- platform_device_del(serial8250_isa_devs);
-put_dev:
- platform_device_put(serial8250_isa_devs);
-unreg_uart_drv:
-#ifdef CONFIG_SPARC
- sunserial_unregister_minors(&serial8250_reg, UART_NR);
-#else
- uart_unregister_driver(&serial8250_reg);
-#endif
-out:
- return ret;
-}
-
-static void __exit serial8250_exit(void)
-{
- struct platform_device *isa_dev = serial8250_isa_devs;
-
- /*
- * This tells serial8250_unregister_port() not to re-register
- * the ports (thereby making serial8250_isa_driver permanently
- * in use.)
- */
- serial8250_isa_devs = NULL;
-
- platform_driver_unregister(&serial8250_isa_driver);
- platform_device_unregister(isa_dev);
-
-#ifdef CONFIG_SPARC
- sunserial_unregister_minors(&serial8250_reg, UART_NR);
-#else
- uart_unregister_driver(&serial8250_reg);
-#endif
-}
-
-module_init(serial8250_init);
-module_exit(serial8250_exit);
-
-EXPORT_SYMBOL(serial8250_suspend_port);
-EXPORT_SYMBOL(serial8250_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
-
-module_param(share_irqs, uint, 0644);
-MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
- " (unsafe)");
-
-module_param(nr_uarts, uint, 0644);
-MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
-
-module_param(skip_txen_test, uint, 0644);
-MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
-
-#ifdef CONFIG_SERIAL_8250_RSA
-module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
-MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
-#endif
-MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
+++ /dev/null
-/*
- * Driver for 8250/16550-type serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King.
- *
- * 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.
- */
-
-#include <linux/serial_8250.h>
-
-struct uart_8250_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short capabilities; /* port capabilities */
- unsigned short bugs; /* port bugs */
- unsigned int tx_loadsz; /* transmit fifo load size */
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char cur_iotype; /* Running I/O type */
-
- /*
- * Some bits in registers are cleared on a read, so they must
- * be saved whenever the register is read but the bits will not
- * be immediately processed.
- */
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
- unsigned char lsr_saved_flags;
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
- unsigned char msr_saved_flags;
-};
-
-struct old_serial_port {
- unsigned int uart;
- unsigned int baud_base;
- unsigned int port;
- unsigned int irq;
- unsigned int flags;
- unsigned char hub6;
- unsigned char io_type;
- unsigned char *iomem_base;
- unsigned short iomem_reg_shift;
- unsigned long irqflags;
-};
-
-/*
- * This replaces serial_uart_config in include/linux/serial.h
- */
-struct serial8250_config {
- const char *name;
- unsigned short fifo_size;
- unsigned short tx_loadsz;
- unsigned char fcr;
- unsigned int flags;
-};
-
-#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */
-#define UART_CAP_EFR (1 << 9) /* UART has EFR */
-#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
-#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
-#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
-#define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */
-
-#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
-#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
-#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
-#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
-
-#define PROBE_RSA (1 << 0)
-#define PROBE_ANY (~0)
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
-#define SERIAL8250_SHARE_IRQS 1
-#else
-#define SERIAL8250_SHARE_IRQS 0
-#endif
-
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-/*
- * Digital did something really horribly wrong with the OUT1 and OUT2
- * lines on at least some ALPHA's. The failure mode is that if either
- * is cleared, the machine locks up with endless interrupts.
- */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
-#elif defined(CONFIG_SBC8560)
-/*
- * WindRiver did something similarly broken on their SBC8560 board. The
- * UART tristates its IRQ output while OUT2 is clear, but they pulled
- * the interrupt line _up_ instead of down, so if we register the IRQ
- * while the UART is in that state, we die in an IRQ storm. */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
-#else
-#define ALPHA_KLUDGE_MCR 0
-#endif
--- /dev/null
+/*
+ * Driver for 8250/16550-type serial ports
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * Copyright (C) 2001 Russell King.
+ *
+ * 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.
+ *
+ * A note about mapbase / membase
+ *
+ * mapbase is the physical address of the IO port.
+ * membase is an 'ioremapped' cookie.
+ */
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/ratelimit.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/nmi.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "8250.h"
+
+#ifdef CONFIG_SPARC
+#include "suncore.h"
+#endif
+
+/*
+ * Configuration:
+ * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
+ * is unsafe when used on edge-triggered interrupts.
+ */
+static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
+
+static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
+
+static struct uart_driver serial8250_reg;
+
+static int serial_index(struct uart_port *port)
+{
+ return (serial8250_reg.minor - 64) + port->line;
+}
+
+static unsigned int skip_txen_test; /* force skip of txen test at init time */
+
+/*
+ * Debugging.
+ */
+#if 0
+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
+#endif
+
+#if 0
+#define DEBUG_INTR(fmt...) printk(fmt)
+#else
+#define DEBUG_INTR(fmt...) do { } while (0)
+#endif
+
+#define PASS_LIMIT 512
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+
+/*
+ * We default to IRQ0 for the "no irq" hack. Some
+ * machine types want others as well - they're free
+ * to redefine this in their header file.
+ */
+#define is_real_interrupt(irq) ((irq) != 0)
+
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
+#define CONFIG_SERIAL_DETECT_IRQ 1
+#endif
+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
+#define CONFIG_SERIAL_MANY_PORTS 1
+#endif
+
+/*
+ * HUB6 is always on. This will be removed once the header
+ * files have been cleaned.
+ */
+#define CONFIG_HUB6 1
+
+#include <asm/serial.h>
+/*
+ * SERIAL_PORT_DFNS tells us about built-in ports that have no
+ * standard enumeration mechanism. Platforms that can find all
+ * serial ports via mechanisms like ACPI or PCI need not supply it.
+ */
+#ifndef SERIAL_PORT_DFNS
+#define SERIAL_PORT_DFNS
+#endif
+
+static const struct old_serial_port old_serial_port[] = {
+ SERIAL_PORT_DFNS /* defined in asm/serial.h */
+};
+
+#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
+
+#ifdef CONFIG_SERIAL_8250_RSA
+
+#define PORT_RSA_MAX 4
+static unsigned long probe_rsa[PORT_RSA_MAX];
+static unsigned int probe_rsa_count;
+#endif /* CONFIG_SERIAL_8250_RSA */
+
+struct irq_info {
+ struct hlist_node node;
+ int irq;
+ spinlock_t lock; /* Protects list not the hash */
+ struct list_head *head;
+};
+
+#define NR_IRQ_HASH 32 /* Can be adjusted later */
+static struct hlist_head irq_lists[NR_IRQ_HASH];
+static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
+
+/*
+ * Here we define the default xmit fifo size used for each type of UART.
+ */
+static const struct serial8250_config uart_config[] = {
+ [PORT_UNKNOWN] = {
+ .name = "unknown",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_8250] = {
+ .name = "8250",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16450] = {
+ .name = "16450",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16550] = {
+ .name = "16550",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16550A] = {
+ .name = "16550A",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_CIRRUS] = {
+ .name = "Cirrus",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16650] = {
+ .name = "ST16650",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_16650V2] = {
+ .name = "ST16650V2",
+ .fifo_size = 32,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_16750] = {
+ .name = "TI16750",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+ UART_FCR7_64BYTE,
+ .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
+ },
+ [PORT_STARTECH] = {
+ .name = "Startech",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16C950] = {
+ .name = "16C950/954",
+ .fifo_size = 128,
+ .tx_loadsz = 128,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ /* UART_CAP_EFR breaks billionon CF bluetooth card. */
+ .flags = UART_CAP_FIFO | UART_CAP_SLEEP,
+ },
+ [PORT_16654] = {
+ .name = "ST16654",
+ .fifo_size = 64,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_16850] = {
+ .name = "XR16850",
+ .fifo_size = 128,
+ .tx_loadsz = 128,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_RSA] = {
+ .name = "RSA",
+ .fifo_size = 2048,
+ .tx_loadsz = 2048,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_NS16550A] = {
+ .name = "NS16550A",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_NATSEMI,
+ },
+ [PORT_XSCALE] = {
+ .name = "XScale",
+ .fifo_size = 32,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
+ },
+ [PORT_RM9000] = {
+ .name = "RM9000",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_OCTEON] = {
+ .name = "OCTEON",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_AR7] = {
+ .name = "AR7",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+ [PORT_U6_16550A] = {
+ .name = "U6_16550A",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+ [PORT_TEGRA] = {
+ .name = "Tegra",
+ .fifo_size = 32,
+ .tx_loadsz = 8,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_01,
+ .flags = UART_CAP_FIFO | UART_CAP_RTOIE,
+ },
+ [PORT_XR17D15X] = {
+ .name = "XR17D15X",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
+ },
+};
+
+#if defined(CONFIG_MIPS_ALCHEMY)
+
+/* Au1x00 UART hardware has a weird register layout */
+static const u8 au_io_in_map[] = {
+ [UART_RX] = 0,
+ [UART_IER] = 2,
+ [UART_IIR] = 3,
+ [UART_LCR] = 5,
+ [UART_MCR] = 6,
+ [UART_LSR] = 7,
+ [UART_MSR] = 8,
+};
+
+static const u8 au_io_out_map[] = {
+ [UART_TX] = 1,
+ [UART_IER] = 2,
+ [UART_FCR] = 4,
+ [UART_LCR] = 5,
+ [UART_MCR] = 6,
+};
+
+/* sane hardware needs no mapping */
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
+{
+ if (p->iotype != UPIO_AU)
+ return offset;
+ return au_io_in_map[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
+{
+ if (p->iotype != UPIO_AU)
+ return offset;
+ return au_io_out_map[offset];
+}
+
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+
+static const u8
+ regmap_in[8] = {
+ [UART_RX] = 0x00,
+ [UART_IER] = 0x0c,
+ [UART_IIR] = 0x14,
+ [UART_LCR] = 0x1c,
+ [UART_MCR] = 0x20,
+ [UART_LSR] = 0x24,
+ [UART_MSR] = 0x28,
+ [UART_SCR] = 0x2c
+ },
+ regmap_out[8] = {
+ [UART_TX] = 0x04,
+ [UART_IER] = 0x0c,
+ [UART_FCR] = 0x18,
+ [UART_LCR] = 0x1c,
+ [UART_MCR] = 0x20,
+ [UART_LSR] = 0x24,
+ [UART_MSR] = 0x28,
+ [UART_SCR] = 0x2c
+ };
+
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
+{
+ if (p->iotype != UPIO_RM9000)
+ return offset;
+ return regmap_in[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
+{
+ if (p->iotype != UPIO_RM9000)
+ return offset;
+ return regmap_out[offset];
+}
+
+#else
+
+/* sane hardware needs no mapping */
+#define map_8250_in_reg(up, offset) (offset)
+#define map_8250_out_reg(up, offset) (offset)
+
+#endif
+
+static unsigned int hub6_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ return inb(p->iobase + 1);
+}
+
+static void hub6_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ outb(value, p->iobase + 1);
+}
+
+static unsigned int mem_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return readb(p->membase + offset);
+}
+
+static void mem_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return readl(p->membase + offset);
+}
+
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return __raw_readl(p->membase + offset);
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ __raw_writel(value, p->membase + offset);
+}
+
+static unsigned int io_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return inb(p->iobase + offset);
+}
+
+static void io_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ outb(value, p->iobase + offset);
+}
+
+static int serial8250_default_handle_irq(struct uart_port *port);
+
+static void set_io_from_upio(struct uart_port *p)
+{
+ struct uart_8250_port *up =
+ container_of(p, struct uart_8250_port, port);
+ switch (p->iotype) {
+ case UPIO_HUB6:
+ p->serial_in = hub6_serial_in;
+ p->serial_out = hub6_serial_out;
+ break;
+
+ case UPIO_MEM:
+ p->serial_in = mem_serial_in;
+ p->serial_out = mem_serial_out;
+ break;
+
+ case UPIO_RM9000:
+ case UPIO_MEM32:
+ p->serial_in = mem32_serial_in;
+ p->serial_out = mem32_serial_out;
+ break;
+
+ case UPIO_AU:
+ p->serial_in = au_serial_in;
+ p->serial_out = au_serial_out;
+ break;
+
+ default:
+ p->serial_in = io_serial_in;
+ p->serial_out = io_serial_out;
+ break;
+ }
+ /* Remember loaded iotype */
+ up->cur_iotype = p->iotype;
+ p->handle_irq = serial8250_default_handle_irq;
+}
+
+static void
+serial_out_sync(struct uart_8250_port *up, int offset, int value)
+{
+ struct uart_port *p = &up->port;
+ switch (p->iotype) {
+ case UPIO_MEM:
+ case UPIO_MEM32:
+ case UPIO_AU:
+ p->serial_out(p, offset, value);
+ p->serial_in(p, UART_LCR); /* safe, no side-effects */
+ break;
+ default:
+ p->serial_out(p, offset, value);
+ }
+}
+
+#define serial_in(up, offset) \
+ (up->port.serial_in(&(up)->port, (offset)))
+#define serial_out(up, offset, value) \
+ (up->port.serial_out(&(up)->port, (offset), (value)))
+/*
+ * We used to support using pause I/O for certain machines. We
+ * haven't supported this for a while, but just in case it's badly
+ * needed for certain old 386 machines, I've left these #define's
+ * in....
+ */
+#define serial_inp(up, offset) serial_in(up, offset)
+#define serial_outp(up, offset, value) serial_out(up, offset, value)
+
+/* Uart divisor latch read */
+static inline int _serial_dl_read(struct uart_8250_port *up)
+{
+ return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+{
+ serial_outp(up, UART_DLL, value & 0xff);
+ serial_outp(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#if defined(CONFIG_MIPS_ALCHEMY)
+/* Au1x00 haven't got a standard divisor latch */
+static int serial_dl_read(struct uart_8250_port *up)
+{
+ if (up->port.iotype == UPIO_AU)
+ return __raw_readl(up->port.membase + 0x28);
+ else
+ return _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+ if (up->port.iotype == UPIO_AU)
+ __raw_writel(value, up->port.membase + 0x28);
+ else
+ _serial_dl_write(up, value);
+}
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+static int serial_dl_read(struct uart_8250_port *up)
+{
+ return (up->port.iotype == UPIO_RM9000) ?
+ (((__raw_readl(up->port.membase + 0x10) << 8) |
+ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+ _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+ if (up->port.iotype == UPIO_RM9000) {
+ __raw_writel(value, up->port.membase + 0x08);
+ __raw_writel(value >> 8, up->port.membase + 0x10);
+ } else {
+ _serial_dl_write(up, value);
+ }
+}
+#else
+#define serial_dl_read(up) _serial_dl_read(up)
+#define serial_dl_write(up, value) _serial_dl_write(up, value)
+#endif
+
+/*
+ * For the 16C950
+ */
+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
+{
+ serial_out(up, UART_SCR, offset);
+ serial_out(up, UART_ICR, value);
+}
+
+static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+{
+ unsigned int value;
+
+ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
+ serial_out(up, UART_SCR, offset);
+ value = serial_in(up, UART_ICR);
+ serial_icr_write(up, UART_ACR, up->acr);
+
+ return value;
+}
+
+/*
+ * FIFO support.
+ */
+static void serial8250_clear_fifos(struct uart_8250_port *p)
+{
+ if (p->capabilities & UART_CAP_FIFO) {
+ serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ serial_outp(p, UART_FCR, 0);
+ }
+}
+
+/*
+ * IER sleep support. UARTs which have EFRs need the "extended
+ * capability" bit enabled. Note that on XR16C850s, we need to
+ * reset LCR to write to IER.
+ */
+static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+{
+ if (p->capabilities & UART_CAP_SLEEP) {
+ if (p->capabilities & UART_CAP_EFR) {
+ serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_outp(p, UART_EFR, UART_EFR_ECB);
+ serial_outp(p, UART_LCR, 0);
+ }
+ serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+ if (p->capabilities & UART_CAP_EFR) {
+ serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_outp(p, UART_EFR, 0);
+ serial_outp(p, UART_LCR, 0);
+ }
+ }
+}
+
+#ifdef CONFIG_SERIAL_8250_RSA
+/*
+ * Attempts to turn on the RSA FIFO. Returns zero on failure.
+ * We set the port uart clock rate if we succeed.
+ */
+static int __enable_rsa(struct uart_8250_port *up)
+{
+ unsigned char mode;
+ int result;
+
+ mode = serial_inp(up, UART_RSA_MSR);
+ result = mode & UART_RSA_MSR_FIFO;
+
+ if (!result) {
+ serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
+ mode = serial_inp(up, UART_RSA_MSR);
+ result = mode & UART_RSA_MSR_FIFO;
+ }
+
+ if (result)
+ up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
+
+ return result;
+}
+
+static void enable_rsa(struct uart_8250_port *up)
+{
+ if (up->port.type == PORT_RSA) {
+ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
+ spin_lock_irq(&up->port.lock);
+ __enable_rsa(up);
+ spin_unlock_irq(&up->port.lock);
+ }
+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+ serial_outp(up, UART_RSA_FRR, 0);
+ }
+}
+
+/*
+ * Attempts to turn off the RSA FIFO. Returns zero on failure.
+ * It is unknown why interrupts were disabled in here. However,
+ * the caller is expected to preserve this behaviour by grabbing
+ * the spinlock before calling this function.
+ */
+static void disable_rsa(struct uart_8250_port *up)
+{
+ unsigned char mode;
+ int result;
+
+ if (up->port.type == PORT_RSA &&
+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+ spin_lock_irq(&up->port.lock);
+
+ mode = serial_inp(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+
+ if (!result) {
+ serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
+ mode = serial_inp(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+ }
+
+ if (result)
+ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
+ spin_unlock_irq(&up->port.lock);
+ }
+}
+#endif /* CONFIG_SERIAL_8250_RSA */
+
+/*
+ * This is a quickie test to see how big the FIFO is.
+ * It doesn't work at all the time, more's the pity.
+ */
+static int size_fifo(struct uart_8250_port *up)
+{
+ unsigned char old_fcr, old_mcr, old_lcr;
+ unsigned short old_dl;
+ int count;
+
+ old_lcr = serial_inp(up, UART_LCR);
+ serial_outp(up, UART_LCR, 0);
+ old_fcr = serial_inp(up, UART_FCR);
+ old_mcr = serial_inp(up, UART_MCR);
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ serial_outp(up, UART_MCR, UART_MCR_LOOP);
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ old_dl = serial_dl_read(up);
+ serial_dl_write(up, 0x0001);
+ serial_outp(up, UART_LCR, 0x03);
+ for (count = 0; count < 256; count++)
+ serial_outp(up, UART_TX, count);
+ mdelay(20);/* FIXME - schedule_timeout */
+ for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
+ (count < 256); count++)
+ serial_inp(up, UART_RX);
+ serial_outp(up, UART_FCR, old_fcr);
+ serial_outp(up, UART_MCR, old_mcr);
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_dl_write(up, old_dl);
+ serial_outp(up, UART_LCR, old_lcr);
+
+ return count;
+}
+
+/*
+ * Read UART ID using the divisor method - set DLL and DLM to zero
+ * and the revision will be in DLL and device type in DLM. We
+ * preserve the device state across this.
+ */
+static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+{
+ unsigned char old_dll, old_dlm, old_lcr;
+ unsigned int id;
+
+ old_lcr = serial_inp(p, UART_LCR);
+ serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
+
+ old_dll = serial_inp(p, UART_DLL);
+ old_dlm = serial_inp(p, UART_DLM);
+
+ serial_outp(p, UART_DLL, 0);
+ serial_outp(p, UART_DLM, 0);
+
+ id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
+
+ serial_outp(p, UART_DLL, old_dll);
+ serial_outp(p, UART_DLM, old_dlm);
+ serial_outp(p, UART_LCR, old_lcr);
+
+ return id;
+}
+
+/*
+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+ * When this function is called we know it is at least a StarTech
+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
+ * its clones. (We treat the broken original StarTech 16650 V1 as a
+ * 16550, and why not? Startech doesn't seem to even acknowledge its
+ * existence.)
+ *
+ * What evil have men's minds wrought...
+ */
+static void autoconfig_has_efr(struct uart_8250_port *up)
+{
+ unsigned int id1, id2, id3, rev;
+
+ /*
+ * Everything with an EFR has SLEEP
+ */
+ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+
+ /*
+ * First we check to see if it's an Oxford Semiconductor UART.
+ *
+ * If we have to do this here because some non-National
+ * Semiconductor clone chips lock up if you try writing to the
+ * LSR register (which serial_icr_read does)
+ */
+
+ /*
+ * Check for Oxford Semiconductor 16C950.
+ *
+ * EFR [4] must be set else this test fails.
+ *
+ * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
+ * claims that it's needed for 952 dual UART's (which are not
+ * recommended for new designs).
+ */
+ up->acr = 0;
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x00);
+ id1 = serial_icr_read(up, UART_ID1);
+ id2 = serial_icr_read(up, UART_ID2);
+ id3 = serial_icr_read(up, UART_ID3);
+ rev = serial_icr_read(up, UART_REV);
+
+ DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
+
+ if (id1 == 0x16 && id2 == 0xC9 &&
+ (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
+ up->port.type = PORT_16C950;
+
+ /*
+ * Enable work around for the Oxford Semiconductor 952 rev B
+ * chip which causes it to seriously miscalculate baud rates
+ * when DLL is 0.
+ */
+ if (id3 == 0x52 && rev == 0x01)
+ up->bugs |= UART_BUG_QUOT;
+ return;
+ }
+
+ /*
+ * We check for a XR16C850 by setting DLL and DLM to 0, and then
+ * reading back DLL and DLM. The chip type depends on the DLM
+ * value read back:
+ * 0x10 - XR16C850 and the DLL contains the chip revision.
+ * 0x12 - XR16C2850.
+ * 0x14 - XR16C854.
+ */
+ id1 = autoconfig_read_divisor_id(up);
+ DEBUG_AUTOCONF("850id=%04x ", id1);
+
+ id2 = id1 >> 8;
+ if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
+ up->port.type = PORT_16850;
+ return;
+ }
+
+ /*
+ * It wasn't an XR16C850.
+ *
+ * We distinguish between the '654 and the '650 by counting
+ * how many bytes are in the FIFO. I'm using this for now,
+ * since that's the technique that was sent to me in the
+ * serial driver update, but I'm not convinced this works.
+ * I've had problems doing this in the past. -TYT
+ */
+ if (size_fifo(up) == 64)
+ up->port.type = PORT_16654;
+ else
+ up->port.type = PORT_16650V2;
+}
+
+/*
+ * We detected a chip without a FIFO. Only two fall into
+ * this category - the original 8250 and the 16450. The
+ * 16450 has a scratch register (accessible with LCR=0)
+ */
+static void autoconfig_8250(struct uart_8250_port *up)
+{
+ unsigned char scratch, status1, status2;
+
+ up->port.type = PORT_8250;
+
+ scratch = serial_in(up, UART_SCR);
+ serial_outp(up, UART_SCR, 0xa5);
+ status1 = serial_in(up, UART_SCR);
+ serial_outp(up, UART_SCR, 0x5a);
+ status2 = serial_in(up, UART_SCR);
+ serial_outp(up, UART_SCR, scratch);
+
+ if (status1 == 0xa5 && status2 == 0x5a)
+ up->port.type = PORT_16450;
+}
+
+static int broken_efr(struct uart_8250_port *up)
+{
+ /*
+ * Exar ST16C2550 "A2" devices incorrectly detect as
+ * having an EFR, and report an ID of 0x0201. See
+ * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
+ */
+ if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
+ return 1;
+
+ return 0;
+}
+
+static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+{
+ unsigned char status;
+
+ status = serial_in(up, 0x04); /* EXCR2 */
+#define PRESL(x) ((x) & 0x30)
+ if (PRESL(status) == 0x10) {
+ /* already in high speed mode */
+ return 0;
+ } else {
+ status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+ status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
+ serial_outp(up, 0x04, status);
+ }
+ return 1;
+}
+
+/*
+ * We know that the chip has FIFOs. Does it have an EFR? The
+ * EFR is located in the same register position as the IIR and
+ * we know the top two bits of the IIR are currently set. The
+ * EFR should contain zero. Try to read the EFR.
+ */
+static void autoconfig_16550a(struct uart_8250_port *up)
+{
+ unsigned char status1, status2;
+ unsigned int iersave;
+
+ up->port.type = PORT_16550A;
+ up->capabilities |= UART_CAP_FIFO;
+
+ /*
+ * Check for presence of the EFR when DLAB is set.
+ * Only ST16C650V1 UARTs pass this test.
+ */
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ if (serial_in(up, UART_EFR) == 0) {
+ serial_outp(up, UART_EFR, 0xA8);
+ if (serial_in(up, UART_EFR) != 0) {
+ DEBUG_AUTOCONF("EFRv1 ");
+ up->port.type = PORT_16650;
+ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+ } else {
+ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+ }
+ serial_outp(up, UART_EFR, 0);
+ return;
+ }
+
+ /*
+ * Maybe it requires 0xbf to be written to the LCR.
+ * (other ST16C650V2 UARTs, TI16C752A, etc)
+ */
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
+ DEBUG_AUTOCONF("EFRv2 ");
+ autoconfig_has_efr(up);
+ return;
+ }
+
+ /*
+ * Check for a National Semiconductor SuperIO chip.
+ * Attempt to switch to bank 2, read the value of the LOOP bit
+ * from EXCR1. Switch back to bank 0, change it in MCR. Then
+ * switch back to bank 2, read it from EXCR1 again and check
+ * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
+ */
+ serial_outp(up, UART_LCR, 0);
+ status1 = serial_in(up, UART_MCR);
+ serial_outp(up, UART_LCR, 0xE0);
+ status2 = serial_in(up, 0x02); /* EXCR1 */
+
+ if (!((status2 ^ status1) & UART_MCR_LOOP)) {
+ serial_outp(up, UART_LCR, 0);
+ serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
+ serial_outp(up, UART_LCR, 0xE0);
+ status2 = serial_in(up, 0x02); /* EXCR1 */
+ serial_outp(up, UART_LCR, 0);
+ serial_outp(up, UART_MCR, status1);
+
+ if ((status2 ^ status1) & UART_MCR_LOOP) {
+ unsigned short quot;
+
+ serial_outp(up, UART_LCR, 0xE0);
+
+ quot = serial_dl_read(up);
+ quot <<= 3;
+
+ if (ns16550a_goto_highspeed(up))
+ serial_dl_write(up, quot);
+
+ serial_outp(up, UART_LCR, 0);
+
+ up->port.uartclk = 921600*16;
+ up->port.type = PORT_NS16550A;
+ up->capabilities |= UART_NATSEMI;
+ return;
+ }
+ }
+
+ /*
+ * No EFR. Try to detect a TI16750, which only sets bit 5 of
+ * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
+ * Try setting it with and without DLAB set. Cheap clones
+ * set bit 5 without DLAB set.
+ */
+ serial_outp(up, UART_LCR, 0);
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+ status1 = serial_in(up, UART_IIR) >> 5;
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+ status2 = serial_in(up, UART_IIR) >> 5;
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_outp(up, UART_LCR, 0);
+
+ DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
+
+ if (status1 == 6 && status2 == 7) {
+ up->port.type = PORT_16750;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
+ return;
+ }
+
+ /*
+ * Try writing and reading the UART_IER_UUE bit (b6).
+ * If it works, this is probably one of the Xscale platform's
+ * internal UARTs.
+ * We're going to explicitly set the UUE bit to 0 before
+ * trying to write and read a 1 just to make sure it's not
+ * already a 1 and maybe locked there before we even start start.
+ */
+ iersave = serial_in(up, UART_IER);
+ serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
+ if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+ /*
+ * OK it's in a known zero state, try writing and reading
+ * without disturbing the current state of the other bits.
+ */
+ serial_outp(up, UART_IER, iersave | UART_IER_UUE);
+ if (serial_in(up, UART_IER) & UART_IER_UUE) {
+ /*
+ * It's an Xscale.
+ * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+ */
+ DEBUG_AUTOCONF("Xscale ");
+ up->port.type = PORT_XSCALE;
+ up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
+ return;
+ }
+ } else {
+ /*
+ * If we got here we couldn't force the IER_UUE bit to 0.
+ * Log it and continue.
+ */
+ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+ }
+ serial_outp(up, UART_IER, iersave);
+
+ /*
+ * Exar uarts have EFR in a weird location
+ */
+ if (up->port.flags & UPF_EXAR_EFR) {
+ up->port.type = PORT_XR17D15X;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
+ }
+
+ /*
+ * We distinguish between 16550A and U6 16550A by counting
+ * how many bytes are in the FIFO.
+ */
+ if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
+ up->port.type = PORT_U6_16550A;
+ up->capabilities |= UART_CAP_AFE;
+ }
+}
+
+/*
+ * This routine is called by rs_init() to initialize a specific serial
+ * port. It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A. The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+{
+ unsigned char status1, scratch, scratch2, scratch3;
+ unsigned char save_lcr, save_mcr;
+ unsigned long flags;
+
+ if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
+ return;
+
+ DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
+ serial_index(&up->port), up->port.iobase, up->port.membase);
+
+ /*
+ * We really do need global IRQs disabled here - we're going to
+ * be frobbing the chips IRQ enable register to see if it exists.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ up->capabilities = 0;
+ up->bugs = 0;
+
+ if (!(up->port.flags & UPF_BUGGY_UART)) {
+ /*
+ * Do a simple existence test first; if we fail this,
+ * there's no point trying anything else.
+ *
+ * 0x80 is used as a nonsense port to prevent against
+ * false positives due to ISA bus float. The
+ * assumption is that 0x80 is a non-existent port;
+ * which should be safe since include/asm/io.h also
+ * makes this assumption.
+ *
+ * Note: this is safe as long as MCR bit 4 is clear
+ * and the device is in "PC" mode.
+ */
+ scratch = serial_inp(up, UART_IER);
+ serial_outp(up, UART_IER, 0);
+#ifdef __i386__
+ outb(0xff, 0x080);
+#endif
+ /*
+ * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+ * 16C754B) allow only to modify them if an EFR bit is set.
+ */
+ scratch2 = serial_inp(up, UART_IER) & 0x0f;
+ serial_outp(up, UART_IER, 0x0F);
+#ifdef __i386__
+ outb(0, 0x080);
+#endif
+ scratch3 = serial_inp(up, UART_IER) & 0x0f;
+ serial_outp(up, UART_IER, scratch);
+ if (scratch2 != 0 || scratch3 != 0x0F) {
+ /*
+ * We failed; there's nothing here
+ */
+ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
+ scratch2, scratch3);
+ goto out;
+ }
+ }
+
+ save_mcr = serial_in(up, UART_MCR);
+ save_lcr = serial_in(up, UART_LCR);
+
+ /*
+ * Check to see if a UART is really there. Certain broken
+ * internal modems based on the Rockwell chipset fail this
+ * test, because they apparently don't implement the loopback
+ * test mode. So this test is skipped on the COM 1 through
+ * COM 4 ports. This *should* be safe, since no board
+ * manufacturer would be stupid enough to design a board
+ * that conflicts with COM 1-4 --- we hope!
+ */
+ if (!(up->port.flags & UPF_SKIP_TEST)) {
+ serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
+ status1 = serial_inp(up, UART_MSR) & 0xF0;
+ serial_outp(up, UART_MCR, save_mcr);
+ if (status1 != 0x90) {
+ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+ status1);
+ goto out;
+ }
+ }
+
+ /*
+ * We're pretty sure there's a port here. Lets find out what
+ * type of port it is. The IIR top two bits allows us to find
+ * out if it's 8250 or 16450, 16550, 16550A or later. This
+ * determines what we test for next.
+ *
+ * We also initialise the EFR (if any) to zero for later. The
+ * EFR occupies the same register location as the FCR and IIR.
+ */
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_outp(up, UART_EFR, 0);
+ serial_outp(up, UART_LCR, 0);
+
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ scratch = serial_in(up, UART_IIR) >> 6;
+
+ DEBUG_AUTOCONF("iir=%d ", scratch);
+
+ switch (scratch) {
+ case 0:
+ autoconfig_8250(up);
+ break;
+ case 1:
+ up->port.type = PORT_UNKNOWN;
+ break;
+ case 2:
+ up->port.type = PORT_16550;
+ break;
+ case 3:
+ autoconfig_16550a(up);
+ break;
+ }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * Only probe for RSA ports if we got the region.
+ */
+ if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
+ int i;
+
+ for (i = 0 ; i < probe_rsa_count; ++i) {
+ if (probe_rsa[i] == up->port.iobase &&
+ __enable_rsa(up)) {
+ up->port.type = PORT_RSA;
+ break;
+ }
+ }
+ }
+#endif
+
+ serial_outp(up, UART_LCR, save_lcr);
+
+ if (up->capabilities != uart_config[up->port.type].flags) {
+ printk(KERN_WARNING
+ "ttyS%d: detected caps %08x should be %08x\n",
+ serial_index(&up->port), up->capabilities,
+ uart_config[up->port.type].flags);
+ }
+
+ up->port.fifosize = uart_config[up->port.type].fifo_size;
+ up->capabilities = uart_config[up->port.type].flags;
+ up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+
+ if (up->port.type == PORT_UNKNOWN)
+ goto out;
+
+ /*
+ * Reset the UART.
+ */
+#ifdef CONFIG_SERIAL_8250_RSA
+ if (up->port.type == PORT_RSA)
+ serial_outp(up, UART_RSA_FRR, 0);
+#endif
+ serial_outp(up, UART_MCR, save_mcr);
+ serial8250_clear_fifos(up);
+ serial_in(up, UART_RX);
+ if (up->capabilities & UART_CAP_UUE)
+ serial_outp(up, UART_IER, UART_IER_UUE);
+ else
+ serial_outp(up, UART_IER, 0);
+
+ out:
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
+}
+
+static void autoconfig_irq(struct uart_8250_port *up)
+{
+ unsigned char save_mcr, save_ier;
+ unsigned char save_ICP = 0;
+ unsigned int ICP = 0;
+ unsigned long irqs;
+ int irq;
+
+ if (up->port.flags & UPF_FOURPORT) {
+ ICP = (up->port.iobase & 0xfe0) | 0x1f;
+ save_ICP = inb_p(ICP);
+ outb_p(0x80, ICP);
+ (void) inb_p(ICP);
+ }
+
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+ save_mcr = serial_inp(up, UART_MCR);
+ save_ier = serial_inp(up, UART_IER);
+ serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+ irqs = probe_irq_on();
+ serial_outp(up, UART_MCR, 0);
+ udelay(10);
+ if (up->port.flags & UPF_FOURPORT) {
+ serial_outp(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS);
+ } else {
+ serial_outp(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+ }
+ serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
+ (void)serial_inp(up, UART_LSR);
+ (void)serial_inp(up, UART_RX);
+ (void)serial_inp(up, UART_IIR);
+ (void)serial_inp(up, UART_MSR);
+ serial_outp(up, UART_TX, 0xFF);
+ udelay(20);
+ irq = probe_irq_off(irqs);
+
+ serial_outp(up, UART_MCR, save_mcr);
+ serial_outp(up, UART_IER, save_ier);
+
+ if (up->port.flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+
+ up->port.irq = (irq > 0) ? irq : 0;
+}
+
+static inline void __stop_tx(struct uart_8250_port *p)
+{
+ if (p->ier & UART_IER_THRI) {
+ p->ier &= ~UART_IER_THRI;
+ serial_out(p, UART_IER, p->ier);
+ }
+}
+
+static void serial8250_stop_tx(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ __stop_tx(up);
+
+ /*
+ * We really want to stop the transmitter from sending.
+ */
+ if (up->port.type == PORT_16C950) {
+ up->acr |= UART_ACR_TXDIS;
+ serial_icr_write(up, UART_ACR, up->acr);
+ }
+}
+
+static void serial8250_start_tx(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+
+ if (up->bugs & UART_BUG_TXEN) {
+ unsigned char lsr;
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ if ((up->port.type == PORT_RM9000) ?
+ (lsr & UART_LSR_THRE) :
+ (lsr & UART_LSR_TEMT))
+ serial8250_tx_chars(up);
+ }
+ }
+
+ /*
+ * Re-enable the transmitter if we disabled it.
+ */
+ if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
+ up->acr &= ~UART_ACR_TXDIS;
+ serial_icr_write(up, UART_ACR, up->acr);
+ }
+}
+
+static void serial8250_stop_rx(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+}
+
+static void serial8250_enable_ms(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ /* no MSR capabilities */
+ if (up->bugs & UART_BUG_NOMSR)
+ return;
+
+ up->ier |= UART_IER_MSI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+/*
+ * Clear the Tegra rx fifo after a break
+ *
+ * FIXME: This needs to become a port specific callback once we have a
+ * framework for this
+ */
+static void clear_rx_fifo(struct uart_8250_port *up)
+{
+ unsigned int status, tmout = 10000;
+ do {
+ status = serial_in(up, UART_LSR);
+ if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+ status = serial_in(up, UART_RX);
+ else
+ break;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while (1);
+}
+
+/*
+ * serial8250_rx_chars: processes according to the passed in LSR
+ * value, and returns the remaining LSR bits not handled
+ * by this Rx routine.
+ */
+unsigned char
+serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+{
+ struct tty_struct *tty = up->port.state->port.tty;
+ unsigned char ch;
+ int max_count = 256;
+ char flag;
+
+ do {
+ if (likely(lsr & UART_LSR_DR))
+ ch = serial_inp(up, UART_RX);
+ else
+ /*
+ * Intel 82571 has a Serial Over Lan device that will
+ * set UART_LSR_BI without setting UART_LSR_DR when
+ * it receives a break. To avoid reading from the
+ * receive buffer without UART_LSR_DR bit set, we
+ * just force the read character to be 0
+ */
+ ch = 0;
+
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ lsr |= up->lsr_saved_flags;
+ up->lsr_saved_flags = 0;
+
+ if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+ /*
+ * For statistics only
+ */
+ if (lsr & UART_LSR_BI) {
+ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+ up->port.icount.brk++;
+ /*
+ * If tegra port then clear the rx fifo to
+ * accept another break/character.
+ */
+ if (up->port.type == PORT_TEGRA)
+ clear_rx_fifo(up);
+
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(&up->port))
+ goto ignore_char;
+ } else if (lsr & UART_LSR_PE)
+ up->port.icount.parity++;
+ else if (lsr & UART_LSR_FE)
+ up->port.icount.frame++;
+ if (lsr & UART_LSR_OE)
+ up->port.icount.overrun++;
+
+ /*
+ * Mask off conditions which should be ignored.
+ */
+ lsr &= up->port.read_status_mask;
+
+ if (lsr & UART_LSR_BI) {
+ DEBUG_INTR("handling break....");
+ flag = TTY_BREAK;
+ } else if (lsr & UART_LSR_PE)
+ flag = TTY_PARITY;
+ else if (lsr & UART_LSR_FE)
+ flag = TTY_FRAME;
+ }
+ if (uart_handle_sysrq_char(&up->port, ch))
+ goto ignore_char;
+
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+
+ignore_char:
+ lsr = serial_inp(up, UART_LSR);
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+ return lsr;
+}
+EXPORT_SYMBOL_GPL(serial8250_rx_chars);
+
+void serial8250_tx_chars(struct uart_8250_port *up)
+{
+ struct circ_buf *xmit = &up->port.state->xmit;
+ int count;
+
+ if (up->port.x_char) {
+ serial_outp(up, UART_TX, up->port.x_char);
+ up->port.icount.tx++;
+ up->port.x_char = 0;
+ return;
+ }
+ if (uart_tx_stopped(&up->port)) {
+ serial8250_stop_tx(&up->port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
+ __stop_tx(up);
+ return;
+ }
+
+ count = up->tx_loadsz;
+ do {
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ up->port.icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ } while (--count > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+
+ DEBUG_INTR("THRE...");
+
+ if (uart_circ_empty(xmit))
+ __stop_tx(up);
+}
+EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+
+unsigned int serial8250_modem_status(struct uart_8250_port *up)
+{
+ unsigned int status = serial_in(up, UART_MSR);
+
+ status |= up->msr_saved_flags;
+ up->msr_saved_flags = 0;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+ up->port.state != NULL) {
+ if (status & UART_MSR_TERI)
+ up->port.icount.rng++;
+ if (status & UART_MSR_DDSR)
+ up->port.icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+
+ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+ }
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(serial8250_modem_status);
+
+/*
+ * This handles the interrupt from one port.
+ */
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+ unsigned char status;
+ unsigned long flags;
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ if (iir & UART_IIR_NO_INT)
+ return 0;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ status = serial_inp(up, UART_LSR);
+
+ DEBUG_INTR("status = %x...", status);
+
+ if (status & (UART_LSR_DR | UART_LSR_BI))
+ status = serial8250_rx_chars(up, status);
+ serial8250_modem_status(up);
+ if (status & UART_LSR_THRE)
+ serial8250_tx_chars(up);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+static int serial8250_default_handle_irq(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned int iir = serial_in(up, UART_IIR);
+
+ return serial8250_handle_irq(port, iir);
+}
+
+/*
+ * This is the serial driver's interrupt routine.
+ *
+ * Arjan thinks the old way was overly complex, so it got simplified.
+ * Alan disagrees, saying that need the complexity to handle the weird
+ * nature of ISA shared interrupts. (This is a special exception.)
+ *
+ * In order to handle ISA shared interrupts properly, we need to check
+ * that all ports have been serviced, and therefore the ISA interrupt
+ * line has been de-asserted.
+ *
+ * This means we need to loop through all ports. checking that they
+ * don't have an interrupt pending.
+ */
+static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
+{
+ struct irq_info *i = dev_id;
+ struct list_head *l, *end = NULL;
+ int pass_counter = 0, handled = 0;
+
+ DEBUG_INTR("serial8250_interrupt(%d)...", irq);
+
+ spin_lock(&i->lock);
+
+ l = i->head;
+ do {
+ struct uart_8250_port *up;
+ struct uart_port *port;
+ bool skip;
+
+ up = list_entry(l, struct uart_8250_port, list);
+ port = &up->port;
+ skip = pass_counter && up->port.flags & UPF_IIR_ONCE;
+
+ if (!skip && port->handle_irq(port)) {
+ handled = 1;
+ end = NULL;
+ } else if (end == NULL)
+ end = l;
+
+ l = l->next;
+
+ if (l == i->head && pass_counter++ > PASS_LIMIT) {
+ /* If we hit this, we're dead. */
+ printk_ratelimited(KERN_ERR
+ "serial8250: too much work for irq%d\n", irq);
+ break;
+ }
+ } while (l != end);
+
+ spin_unlock(&i->lock);
+
+ DEBUG_INTR("end.\n");
+
+ return IRQ_RETVAL(handled);
+}
+
+/*
+ * To support ISA shared interrupts, we need to have one interrupt
+ * handler that ensures that the IRQ line has been deasserted
+ * before returning. Failing to do this will result in the IRQ
+ * line being stuck active, and, since ISA irqs are edge triggered,
+ * no more IRQs will be seen.
+ */
+static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
+{
+ spin_lock_irq(&i->lock);
+
+ if (!list_empty(i->head)) {
+ if (i->head == &up->list)
+ i->head = i->head->next;
+ list_del(&up->list);
+ } else {
+ BUG_ON(i->head != &up->list);
+ i->head = NULL;
+ }
+ spin_unlock_irq(&i->lock);
+ /* List empty so throw away the hash node */
+ if (i->head == NULL) {
+ hlist_del(&i->node);
+ kfree(i);
+ }
+}
+
+static int serial_link_irq_chain(struct uart_8250_port *up)
+{
+ struct hlist_head *h;
+ struct hlist_node *n;
+ struct irq_info *i;
+ int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+
+ mutex_lock(&hash_mutex);
+
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ if (n == NULL) {
+ i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+ if (i == NULL) {
+ mutex_unlock(&hash_mutex);
+ return -ENOMEM;
+ }
+ spin_lock_init(&i->lock);
+ i->irq = up->port.irq;
+ hlist_add_head(&i->node, h);
+ }
+ mutex_unlock(&hash_mutex);
+
+ spin_lock_irq(&i->lock);
+
+ if (i->head) {
+ list_add(&up->list, i->head);
+ spin_unlock_irq(&i->lock);
+
+ ret = 0;
+ } else {
+ INIT_LIST_HEAD(&up->list);
+ i->head = &up->list;
+ spin_unlock_irq(&i->lock);
+ irq_flags |= up->port.irqflags;
+ ret = request_irq(up->port.irq, serial8250_interrupt,
+ irq_flags, "serial", i);
+ if (ret < 0)
+ serial_do_unlink(i, up);
+ }
+
+ return ret;
+}
+
+static void serial_unlink_irq_chain(struct uart_8250_port *up)
+{
+ struct irq_info *i;
+ struct hlist_node *n;
+ struct hlist_head *h;
+
+ mutex_lock(&hash_mutex);
+
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ BUG_ON(n == NULL);
+ BUG_ON(i->head == NULL);
+
+ if (list_empty(i->head))
+ free_irq(up->port.irq, i);
+
+ serial_do_unlink(i, up);
+ mutex_unlock(&hash_mutex);
+}
+
+/*
+ * This function is used to handle ports that do not have an
+ * interrupt. This doesn't work very well for 16450's, but gives
+ * barely passable results for a 16550A. (Although at the expense
+ * of much CPU overhead).
+ */
+static void serial8250_timeout(unsigned long data)
+{
+ struct uart_8250_port *up = (struct uart_8250_port *)data;
+
+ up->port.handle_irq(&up->port);
+ mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
+}
+
+static void serial8250_backup_timeout(unsigned long data)
+{
+ struct uart_8250_port *up = (struct uart_8250_port *)data;
+ unsigned int iir, ier = 0, lsr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /*
+ * Must disable interrupts or else we risk racing with the interrupt
+ * based handler.
+ */
+ if (is_real_interrupt(up->port.irq)) {
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
+ }
+
+ iir = serial_in(up, UART_IIR);
+
+ /*
+ * This should be a safe test for anyone who doesn't trust the
+ * IIR bits on their UART, but it's specifically designed for
+ * the "Diva" UART used on the management processor on many HP
+ * ia64 and parisc boxes.
+ */
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+ (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
+ (lsr & UART_LSR_THRE)) {
+ iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+ iir |= UART_IIR_THRI;
+ }
+
+ if (!(iir & UART_IIR_NO_INT))
+ serial8250_tx_chars(up);
+
+ if (is_real_interrupt(up->port.irq))
+ serial_out(up, UART_IER, ier);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /* Standard timer interval plus 0.2s to keep the port running */
+ mod_timer(&up->timer,
+ jiffies + uart_poll_timeout(&up->port) + HZ / 5);
+}
+
+static unsigned int serial8250_tx_empty(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned long flags;
+ unsigned int lsr;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int serial8250_get_mctrl(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned int status;
+ unsigned int ret;
+
+ status = serial8250_modem_status(up);
+
+ ret = 0;
+ if (status & UART_MSR_DCD)
+ ret |= TIOCM_CAR;
+ if (status & UART_MSR_RI)
+ ret |= TIOCM_RNG;
+ if (status & UART_MSR_DSR)
+ ret |= TIOCM_DSR;
+ if (status & UART_MSR_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned char mcr = 0;
+
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
+
+ serial_out(up, UART_MCR, mcr);
+}
+
+static void serial8250_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(up, UART_LCR, up->lcr);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+ unsigned int status, tmout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ for (;;) {
+ status = serial_in(up, UART_LSR);
+
+ up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
+
+ if ((status & bits) == bits)
+ break;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ }
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ unsigned int tmout;
+ for (tmout = 1000000; tmout; tmout--) {
+ unsigned int msr = serial_in(up, UART_MSR);
+ up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+ if (msr & UART_MSR_CTS)
+ break;
+ udelay(1);
+ touch_nmi_watchdog();
+ }
+ }
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial8250_get_poll_char(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned char lsr = serial_inp(up, UART_LSR);
+
+ if (!(lsr & UART_LSR_DR))
+ return NO_POLL_CHAR;
+
+ return serial_inp(up, UART_RX);
+}
+
+
+static void serial8250_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ unsigned int ier;
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_in(up, UART_IER);
+ if (up->capabilities & UART_CAP_UUE)
+ serial_out(up, UART_IER, UART_IER_UUE);
+ else
+ serial_out(up, UART_IER, 0);
+
+ wait_for_xmitr(up, BOTH_EMPTY);
+ /*
+ * Send the character out.
+ * If a LF, also do CR...
+ */
+ serial_out(up, UART_TX, c);
+ if (c == 10) {
+ wait_for_xmitr(up, BOTH_EMPTY);
+ serial_out(up, UART_TX, 13);
+ }
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+ serial_out(up, UART_IER, ier);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+static int serial8250_startup(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned long flags;
+ unsigned char lsr, iir;
+ int retval;
+
+ up->port.fifosize = uart_config[up->port.type].fifo_size;
+ up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+ up->capabilities = uart_config[up->port.type].flags;
+ up->mcr = 0;
+
+ if (up->port.iotype != up->cur_iotype)
+ set_io_from_upio(port);
+
+ if (up->port.type == PORT_16C950) {
+ /* Wake up and initialize UART */
+ up->acr = 0;
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_outp(up, UART_EFR, UART_EFR_ECB);
+ serial_outp(up, UART_IER, 0);
+ serial_outp(up, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_outp(up, UART_EFR, UART_EFR_ECB);
+ serial_outp(up, UART_LCR, 0);
+ }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * If this is an RSA port, see if we can kick it up to the
+ * higher speed clock.
+ */
+ enable_rsa(up);
+#endif
+
+ /*
+ * Clear the FIFO buffers and disable them.
+ * (they will be reenabled in set_termios())
+ */
+ serial8250_clear_fifos(up);
+
+ /*
+ * Clear the interrupt registers.
+ */
+ (void) serial_inp(up, UART_LSR);
+ (void) serial_inp(up, UART_RX);
+ (void) serial_inp(up, UART_IIR);
+ (void) serial_inp(up, UART_MSR);
+
+ /*
+ * At this point, there's no way the LSR could still be 0xff;
+ * if it is, then bail out, because there's likely no UART
+ * here.
+ */
+ if (!(up->port.flags & UPF_BUGGY_UART) &&
+ (serial_inp(up, UART_LSR) == 0xff)) {
+ printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+ serial_index(&up->port));
+ return -ENODEV;
+ }
+
+ /*
+ * For a XR16C850, we need to set the trigger levels
+ */
+ if (up->port.type == PORT_16850) {
+ unsigned char fctr;
+
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+ fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+ serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+ serial_outp(up, UART_TRG, UART_TRG_96);
+ serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+ serial_outp(up, UART_TRG, UART_TRG_96);
+
+ serial_outp(up, UART_LCR, 0);
+ }
+
+ if (is_real_interrupt(up->port.irq)) {
+ unsigned char iir1;
+ /*
+ * Test for UARTs that do not reassert THRE when the
+ * transmitter is idle and the interrupt has already
+ * been cleared. Real 16550s should always reassert
+ * this interrupt whenever the transmitter is idle and
+ * the interrupt is enabled. Delays are necessary to
+ * allow register changes to become visible.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.irqflags & IRQF_SHARED)
+ disable_irq_nosync(up->port.irq);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+ iir1 = serial_in(up, UART_IIR);
+ serial_out(up, UART_IER, 0);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow a working UART time to re-assert THRE */
+ iir = serial_in(up, UART_IIR);
+ serial_out(up, UART_IER, 0);
+
+ if (up->port.irqflags & IRQF_SHARED)
+ enable_irq(up->port.irq);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
+ * If the interrupt is not reasserted, setup a timer to
+ * kick the UART on a regular basis.
+ */
+ if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
+ up->bugs |= UART_BUG_THRE;
+ pr_debug("ttyS%d - using backup timer\n",
+ serial_index(port));
+ }
+ }
+
+ /*
+ * The above check will only give an accurate result the first time
+ * the port is opened so this value needs to be preserved.
+ */
+ if (up->bugs & UART_BUG_THRE) {
+ up->timer.function = serial8250_backup_timeout;
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies +
+ uart_poll_timeout(port) + HZ / 5);
+ }
+
+ /*
+ * If the "interrupt" for this port doesn't correspond with any
+ * hardware interrupt, we use a timer-based system. The original
+ * driver used to do this with IRQ0.
+ */
+ if (!is_real_interrupt(up->port.irq)) {
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+ } else {
+ retval = serial_link_irq_chain(up);
+ if (retval)
+ return retval;
+ }
+
+ /*
+ * Now, initialize the UART
+ */
+ serial_outp(up, UART_LCR, UART_LCR_WLEN8);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ if (!is_real_interrupt(up->port.irq))
+ up->port.mctrl |= TIOCM_OUT1;
+ } else
+ /*
+ * Most PC uarts need OUT2 raised to enable interrupts.
+ */
+ if (is_real_interrupt(up->port.irq))
+ up->port.mctrl |= TIOCM_OUT2;
+
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+
+ /* Serial over Lan (SoL) hack:
+ Intel 8257x Gigabit ethernet chips have a
+ 16550 emulation, to be used for Serial Over Lan.
+ Those chips take a longer time than a normal
+ serial device to signalize that a transmission
+ data was queued. Due to that, the above test generally
+ fails. One solution would be to delay the reading of
+ iir. However, this is not reliable, since the timeout
+ is variable. So, let's just don't test if we receive
+ TX irq. This way, we'll never enable UART_BUG_TXEN.
+ */
+ if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
+ goto dont_test_tx_en;
+
+ /*
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+ */
+ serial_outp(up, UART_IER, UART_IER_THRI);
+ lsr = serial_in(up, UART_LSR);
+ iir = serial_in(up, UART_IIR);
+ serial_outp(up, UART_IER, 0);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+ up->bugs |= UART_BUG_TXEN;
+ pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+ serial_index(port));
+ }
+ } else {
+ up->bugs &= ~UART_BUG_TXEN;
+ }
+
+dont_test_tx_en:
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
+ * Clear the interrupt registers again for luck, and clear the
+ * saved flags to avoid getting false values from polling
+ * routines or the previous session.
+ */
+ serial_inp(up, UART_LSR);
+ serial_inp(up, UART_RX);
+ serial_inp(up, UART_IIR);
+ serial_inp(up, UART_MSR);
+ up->lsr_saved_flags = 0;
+ up->msr_saved_flags = 0;
+
+ /*
+ * Finally, enable interrupts. Note: Modem status interrupts
+ * are set via set_termios(), which will be occurring imminently
+ * anyway, so we don't enable them here.
+ */
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_outp(up, UART_IER, up->ier);
+
+ if (up->port.flags & UPF_FOURPORT) {
+ unsigned int icp;
+ /*
+ * Enable interrupts on the AST Fourport board
+ */
+ icp = (up->port.iobase & 0xfe0) | 0x01f;
+ outb_p(0x80, icp);
+ (void) inb_p(icp);
+ }
+
+ return 0;
+}
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned long flags;
+
+ /*
+ * Disable interrupts from this port
+ */
+ up->ier = 0;
+ serial_outp(up, UART_IER, 0);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ /* reset interrupts on the AST Fourport board */
+ inb((up->port.iobase & 0xfe0) | 0x1f);
+ up->port.mctrl |= TIOCM_OUT1;
+ } else
+ up->port.mctrl &= ~TIOCM_OUT2;
+
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
+ * Disable break condition and FIFOs
+ */
+ serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
+ serial8250_clear_fifos(up);
+
+#ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * Reset the RSA board back to 115kbps compat mode.
+ */
+ disable_rsa(up);
+#endif
+
+ /*
+ * Read data port to reset things, and then unlink from
+ * the IRQ chain.
+ */
+ (void) serial_in(up, UART_RX);
+
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+ if (is_real_interrupt(up->port.irq))
+ serial_unlink_irq_chain(up);
+}
+
+static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
+{
+ unsigned int quot;
+
+ /*
+ * Handle magic divisors for baud rates above baud_base on
+ * SMSC SuperIO chips.
+ */
+ if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+ baud == (port->uartclk/4))
+ quot = 0x8001;
+ else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+ baud == (port->uartclk/8))
+ quot = 0x8002;
+ else
+ quot = uart_get_divisor(port, baud);
+
+ return quot;
+}
+
+void
+serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ unsigned char cval, fcr = 0;
+ unsigned long flags;
+ unsigned int baud, quot;
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ cval = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ cval = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ cval = UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ cval = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ cval |= UART_LCR_STOP;
+ if (termios->c_cflag & PARENB)
+ cval |= UART_LCR_PARITY;
+ if (!(termios->c_cflag & PARODD))
+ cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+ if (termios->c_cflag & CMSPAR)
+ cval |= UART_LCR_SPAR;
+#endif
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 16);
+ quot = serial8250_get_divisor(port, baud);
+
+ /*
+ * Oxford Semi 952 rev B workaround
+ */
+ if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
+ quot++;
+
+ if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
+ if (baud < 2400)
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+ else
+ fcr = uart_config[up->port.type].fcr;
+ }
+
+ /*
+ * MCR-based auto flow control. When AFE is enabled, RTS will be
+ * deasserted when the receive FIFO contains more characters than
+ * the trigger, or the MCR RTS bit is cleared. In the case where
+ * the remote UART is not using CTS auto flow control, we must
+ * have sufficient FIFO entries for the latency of the remote
+ * UART to respond. IOW, at least 32 bytes of FIFO.
+ */
+ if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
+ up->mcr &= ~UART_MCR_AFE;
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE;
+ }
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (termios->c_iflag & INPCK)
+ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ up->port.read_status_mask |= UART_LSR_BI;
+
+ /*
+ * Characteres to ignore
+ */
+ up->port.ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ up->port.ignore_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_OE;
+ }
+
+ /*
+ * ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= UART_LSR_DR;
+
+ /*
+ * CTS flow control flag and modem status interrupts
+ */
+ up->ier &= ~UART_IER_MSI;
+ if (!(up->bugs & UART_BUG_NOMSR) &&
+ UART_ENABLE_MS(&up->port, termios->c_cflag))
+ up->ier |= UART_IER_MSI;
+ if (up->capabilities & UART_CAP_UUE)
+ up->ier |= UART_IER_UUE;
+ if (up->capabilities & UART_CAP_RTOIE)
+ up->ier |= UART_IER_RTOIE;
+
+ serial_out(up, UART_IER, up->ier);
+
+ if (up->capabilities & UART_CAP_EFR) {
+ unsigned char efr = 0;
+ /*
+ * TI16C752/Startech hardware flow control. FIXME:
+ * - TI16C752 requires control thresholds to be set.
+ * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
+ */
+ if (termios->c_cflag & CRTSCTS)
+ efr |= UART_EFR_CTS;
+
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (up->port.flags & UPF_EXAR_EFR)
+ serial_outp(up, UART_XR_EFR, efr);
+ else
+ serial_outp(up, UART_EFR, efr);
+ }
+
+#ifdef CONFIG_ARCH_OMAP
+ /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+ if (cpu_is_omap1510() && is_omap_port(up)) {
+ if (baud == 115200) {
+ quot = 1;
+ serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
+ } else
+ serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
+ }
+#endif
+
+ if (up->capabilities & UART_NATSEMI) {
+ /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
+ serial_outp(up, UART_LCR, 0xe0);
+ } else {
+ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+ }
+
+ serial_dl_write(up, quot);
+
+ /*
+ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+ * is written without DLAB set, this mode will be disabled.
+ */
+ if (up->port.type == PORT_16750)
+ serial_outp(up, UART_FCR, fcr);
+
+ serial_outp(up, UART_LCR, cval); /* reset DLAB */
+ up->lcr = cval; /* Save LCR */
+ if (up->port.type != PORT_16750) {
+ if (fcr & UART_FCR_ENABLE_FIFO) {
+ /* emulated UARTs (Lucent Venus 167x) need two steps */
+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ }
+ serial_outp(up, UART_FCR, fcr); /* set fcr */
+ }
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+}
+EXPORT_SYMBOL(serial8250_do_set_termios);
+
+static void
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ if (port->set_termios)
+ port->set_termios(port, termios, old);
+ else
+ serial8250_do_set_termios(port, termios, old);
+}
+
+static void
+serial8250_set_ldisc(struct uart_port *port, int new)
+{
+ if (new == N_PPS) {
+ port->flags |= UPF_HARDPPS_CD;
+ serial8250_enable_ms(port);
+ } else
+ port->flags &= ~UPF_HARDPPS_CD;
+}
+
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct uart_8250_port *p =
+ container_of(port, struct uart_8250_port, port);
+
+ serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
+
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ if (port->pm)
+ port->pm(port, state, oldstate);
+ else
+ serial8250_do_pm(port, state, oldstate);
+}
+
+static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+{
+ if (pt->port.iotype == UPIO_AU)
+ return 0x1000;
+#ifdef CONFIG_ARCH_OMAP
+ if (is_omap_port(pt))
+ return 0x16 << pt->port.regshift;
+#endif
+ return 8 << pt->port.regshift;
+}
+
+/*
+ * Resource handling.
+ */
+static int serial8250_request_std_resource(struct uart_8250_port *up)
+{
+ unsigned int size = serial8250_port_size(up);
+ int ret = 0;
+
+ switch (up->port.iotype) {
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM:
+ if (!up->port.mapbase)
+ break;
+
+ if (!request_mem_region(up->port.mapbase, size, "serial")) {
+ ret = -EBUSY;
+ break;
+ }
+
+ if (up->port.flags & UPF_IOREMAP) {
+ up->port.membase = ioremap_nocache(up->port.mapbase,
+ size);
+ if (!up->port.membase) {
+ release_mem_region(up->port.mapbase, size);
+ ret = -ENOMEM;
+ }
+ }
+ break;
+
+ case UPIO_HUB6:
+ case UPIO_PORT:
+ if (!request_region(up->port.iobase, size, "serial"))
+ ret = -EBUSY;
+ break;
+ }
+ return ret;
+}
+
+static void serial8250_release_std_resource(struct uart_8250_port *up)
+{
+ unsigned int size = serial8250_port_size(up);
+
+ switch (up->port.iotype) {
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM:
+ if (!up->port.mapbase)
+ break;
+
+ if (up->port.flags & UPF_IOREMAP) {
+ iounmap(up->port.membase);
+ up->port.membase = NULL;
+ }
+
+ release_mem_region(up->port.mapbase, size);
+ break;
+
+ case UPIO_HUB6:
+ case UPIO_PORT:
+ release_region(up->port.iobase, size);
+ break;
+ }
+}
+
+static int serial8250_request_rsa_resource(struct uart_8250_port *up)
+{
+ unsigned long start = UART_RSA_BASE << up->port.regshift;
+ unsigned int size = 8 << up->port.regshift;
+ int ret = -EINVAL;
+
+ switch (up->port.iotype) {
+ case UPIO_HUB6:
+ case UPIO_PORT:
+ start += up->port.iobase;
+ if (request_region(start, size, "serial-rsa"))
+ ret = 0;
+ else
+ ret = -EBUSY;
+ break;
+ }
+
+ return ret;
+}
+
+static void serial8250_release_rsa_resource(struct uart_8250_port *up)
+{
+ unsigned long offset = UART_RSA_BASE << up->port.regshift;
+ unsigned int size = 8 << up->port.regshift;
+
+ switch (up->port.iotype) {
+ case UPIO_HUB6:
+ case UPIO_PORT:
+ release_region(up->port.iobase + offset, size);
+ break;
+ }
+}
+
+static void serial8250_release_port(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ serial8250_release_std_resource(up);
+ if (up->port.type == PORT_RSA)
+ serial8250_release_rsa_resource(up);
+}
+
+static int serial8250_request_port(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ int ret = 0;
+
+ ret = serial8250_request_std_resource(up);
+ if (ret == 0 && up->port.type == PORT_RSA) {
+ ret = serial8250_request_rsa_resource(up);
+ if (ret < 0)
+ serial8250_release_std_resource(up);
+ }
+
+ return ret;
+}
+
+static void serial8250_config_port(struct uart_port *port, int flags)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+ int probeflags = PROBE_ANY;
+ int ret;
+
+ /*
+ * Find the region that we can probe for. This in turn
+ * tells us whether we can probe for the type of port.
+ */
+ ret = serial8250_request_std_resource(up);
+ if (ret < 0)
+ return;
+
+ ret = serial8250_request_rsa_resource(up);
+ if (ret < 0)
+ probeflags &= ~PROBE_RSA;
+
+ if (up->port.iotype != up->cur_iotype)
+ set_io_from_upio(port);
+
+ if (flags & UART_CONFIG_TYPE)
+ autoconfig(up, probeflags);
+
+ /* if access method is AU, it is a 16550 with a quirk */
+ if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
+ up->bugs |= UART_BUG_NOMSR;
+
+ if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
+ autoconfig_irq(up);
+
+ if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
+ serial8250_release_rsa_resource(up);
+ if (up->port.type == PORT_UNKNOWN)
+ serial8250_release_std_resource(up);
+}
+
+static int
+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if (ser->irq >= nr_irqs || ser->irq < 0 ||
+ ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+ ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
+ ser->type == PORT_STARTECH)
+ return -EINVAL;
+ return 0;
+}
+
+static const char *
+serial8250_type(struct uart_port *port)
+{
+ int type = port->type;
+
+ if (type >= ARRAY_SIZE(uart_config))
+ type = 0;
+ return uart_config[type].name;
+}
+
+static struct uart_ops serial8250_pops = {
+ .tx_empty = serial8250_tx_empty,
+ .set_mctrl = serial8250_set_mctrl,
+ .get_mctrl = serial8250_get_mctrl,
+ .stop_tx = serial8250_stop_tx,
+ .start_tx = serial8250_start_tx,
+ .stop_rx = serial8250_stop_rx,
+ .enable_ms = serial8250_enable_ms,
+ .break_ctl = serial8250_break_ctl,
+ .startup = serial8250_startup,
+ .shutdown = serial8250_shutdown,
+ .set_termios = serial8250_set_termios,
+ .set_ldisc = serial8250_set_ldisc,
+ .pm = serial8250_pm,
+ .type = serial8250_type,
+ .release_port = serial8250_release_port,
+ .request_port = serial8250_request_port,
+ .config_port = serial8250_config_port,
+ .verify_port = serial8250_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = serial8250_get_poll_char,
+ .poll_put_char = serial8250_put_poll_char,
+#endif
+};
+
+static struct uart_8250_port serial8250_ports[UART_NR];
+
+static void (*serial8250_isa_config)(int port, struct uart_port *up,
+ unsigned short *capabilities);
+
+void serial8250_set_isa_configurator(
+ void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
+{
+ serial8250_isa_config = v;
+}
+EXPORT_SYMBOL(serial8250_set_isa_configurator);
+
+static void __init serial8250_isa_init_ports(void)
+{
+ struct uart_8250_port *up;
+ static int first = 1;
+ int i, irqflag = 0;
+
+ if (!first)
+ return;
+ first = 0;
+
+ for (i = 0; i < nr_uarts; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+
+ up->port.line = i;
+ spin_lock_init(&up->port.lock);
+
+ init_timer(&up->timer);
+ up->timer.function = serial8250_timeout;
+
+ /*
+ * ALPHA_KLUDGE_MCR needs to be killed.
+ */
+ up->mcr_mask = ~ALPHA_KLUDGE_MCR;
+ up->mcr_force = ALPHA_KLUDGE_MCR;
+
+ up->port.ops = &serial8250_pops;
+ }
+
+ if (share_irqs)
+ irqflag = IRQF_SHARED;
+
+ for (i = 0, up = serial8250_ports;
+ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
+ i++, up++) {
+ up->port.iobase = old_serial_port[i].port;
+ up->port.irq = irq_canonicalize(old_serial_port[i].irq);
+ up->port.irqflags = old_serial_port[i].irqflags;
+ up->port.uartclk = old_serial_port[i].baud_base * 16;
+ up->port.flags = old_serial_port[i].flags;
+ up->port.hub6 = old_serial_port[i].hub6;
+ up->port.membase = old_serial_port[i].iomem_base;
+ up->port.iotype = old_serial_port[i].io_type;
+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ set_io_from_upio(&up->port);
+ up->port.irqflags |= irqflag;
+ if (serial8250_isa_config != NULL)
+ serial8250_isa_config(i, &up->port, &up->capabilities);
+
+ }
+}
+
+static void
+serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
+{
+ up->port.type = type;
+ up->port.fifosize = uart_config[type].fifo_size;
+ up->capabilities = uart_config[type].flags;
+ up->tx_loadsz = uart_config[type].tx_loadsz;
+}
+
+static void __init
+serial8250_register_ports(struct uart_driver *drv, struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < nr_uarts; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+ up->cur_iotype = 0xFF;
+ }
+
+ serial8250_isa_init_ports();
+
+ for (i = 0; i < nr_uarts; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+
+ up->port.dev = dev;
+
+ if (up->port.flags & UPF_FIXED_TYPE)
+ serial8250_init_fixed_type_port(up, up->port.type);
+
+ uart_add_one_port(drv, &up->port);
+ }
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+
+static void serial8250_console_putchar(struct uart_port *port, int ch)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_out(up, UART_TX, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void
+serial8250_console_write(struct console *co, const char *s, unsigned int count)
+{
+ struct uart_8250_port *up = &serial8250_ports[co->index];
+ unsigned long flags;
+ unsigned int ier;
+ int locked = 1;
+
+ touch_nmi_watchdog();
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ /* serial8250_handle_irq() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_in(up, UART_IER);
+
+ if (up->capabilities & UART_CAP_UUE)
+ serial_out(up, UART_IER, UART_IER_UUE);
+ else
+ serial_out(up, UART_IER, 0);
+
+ uart_console_write(&up->port, s, count, serial8250_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+ serial_out(up, UART_IER, ier);
+
+ /*
+ * The receive handling will happen properly because the
+ * receive ready bit will still be set; it is not cleared
+ * on read. However, modem control will not, we must
+ * call it if we have saved something in the saved flags
+ * while processing with interrupts off.
+ */
+ if (up->msr_saved_flags)
+ serial8250_modem_status(up);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
+}
+
+static int __init serial8250_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (co->index >= nr_uarts)
+ co->index = 0;
+ port = &serial8250_ports[co->index].port;
+ if (!port->iobase && !port->membase)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static int serial8250_console_early_setup(void)
+{
+ return serial8250_find_port_for_earlycon();
+}
+
+static struct console serial8250_console = {
+ .name = "ttyS",
+ .write = serial8250_console_write,
+ .device = uart_console_device,
+ .setup = serial8250_console_setup,
+ .early_setup = serial8250_console_early_setup,
+ .flags = CON_PRINTBUFFER | CON_ANYTIME,
+ .index = -1,
+ .data = &serial8250_reg,
+};
+
+static int __init serial8250_console_init(void)
+{
+ if (nr_uarts > UART_NR)
+ nr_uarts = UART_NR;
+
+ serial8250_isa_init_ports();
+ register_console(&serial8250_console);
+ return 0;
+}
+console_initcall(serial8250_console_init);
+
+int serial8250_find_port(struct uart_port *p)
+{
+ int line;
+ struct uart_port *port;
+
+ for (line = 0; line < nr_uarts; line++) {
+ port = &serial8250_ports[line].port;
+ if (uart_match_port(p, port))
+ return line;
+ }
+ return -ENODEV;
+}
+
+#define SERIAL8250_CONSOLE &serial8250_console
+#else
+#define SERIAL8250_CONSOLE NULL
+#endif
+
+static struct uart_driver serial8250_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "ttyS",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .cons = SERIAL8250_CONSOLE,
+};
+
+/*
+ * early_serial_setup - early registration for 8250 ports
+ *
+ * Setup an 8250 port structure prior to console initialisation. Use
+ * after console initialisation will cause undefined behaviour.
+ */
+int __init early_serial_setup(struct uart_port *port)
+{
+ struct uart_port *p;
+
+ if (port->line >= ARRAY_SIZE(serial8250_ports))
+ return -ENODEV;
+
+ serial8250_isa_init_ports();
+ p = &serial8250_ports[port->line].port;
+ p->iobase = port->iobase;
+ p->membase = port->membase;
+ p->irq = port->irq;
+ p->irqflags = port->irqflags;
+ p->uartclk = port->uartclk;
+ p->fifosize = port->fifosize;
+ p->regshift = port->regshift;
+ p->iotype = port->iotype;
+ p->flags = port->flags;
+ p->mapbase = port->mapbase;
+ p->private_data = port->private_data;
+ p->type = port->type;
+ p->line = port->line;
+
+ set_io_from_upio(p);
+ if (port->serial_in)
+ p->serial_in = port->serial_in;
+ if (port->serial_out)
+ p->serial_out = port->serial_out;
+ if (port->handle_irq)
+ p->handle_irq = port->handle_irq;
+ else
+ p->handle_irq = serial8250_default_handle_irq;
+
+ return 0;
+}
+
+/**
+ * serial8250_suspend_port - suspend one serial port
+ * @line: serial line number
+ *
+ * Suspend one serial port.
+ */
+void serial8250_suspend_port(int line)
+{
+ uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
+}
+
+/**
+ * serial8250_resume_port - resume one serial port
+ * @line: serial line number
+ *
+ * Resume one serial port.
+ */
+void serial8250_resume_port(int line)
+{
+ struct uart_8250_port *up = &serial8250_ports[line];
+
+ if (up->capabilities & UART_NATSEMI) {
+ /* Ensure it's still in high speed mode */
+ serial_outp(up, UART_LCR, 0xE0);
+
+ ns16550a_goto_highspeed(up);
+
+ serial_outp(up, UART_LCR, 0);
+ up->port.uartclk = 921600*16;
+ }
+ uart_resume_port(&serial8250_reg, &up->port);
+}
+
+/*
+ * Register a set of serial devices attached to a platform device. The
+ * list is terminated with a zero flags entry, which means we expect
+ * all entries to have at least UPF_BOOT_AUTOCONF set.
+ */
+static int __devinit serial8250_probe(struct platform_device *dev)
+{
+ struct plat_serial8250_port *p = dev->dev.platform_data;
+ struct uart_port port;
+ int ret, i, irqflag = 0;
+
+ memset(&port, 0, sizeof(struct uart_port));
+
+ if (share_irqs)
+ irqflag = IRQF_SHARED;
+
+ for (i = 0; p && p->flags != 0; p++, i++) {
+ port.iobase = p->iobase;
+ port.membase = p->membase;
+ port.irq = p->irq;
+ port.irqflags = p->irqflags;
+ port.uartclk = p->uartclk;
+ port.regshift = p->regshift;
+ port.iotype = p->iotype;
+ port.flags = p->flags;
+ port.mapbase = p->mapbase;
+ port.hub6 = p->hub6;
+ port.private_data = p->private_data;
+ port.type = p->type;
+ port.serial_in = p->serial_in;
+ port.serial_out = p->serial_out;
+ port.handle_irq = p->handle_irq;
+ port.set_termios = p->set_termios;
+ port.pm = p->pm;
+ port.dev = &dev->dev;
+ port.irqflags |= irqflag;
+ ret = serial8250_register_port(&port);
+ if (ret < 0) {
+ dev_err(&dev->dev, "unable to register port at index %d "
+ "(IO%lx MEM%llx IRQ%d): %d\n", i,
+ p->iobase, (unsigned long long)p->mapbase,
+ p->irq, ret);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial8250_remove(struct platform_device *dev)
+{
+ int i;
+
+ for (i = 0; i < nr_uarts; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+
+ if (up->port.dev == &dev->dev)
+ serial8250_unregister_port(i);
+ }
+ return 0;
+}
+
+static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
+{
+ int i;
+
+ for (i = 0; i < UART_NR; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+
+ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+ uart_suspend_port(&serial8250_reg, &up->port);
+ }
+
+ return 0;
+}
+
+static int serial8250_resume(struct platform_device *dev)
+{
+ int i;
+
+ for (i = 0; i < UART_NR; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+
+ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+ serial8250_resume_port(i);
+ }
+
+ return 0;
+}
+
+static struct platform_driver serial8250_isa_driver = {
+ .probe = serial8250_probe,
+ .remove = __devexit_p(serial8250_remove),
+ .suspend = serial8250_suspend,
+ .resume = serial8250_resume,
+ .driver = {
+ .name = "serial8250",
+ .owner = THIS_MODULE,
+ },
+};
+
+/*
+ * This "device" covers _all_ ISA 8250-compatible serial devices listed
+ * in the table in include/asm/serial.h
+ */
+static struct platform_device *serial8250_isa_devs;
+
+/*
+ * serial8250_register_port and serial8250_unregister_port allows for
+ * 16x50 serial ports to be configured at run-time, to support PCMCIA
+ * modems and PCI multiport cards.
+ */
+static DEFINE_MUTEX(serial_mutex);
+
+static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
+{
+ int i;
+
+ /*
+ * First, find a port entry which matches.
+ */
+ for (i = 0; i < nr_uarts; i++)
+ if (uart_match_port(&serial8250_ports[i].port, port))
+ return &serial8250_ports[i];
+
+ /*
+ * We didn't find a matching entry, so look for the first
+ * free entry. We look for one which hasn't been previously
+ * used (indicated by zero iobase).
+ */
+ for (i = 0; i < nr_uarts; i++)
+ if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
+ serial8250_ports[i].port.iobase == 0)
+ return &serial8250_ports[i];
+
+ /*
+ * That also failed. Last resort is to find any entry which
+ * doesn't have a real port associated with it.
+ */
+ for (i = 0; i < nr_uarts; i++)
+ if (serial8250_ports[i].port.type == PORT_UNKNOWN)
+ return &serial8250_ports[i];
+
+ return NULL;
+}
+
+/**
+ * serial8250_register_port - register a serial port
+ * @port: serial port template
+ *
+ * Configure the serial port specified by the request. If the
+ * port exists and is in use, it is hung up and unregistered
+ * first.
+ *
+ * The port is then probed and if necessary the IRQ is autodetected
+ * If this fails an error is returned.
+ *
+ * On success the port is ready to use and the line number is returned.
+ */
+int serial8250_register_port(struct uart_port *port)
+{
+ struct uart_8250_port *uart;
+ int ret = -ENOSPC;
+
+ if (port->uartclk == 0)
+ return -EINVAL;
+
+ mutex_lock(&serial_mutex);
+
+ uart = serial8250_find_match_or_unused(port);
+ if (uart) {
+ uart_remove_one_port(&serial8250_reg, &uart->port);
+
+ uart->port.iobase = port->iobase;
+ uart->port.membase = port->membase;
+ uart->port.irq = port->irq;
+ uart->port.irqflags = port->irqflags;
+ uart->port.uartclk = port->uartclk;
+ uart->port.fifosize = port->fifosize;
+ uart->port.regshift = port->regshift;
+ uart->port.iotype = port->iotype;
+ uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
+ uart->port.mapbase = port->mapbase;
+ uart->port.private_data = port->private_data;
+ if (port->dev)
+ uart->port.dev = port->dev;
+
+ if (port->flags & UPF_FIXED_TYPE)
+ serial8250_init_fixed_type_port(uart, port->type);
+
+ set_io_from_upio(&uart->port);
+ /* Possibly override default I/O functions. */
+ if (port->serial_in)
+ uart->port.serial_in = port->serial_in;
+ if (port->serial_out)
+ uart->port.serial_out = port->serial_out;
+ if (port->handle_irq)
+ uart->port.handle_irq = port->handle_irq;
+ /* Possibly override set_termios call */
+ if (port->set_termios)
+ uart->port.set_termios = port->set_termios;
+ if (port->pm)
+ uart->port.pm = port->pm;
+
+ if (serial8250_isa_config != NULL)
+ serial8250_isa_config(0, &uart->port,
+ &uart->capabilities);
+
+ ret = uart_add_one_port(&serial8250_reg, &uart->port);
+ if (ret == 0)
+ ret = uart->port.line;
+ }
+ mutex_unlock(&serial_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(serial8250_register_port);
+
+/**
+ * serial8250_unregister_port - remove a 16x50 serial port at runtime
+ * @line: serial line number
+ *
+ * Remove one serial port. This may not be called from interrupt
+ * context. We hand the port back to the our control.
+ */
+void serial8250_unregister_port(int line)
+{
+ struct uart_8250_port *uart = &serial8250_ports[line];
+
+ mutex_lock(&serial_mutex);
+ uart_remove_one_port(&serial8250_reg, &uart->port);
+ if (serial8250_isa_devs) {
+ uart->port.flags &= ~UPF_BOOT_AUTOCONF;
+ uart->port.type = PORT_UNKNOWN;
+ uart->port.dev = &serial8250_isa_devs->dev;
+ uart->capabilities = uart_config[uart->port.type].flags;
+ uart_add_one_port(&serial8250_reg, &uart->port);
+ } else {
+ uart->port.dev = NULL;
+ }
+ mutex_unlock(&serial_mutex);
+}
+EXPORT_SYMBOL(serial8250_unregister_port);
+
+static int __init serial8250_init(void)
+{
+ int ret;
+
+ if (nr_uarts > UART_NR)
+ nr_uarts = UART_NR;
+
+ printk(KERN_INFO "Serial: 8250/16550 driver, "
+ "%d ports, IRQ sharing %sabled\n", nr_uarts,
+ share_irqs ? "en" : "dis");
+
+#ifdef CONFIG_SPARC
+ ret = sunserial_register_minors(&serial8250_reg, UART_NR);
+#else
+ serial8250_reg.nr = UART_NR;
+ ret = uart_register_driver(&serial8250_reg);
+#endif
+ if (ret)
+ goto out;
+
+ serial8250_isa_devs = platform_device_alloc("serial8250",
+ PLAT8250_DEV_LEGACY);
+ if (!serial8250_isa_devs) {
+ ret = -ENOMEM;
+ goto unreg_uart_drv;
+ }
+
+ ret = platform_device_add(serial8250_isa_devs);
+ if (ret)
+ goto put_dev;
+
+ serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
+
+ ret = platform_driver_register(&serial8250_isa_driver);
+ if (ret == 0)
+ goto out;
+
+ platform_device_del(serial8250_isa_devs);
+put_dev:
+ platform_device_put(serial8250_isa_devs);
+unreg_uart_drv:
+#ifdef CONFIG_SPARC
+ sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
+ uart_unregister_driver(&serial8250_reg);
+#endif
+out:
+ return ret;
+}
+
+static void __exit serial8250_exit(void)
+{
+ struct platform_device *isa_dev = serial8250_isa_devs;
+
+ /*
+ * This tells serial8250_unregister_port() not to re-register
+ * the ports (thereby making serial8250_isa_driver permanently
+ * in use.)
+ */
+ serial8250_isa_devs = NULL;
+
+ platform_driver_unregister(&serial8250_isa_driver);
+ platform_device_unregister(isa_dev);
+
+#ifdef CONFIG_SPARC
+ sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
+ uart_unregister_driver(&serial8250_reg);
+#endif
+}
+
+module_init(serial8250_init);
+module_exit(serial8250_exit);
+
+EXPORT_SYMBOL(serial8250_suspend_port);
+EXPORT_SYMBOL(serial8250_resume_port);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
+
+module_param(share_irqs, uint, 0644);
+MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
+ " (unsafe)");
+
+module_param(nr_uarts, uint, 0644);
+MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+
+module_param(skip_txen_test, uint, 0644);
+MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
+
+#ifdef CONFIG_SERIAL_8250_RSA
+module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
+MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
+#endif
+MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
--- /dev/null
+/*
+ * Driver for 8250/16550-type serial ports
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * Copyright (C) 2001 Russell King.
+ *
+ * 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.
+ */
+
+#include <linux/serial_8250.h>
+
+struct uart_8250_port {
+ struct uart_port port;
+ struct timer_list timer; /* "no irq" timer */
+ struct list_head list; /* ports on this IRQ */
+ unsigned short capabilities; /* port capabilities */
+ unsigned short bugs; /* port bugs */
+ unsigned int tx_loadsz; /* transmit fifo load size */
+ unsigned char acr;
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char mcr_mask; /* mask of user bits */
+ unsigned char mcr_force; /* mask of forced bits */
+ unsigned char cur_iotype; /* Running I/O type */
+
+ /*
+ * Some bits in registers are cleared on a read, so they must
+ * be saved whenever the register is read but the bits will not
+ * be immediately processed.
+ */
+#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
+ unsigned char lsr_saved_flags;
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+};
+
+struct old_serial_port {
+ unsigned int uart;
+ unsigned int baud_base;
+ unsigned int port;
+ unsigned int irq;
+ unsigned int flags;
+ unsigned char hub6;
+ unsigned char io_type;
+ unsigned char *iomem_base;
+ unsigned short iomem_reg_shift;
+ unsigned long irqflags;
+};
+
+/*
+ * This replaces serial_uart_config in include/linux/serial.h
+ */
+struct serial8250_config {
+ const char *name;
+ unsigned short fifo_size;
+ unsigned short tx_loadsz;
+ unsigned char fcr;
+ unsigned int flags;
+};
+
+#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */
+#define UART_CAP_EFR (1 << 9) /* UART has EFR */
+#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
+#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
+#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
+#define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */
+
+#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
+#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
+#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
+#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
+
+#define PROBE_RSA (1 << 0)
+#define PROBE_ANY (~0)
+
+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+
+#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
+#define SERIAL8250_SHARE_IRQS 1
+#else
+#define SERIAL8250_SHARE_IRQS 0
+#endif
+
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+/*
+ * Digital did something really horribly wrong with the OUT1 and OUT2
+ * lines on at least some ALPHA's. The failure mode is that if either
+ * is cleared, the machine locks up with endless interrupts.
+ */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
+#elif defined(CONFIG_SBC8560)
+/*
+ * WindRiver did something similarly broken on their SBC8560 board. The
+ * UART tristates its IRQ output while OUT2 is clear, but they pulled
+ * the interrupt line _up_ instead of down, so if we register the IRQ
+ * while the UART is in that state, we die in an IRQ storm. */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
+#else
+#define ALPHA_KLUDGE_MCR 0
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2005 Russell King.
+ * Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq) \
+ { \
+ .iobase = _base, \
+ .irq = _irq, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ }
+
+static struct plat_serial8250_port accent_data[] = {
+ PORT(0x330, 4),
+ PORT(0x338, 4),
+ { },
+};
+
+static struct platform_device accent_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_ACCENT,
+ .dev = {
+ .platform_data = accent_data,
+ },
+};
+
+static int __init accent_init(void)
+{
+ return platform_device_register(&accent_device);
+}
+
+module_init(accent_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for Accent Async cards");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * linux/drivers/serial/acorn.c
+ *
+ * Copyright (C) 1996-2003 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/ecard.h>
+#include <asm/string.h>
+
+#include "8250.h"
+
+#define MAX_PORTS 3
+
+struct serial_card_type {
+ unsigned int num_ports;
+ unsigned int uartclk;
+ unsigned int type;
+ unsigned int offset[MAX_PORTS];
+};
+
+struct serial_card_info {
+ unsigned int num_ports;
+ int ports[MAX_PORTS];
+ void __iomem *vaddr;
+};
+
+static int __devinit
+serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+ struct serial_card_info *info;
+ struct serial_card_type *type = id->data;
+ struct uart_port port;
+ unsigned long bus_addr;
+ unsigned int i;
+
+ info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->num_ports = type->num_ports;
+
+ bus_addr = ecard_resource_start(ec, type->type);
+ info->vaddr = ecardm_iomap(ec, type->type, 0, 0);
+ if (!info->vaddr) {
+ kfree(info);
+ return -ENOMEM;
+ }
+
+ ecard_set_drvdata(ec, info);
+
+ memset(&port, 0, sizeof(struct uart_port));
+ port.irq = ec->irq;
+ port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ port.uartclk = type->uartclk;
+ port.iotype = UPIO_MEM;
+ port.regshift = 2;
+ port.dev = &ec->dev;
+
+ for (i = 0; i < info->num_ports; i ++) {
+ port.membase = info->vaddr + type->offset[i];
+ port.mapbase = bus_addr + type->offset[i];
+
+ info->ports[i] = serial8250_register_port(&port);
+ }
+
+ return 0;
+}
+
+static void __devexit serial_card_remove(struct expansion_card *ec)
+{
+ struct serial_card_info *info = ecard_get_drvdata(ec);
+ int i;
+
+ ecard_set_drvdata(ec, NULL);
+
+ for (i = 0; i < info->num_ports; i++)
+ if (info->ports[i] > 0)
+ serial8250_unregister_port(info->ports[i]);
+
+ kfree(info);
+}
+
+static struct serial_card_type atomwide_type = {
+ .num_ports = 3,
+ .uartclk = 7372800,
+ .type = ECARD_RES_IOCSLOW,
+ .offset = { 0x2800, 0x2400, 0x2000 },
+};
+
+static struct serial_card_type serport_type = {
+ .num_ports = 2,
+ .uartclk = 3686400,
+ .type = ECARD_RES_IOCSLOW,
+ .offset = { 0x2000, 0x2020 },
+};
+
+static const struct ecard_id serial_cids[] = {
+ { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, &atomwide_type },
+ { MANU_SERPORT, PROD_SERPORT_DSPORT, &serport_type },
+ { 0xffff, 0xffff }
+};
+
+static struct ecard_driver serial_card_driver = {
+ .probe = serial_card_probe,
+ .remove = __devexit_p(serial_card_remove),
+ .id_table = serial_cids,
+ .drv = {
+ .name = "8250_acorn",
+ },
+};
+
+static int __init serial_card_init(void)
+{
+ return ecard_register_driver(&serial_card_driver);
+}
+
+static void __exit serial_card_exit(void)
+{
+ ecard_remove_driver(&serial_card_driver);
+}
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
+MODULE_LICENSE("GPL");
+
+module_init(serial_card_init);
+module_exit(serial_card_exit);
--- /dev/null
+/*
+ * Copyright (C) 2005 Russell King.
+ * Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq) \
+ { \
+ .iobase = _base, \
+ .irq = _irq, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ }
+
+static struct plat_serial8250_port boca_data[] = {
+ PORT(0x100, 12),
+ PORT(0x108, 12),
+ PORT(0x110, 12),
+ PORT(0x118, 12),
+ PORT(0x120, 12),
+ PORT(0x128, 12),
+ PORT(0x130, 12),
+ PORT(0x138, 12),
+ PORT(0x140, 12),
+ PORT(0x148, 12),
+ PORT(0x150, 12),
+ PORT(0x158, 12),
+ PORT(0x160, 12),
+ PORT(0x168, 12),
+ PORT(0x170, 12),
+ PORT(0x178, 12),
+ { },
+};
+
+static struct platform_device boca_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_BOCA,
+ .dev = {
+ .platform_data = boca_data,
+ },
+};
+
+static int __init boca_init(void)
+{
+ return platform_device_register(&boca_device);
+}
+
+module_init(boca_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for Boca cards");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Synopsys DesignWare 8250 driver.
+ *
+ * Copyright 2011 Picochip, Jamie Iles.
+ *
+ * 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.
+ *
+ * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
+ * LCR is written whilst busy. If it is, then a busy detect interrupt is
+ * raised, the LCR needs to be rewritten and the uart status register read.
+ */
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct dw8250_data {
+ int last_lcr;
+ int line;
+};
+
+static void dw8250_serial_out(struct uart_port *p, int offset, int value)
+{
+ struct dw8250_data *d = p->private_data;
+
+ if (offset == UART_LCR)
+ d->last_lcr = value;
+
+ offset <<= p->regshift;
+ writeb(value, p->membase + offset);
+}
+
+static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
+{
+ offset <<= p->regshift;
+
+ return readb(p->membase + offset);
+}
+
+static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
+{
+ struct dw8250_data *d = p->private_data;
+
+ if (offset == UART_LCR)
+ d->last_lcr = value;
+
+ offset <<= p->regshift;
+ writel(value, p->membase + offset);
+}
+
+static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
+{
+ offset <<= p->regshift;
+
+ return readl(p->membase + offset);
+}
+
+/* Offset for the DesignWare's UART Status Register. */
+#define UART_USR 0x1f
+
+static int dw8250_handle_irq(struct uart_port *p)
+{
+ struct dw8250_data *d = p->private_data;
+ unsigned int iir = p->serial_in(p, UART_IIR);
+
+ if (serial8250_handle_irq(p, iir)) {
+ return 1;
+ } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+ /* Clear the USR and write the LCR again. */
+ (void)p->serial_in(p, UART_USR);
+ p->serial_out(p, d->last_lcr, UART_LCR);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int __devinit dw8250_probe(struct platform_device *pdev)
+{
+ struct uart_port port = {};
+ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ struct device_node *np = pdev->dev.of_node;
+ u32 val;
+ struct dw8250_data *data;
+
+ if (!regs || !irq) {
+ dev_err(&pdev->dev, "no registers/irq defined\n");
+ return -EINVAL;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ port.private_data = data;
+
+ spin_lock_init(&port.lock);
+ port.mapbase = regs->start;
+ port.irq = irq->start;
+ port.handle_irq = dw8250_handle_irq;
+ port.type = PORT_8250;
+ port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+ UPF_FIXED_PORT | UPF_FIXED_TYPE;
+ port.dev = &pdev->dev;
+
+ port.iotype = UPIO_MEM;
+ port.serial_in = dw8250_serial_in;
+ port.serial_out = dw8250_serial_out;
+ if (!of_property_read_u32(np, "reg-io-width", &val)) {
+ switch (val) {
+ case 1:
+ break;
+ case 4:
+ port.iotype = UPIO_MEM32;
+ port.serial_in = dw8250_serial_in32;
+ port.serial_out = dw8250_serial_out32;
+ break;
+ default:
+ dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
+ val);
+ return -EINVAL;
+ }
+ }
+
+ if (!of_property_read_u32(np, "reg-shift", &val))
+ port.regshift = val;
+
+ if (of_property_read_u32(np, "clock-frequency", &val)) {
+ dev_err(&pdev->dev, "no clock-frequency property set\n");
+ return -EINVAL;
+ }
+ port.uartclk = val;
+
+ data->line = serial8250_register_port(&port);
+ if (data->line < 0)
+ return data->line;
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int __devexit dw8250_remove(struct platform_device *pdev)
+{
+ struct dw8250_data *data = platform_get_drvdata(pdev);
+
+ serial8250_unregister_port(data->line);
+
+ return 0;
+}
+
+static const struct of_device_id dw8250_match[] = {
+ { .compatible = "snps,dw-apb-uart" },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dw8250_match);
+
+static struct platform_driver dw8250_platform_driver = {
+ .driver = {
+ .name = "dw-apb-uart",
+ .owner = THIS_MODULE,
+ .of_match_table = dw8250_match,
+ },
+ .probe = dw8250_probe,
+ .remove = __devexit_p(dw8250_remove),
+};
+
+module_platform_driver(dw8250_platform_driver);
+
+MODULE_AUTHOR("Jamie Iles");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
--- /dev/null
+/*
+ * Early serial console for 8250/16550 devices
+ *
+ * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
+ * and on early_printk.c by Andi Kleen.
+ *
+ * This is for use before the serial driver has initialized, in
+ * particular, before the UARTs have been discovered and named.
+ * Instead of specifying the console device as, e.g., "ttyS0",
+ * we locate the device directly by its MMIO or I/O port address.
+ *
+ * The user can specify the device directly, e.g.,
+ * earlycon=uart8250,io,0x3f8,9600n8
+ * earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * earlycon=uart8250,mmio32,0xff5e0000,115200n8
+ * or
+ * console=uart8250,io,0x3f8,9600n8
+ * console=uart8250,mmio,0xff5e0000,115200n8
+ * console=uart8250,mmio32,0xff5e0000,115200n8
+ */
+
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <asm/io.h>
+#include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
+
+struct early_serial8250_device {
+ struct uart_port port;
+ char options[16]; /* e.g., 115200n8 */
+ unsigned int baud;
+};
+
+static struct early_serial8250_device early_device;
+
+static unsigned int __init serial_in(struct uart_port *port, int offset)
+{
+ switch (port->iotype) {
+ case UPIO_MEM:
+ return readb(port->membase + offset);
+ case UPIO_MEM32:
+ return readl(port->membase + (offset << 2));
+ case UPIO_PORT:
+ return inb(port->iobase + offset);
+ default:
+ return 0;
+ }
+}
+
+static void __init serial_out(struct uart_port *port, int offset, int value)
+{
+ switch (port->iotype) {
+ case UPIO_MEM:
+ writeb(value, port->membase + offset);
+ break;
+ case UPIO_MEM32:
+ writel(value, port->membase + (offset << 2));
+ break;
+ case UPIO_PORT:
+ outb(value, port->iobase + offset);
+ break;
+ }
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void __init wait_for_xmitr(struct uart_port *port)
+{
+ unsigned int status;
+
+ for (;;) {
+ status = serial_in(port, UART_LSR);
+ if ((status & BOTH_EMPTY) == BOTH_EMPTY)
+ return;
+ cpu_relax();
+ }
+}
+
+static void __init serial_putc(struct uart_port *port, int c)
+{
+ wait_for_xmitr(port);
+ serial_out(port, UART_TX, c);
+}
+
+static void __init early_serial8250_write(struct console *console,
+ const char *s, unsigned int count)
+{
+ struct uart_port *port = &early_device.port;
+ unsigned int ier;
+
+ /* Save the IER and disable interrupts */
+ ier = serial_in(port, UART_IER);
+ serial_out(port, UART_IER, 0);
+
+ uart_console_write(port, s, count, serial_putc);
+
+ /* Wait for transmitter to become empty and restore the IER */
+ wait_for_xmitr(port);
+ serial_out(port, UART_IER, ier);
+}
+
+static unsigned int __init probe_baud(struct uart_port *port)
+{
+ unsigned char lcr, dll, dlm;
+ unsigned int quot;
+
+ lcr = serial_in(port, UART_LCR);
+ serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+ dll = serial_in(port, UART_DLL);
+ dlm = serial_in(port, UART_DLM);
+ serial_out(port, UART_LCR, lcr);
+
+ quot = (dlm << 8) | dll;
+ return (port->uartclk / 16) / quot;
+}
+
+static void __init init_port(struct early_serial8250_device *device)
+{
+ struct uart_port *port = &device->port;
+ unsigned int divisor;
+ unsigned char c;
+
+ serial_out(port, UART_LCR, 0x3); /* 8n1 */
+ serial_out(port, UART_IER, 0); /* no interrupt */
+ serial_out(port, UART_FCR, 0); /* no fifo */
+ serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
+
+ divisor = port->uartclk / (16 * device->baud);
+ c = serial_in(port, UART_LCR);
+ serial_out(port, UART_LCR, c | UART_LCR_DLAB);
+ serial_out(port, UART_DLL, divisor & 0xff);
+ serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
+ serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
+}
+
+static int __init parse_options(struct early_serial8250_device *device,
+ char *options)
+{
+ struct uart_port *port = &device->port;
+ int mmio, mmio32, length;
+
+ if (!options)
+ return -ENODEV;
+
+ port->uartclk = BASE_BAUD * 16;
+
+ mmio = !strncmp(options, "mmio,", 5);
+ mmio32 = !strncmp(options, "mmio32,", 7);
+ if (mmio || mmio32) {
+ port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
+ port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
+ &options, 0);
+ if (mmio32)
+ port->regshift = 2;
+#ifdef CONFIG_FIX_EARLYCON_MEM
+ set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
+ port->mapbase & PAGE_MASK);
+ port->membase =
+ (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+ port->membase += port->mapbase & ~PAGE_MASK;
+#else
+ port->membase = ioremap_nocache(port->mapbase, 64);
+ if (!port->membase) {
+ printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
+ __func__,
+ (unsigned long long) port->mapbase);
+ return -ENOMEM;
+ }
+#endif
+ } else if (!strncmp(options, "io,", 3)) {
+ port->iotype = UPIO_PORT;
+ port->iobase = simple_strtoul(options + 3, &options, 0);
+ mmio = 0;
+ } else
+ return -EINVAL;
+
+ options = strchr(options, ',');
+ if (options) {
+ options++;
+ device->baud = simple_strtoul(options, NULL, 0);
+ length = min(strcspn(options, " "), sizeof(device->options));
+ strncpy(device->options, options, length);
+ } else {
+ device->baud = probe_baud(port);
+ snprintf(device->options, sizeof(device->options), "%u",
+ device->baud);
+ }
+
+ if (mmio || mmio32)
+ printk(KERN_INFO
+ "Early serial console at MMIO%s 0x%llx (options '%s')\n",
+ mmio32 ? "32" : "",
+ (unsigned long long)port->mapbase,
+ device->options);
+ else
+ printk(KERN_INFO
+ "Early serial console at I/O port 0x%lx (options '%s')\n",
+ port->iobase,
+ device->options);
+
+ return 0;
+}
+
+static struct console early_serial8250_console __initdata = {
+ .name = "uart",
+ .write = early_serial8250_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+ .index = -1,
+};
+
+static int __init early_serial8250_setup(char *options)
+{
+ struct early_serial8250_device *device = &early_device;
+ int err;
+
+ if (device->port.membase || device->port.iobase)
+ return 0;
+
+ err = parse_options(device, options);
+ if (err < 0)
+ return err;
+
+ init_port(device);
+ return 0;
+}
+
+int __init setup_early_serial8250_console(char *cmdline)
+{
+ char *options;
+ int err;
+
+ options = strstr(cmdline, "uart8250,");
+ if (!options) {
+ options = strstr(cmdline, "uart,");
+ if (!options)
+ return 0;
+ }
+
+ options = strchr(cmdline, ',') + 1;
+ err = early_serial8250_setup(options);
+ if (err < 0)
+ return err;
+
+ register_console(&early_serial8250_console);
+
+ return 0;
+}
+
+int serial8250_find_port_for_earlycon(void)
+{
+ struct early_serial8250_device *device = &early_device;
+ struct uart_port *port = &device->port;
+ int line;
+ int ret;
+
+ if (!device->port.membase && !device->port.iobase)
+ return -ENODEV;
+
+ line = serial8250_find_port(port);
+ if (line < 0)
+ return -ENODEV;
+
+ ret = update_console_cmdline("uart", 8250,
+ "ttyS", line, device->options);
+ if (ret < 0)
+ ret = update_console_cmdline("uart", 0,
+ "ttyS", line, device->options);
+
+ return ret;
+}
+
+early_param("earlycon", setup_early_serial8250_console);
--- /dev/null
+/*
+ * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
+ * Based on 8250_boca.
+ *
+ * Copyright (C) 2005 Russell King.
+ * Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq) \
+ { \
+ .iobase = _base, \
+ .irq = _irq, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ }
+
+static struct plat_serial8250_port exar_data[] = {
+ PORT(0x100, 5),
+ PORT(0x108, 5),
+ PORT(0x110, 5),
+ PORT(0x118, 5),
+ { },
+};
+
+static struct platform_device exar_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_EXAR_ST16C554,
+ .dev = {
+ .platform_data = exar_data,
+ },
+};
+
+static int __init exar_init(void)
+{
+ return platform_device_register(&exar_device);
+}
+
+module_init(exar_init);
+
+MODULE_AUTHOR("Paul B Schroeder");
+MODULE_DESCRIPTION("8250 serial probe module for Exar cards");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Copyright (C) 2005 Russell King.
+ * Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq) \
+ { \
+ .iobase = _base, \
+ .irq = _irq, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \
+ }
+
+static struct plat_serial8250_port fourport_data[] = {
+ PORT(0x1a0, 9),
+ PORT(0x1a8, 9),
+ PORT(0x1b0, 9),
+ PORT(0x1b8, 9),
+ PORT(0x2a0, 5),
+ PORT(0x2a8, 5),
+ PORT(0x2b0, 5),
+ PORT(0x2b8, 5),
+ { },
+};
+
+static struct platform_device fourport_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_FOURPORT,
+ .dev = {
+ .platform_data = fourport_data,
+ },
+};
+
+static int __init fourport_init(void)
+{
+ return platform_device_register(&fourport_device);
+}
+
+module_init(fourport_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for AST Fourport cards");
+MODULE_LICENSE("GPL");
--- /dev/null
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
+
+#include "8250.h"
+
+/*
+ * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This isn't a full driver; it just provides an alternate IRQ
+ * handler to deal with an errata. Everything else is just
+ * using the bog standard 8250 support.
+ *
+ * We follow code flow of serial8250_default_handle_irq() but add
+ * a check for a break and insert a dummy read on the Rx for the
+ * immediately following IRQ event.
+ *
+ * We re-use the already existing "bug handling" lsr_saved_flags
+ * field to carry the "what we just did" information from the one
+ * IRQ event to the next one.
+ */
+
+int fsl8250_handle_irq(struct uart_port *port)
+{
+ unsigned char lsr, orig_lsr;
+ unsigned long flags;
+ unsigned int iir;
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ iir = port->serial_in(port, UART_IIR);
+ if (iir & UART_IIR_NO_INT) {
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 0;
+ }
+
+ /* This is the WAR; if last event was BRK, then read and return */
+ if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
+ up->lsr_saved_flags &= ~UART_LSR_BI;
+ port->serial_in(port, UART_RX);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 1;
+ }
+
+ lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR);
+
+ if (lsr & (UART_LSR_DR | UART_LSR_BI))
+ lsr = serial8250_rx_chars(up, lsr);
+
+ serial8250_modem_status(up);
+
+ if (lsr & UART_LSR_THRE)
+ serial8250_tx_chars(up);
+
+ up->lsr_saved_flags = orig_lsr;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 1;
+}
--- /dev/null
+/*
+ * Serial Device Initialisation for Lasi/Asp/Wax/Dino
+ *
+ * (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/serial_core.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+
+#include <asm/hardware.h>
+#include <asm/parisc-device.h>
+#include <asm/io.h>
+
+#include "8250.h"
+
+static int __init serial_init_chip(struct parisc_device *dev)
+{
+ struct uart_port port;
+ unsigned long address;
+ int err;
+
+ if (!dev->irq) {
+ /* We find some unattached serial ports by walking native
+ * busses. These should be silently ignored. Otherwise,
+ * what we have here is a missing parent device, so tell
+ * the user what they're missing.
+ */
+ if (parisc_parent(dev)->id.hw_type != HPHW_IOA)
+ printk(KERN_INFO
+ "Serial: device 0x%llx not configured.\n"
+ "Enable support for Wax, Lasi, Asp or Dino.\n",
+ (unsigned long long)dev->hpa.start);
+ return -ENODEV;
+ }
+
+ address = dev->hpa.start;
+ if (dev->id.sversion != 0x8d)
+ address += 0x800;
+
+ memset(&port, 0, sizeof(port));
+ port.iotype = UPIO_MEM;
+ /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
+ port.uartclk = 7272727;
+ port.mapbase = address;
+ port.membase = ioremap_nocache(address, 16);
+ port.irq = dev->irq;
+ port.flags = UPF_BOOT_AUTOCONF;
+ port.dev = &dev->dev;
+
+ err = serial8250_register_port(&port);
+ if (err < 0) {
+ printk(KERN_WARNING
+ "serial8250_register_port returned error %d\n", err);
+ iounmap(port.membase);
+ return err;
+ }
+
+ return 0;
+}
+
+static struct parisc_device_id serial_tbl[] = {
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 },
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c },
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d },
+ { 0 }
+};
+
+/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1
+ * attached to Dino. Unfortunately, Dino appears before Lasi in the device
+ * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one
+ * which only knows about Lasi and then a second which will find all the
+ * other serial ports. HPUX ignores this problem.
+ */
+static struct parisc_device_id lasi_tbl[] = {
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */
+ { 0 }
+};
+
+
+MODULE_DEVICE_TABLE(parisc, serial_tbl);
+
+static struct parisc_driver lasi_driver = {
+ .name = "serial_1",
+ .id_table = lasi_tbl,
+ .probe = serial_init_chip,
+};
+
+static struct parisc_driver serial_driver = {
+ .name = "serial",
+ .id_table = serial_tbl,
+ .probe = serial_init_chip,
+};
+
+static int __init probe_serial_gsc(void)
+{
+ register_parisc_driver(&lasi_driver);
+ register_parisc_driver(&serial_driver);
+ return 0;
+}
+
+module_init(probe_serial_gsc);
+
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Driver for the 98626/98644/internal serial interface on hp300/hp400
+ * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
+ *
+ * Ported from 2.2 and modified to use the normal 8250 driver
+ * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/delay.h>
+#include <linux/dio.h>
+#include <linux/console.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#include "8250.h"
+
+#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
+#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
+#endif
+
+#ifdef CONFIG_HPAPCI
+struct hp300_port
+{
+ struct hp300_port *next; /* next port */
+ int line; /* line (tty) number */
+};
+
+static struct hp300_port *hp300_ports;
+#endif
+
+#ifdef CONFIG_HPDCA
+
+static int __devinit hpdca_init_one(struct dio_dev *d,
+ const struct dio_device_id *ent);
+static void __devexit hpdca_remove_one(struct dio_dev *d);
+
+static struct dio_device_id hpdca_dio_tbl[] = {
+ { DIO_ID_DCA0 },
+ { DIO_ID_DCA0REM },
+ { DIO_ID_DCA1 },
+ { DIO_ID_DCA1REM },
+ { 0 }
+};
+
+static struct dio_driver hpdca_driver = {
+ .name = "hpdca",
+ .id_table = hpdca_dio_tbl,
+ .probe = hpdca_init_one,
+ .remove = __devexit_p(hpdca_remove_one),
+};
+
+#endif
+
+static unsigned int num_ports;
+
+extern int hp300_uart_scode;
+
+/* Offset to UART registers from base of DCA */
+#define UART_OFFSET 17
+
+#define DCA_ID 0x01 /* ID (read), reset (write) */
+#define DCA_IC 0x03 /* Interrupt control */
+
+/* Interrupt control */
+#define DCA_IC_IE 0x80 /* Master interrupt enable */
+
+#define HPDCA_BAUD_BASE 153600
+
+/* Base address of the Frodo part */
+#define FRODO_BASE (0x41c000)
+
+/*
+ * Where we find the 8250-like APCI ports, and how far apart they are.
+ */
+#define FRODO_APCIBASE 0x0
+#define FRODO_APCISPACE 0x20
+#define FRODO_APCI_OFFSET(x) (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
+
+#define HPAPCI_BAUD_BASE 500400
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+/*
+ * Parse the bootinfo to find descriptions for headless console and
+ * debug serial ports and register them with the 8250 driver.
+ * This function should be called before serial_console_init() is called
+ * to make sure the serial console will be available for use. IA-64 kernel
+ * calls this function from setup_arch() after the EFI and ACPI tables have
+ * been parsed.
+ */
+int __init hp300_setup_serial_console(void)
+{
+ int scode;
+ struct uart_port port;
+
+ memset(&port, 0, sizeof(port));
+
+ if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
+ return 0;
+
+ if (DIO_SCINHOLE(hp300_uart_scode))
+ return 0;
+
+ scode = hp300_uart_scode;
+
+ /* Memory mapped I/O */
+ port.iotype = UPIO_MEM;
+ port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+ port.type = PORT_UNKNOWN;
+
+ /* Check for APCI console */
+ if (scode == 256) {
+#ifdef CONFIG_HPAPCI
+ printk(KERN_INFO "Serial console is HP APCI 1\n");
+
+ port.uartclk = HPAPCI_BAUD_BASE * 16;
+ port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
+ port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+ port.regshift = 2;
+ add_preferred_console("ttyS", port.line, "9600n8");
+#else
+ printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
+ return 0;
+#endif
+ } else {
+#ifdef CONFIG_HPDCA
+ unsigned long pa = dio_scodetophysaddr(scode);
+ if (!pa)
+ return 0;
+
+ printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
+
+ port.uartclk = HPDCA_BAUD_BASE * 16;
+ port.mapbase = (pa + UART_OFFSET);
+ port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+ port.regshift = 1;
+ port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
+
+ /* Enable board-interrupts */
+ out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
+
+ if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
+ add_preferred_console("ttyS", port.line, "9600n8");
+#else
+ printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
+ return 0;
+#endif
+ }
+
+ if (early_serial_setup(&port) < 0)
+ printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
+ return 0;
+}
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+#ifdef CONFIG_HPDCA
+static int __devinit hpdca_init_one(struct dio_dev *d,
+ const struct dio_device_id *ent)
+{
+ struct uart_port port;
+ int line;
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ if (hp300_uart_scode == d->scode) {
+ /* Already got it. */
+ return 0;
+ }
+#endif
+ memset(&port, 0, sizeof(struct uart_port));
+
+ /* Memory mapped I/O */
+ port.iotype = UPIO_MEM;
+ port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+ port.irq = d->ipl;
+ port.uartclk = HPDCA_BAUD_BASE * 16;
+ port.mapbase = (d->resource.start + UART_OFFSET);
+ port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+ port.regshift = 1;
+ port.dev = &d->dev;
+ line = serial8250_register_port(&port);
+
+ if (line < 0) {
+ printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
+ " irq %d failed\n", d->scode, port.irq);
+ return -ENOMEM;
+ }
+
+ /* Enable board-interrupts */
+ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
+ dio_set_drvdata(d, (void *)line);
+
+ /* Reset the DCA */
+ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
+ udelay(100);
+
+ num_ports++;
+
+ return 0;
+}
+#endif
+
+static int __init hp300_8250_init(void)
+{
+ static int called;
+#ifdef CONFIG_HPAPCI
+ int line;
+ unsigned long base;
+ struct uart_port uport;
+ struct hp300_port *port;
+ int i;
+#endif
+ if (called)
+ return -ENODEV;
+ called = 1;
+
+ if (!MACH_IS_HP300)
+ return -ENODEV;
+
+#ifdef CONFIG_HPDCA
+ dio_register_driver(&hpdca_driver);
+#endif
+#ifdef CONFIG_HPAPCI
+ if (hp300_model < HP_400) {
+ if (!num_ports)
+ return -ENODEV;
+ return 0;
+ }
+ /* These models have the Frodo chip.
+ * Port 0 is reserved for the Apollo Domain keyboard.
+ * Port 1 is either the console or the DCA.
+ */
+ for (i = 1; i < 4; i++) {
+ /* Port 1 is the console on a 425e, on other machines it's
+ * mapped to DCA.
+ */
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ if (i == 1)
+ continue;
+#endif
+
+ /* Create new serial device */
+ port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ memset(&uport, 0, sizeof(struct uart_port));
+
+ base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
+
+ /* Memory mapped I/O */
+ uport.iotype = UPIO_MEM;
+ uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
+ | UPF_BOOT_AUTOCONF;
+ /* XXX - no interrupt support yet */
+ uport.irq = 0;
+ uport.uartclk = HPAPCI_BAUD_BASE * 16;
+ uport.mapbase = base;
+ uport.membase = (char *)(base + DIO_VIRADDRBASE);
+ uport.regshift = 2;
+
+ line = serial8250_register_port(&uport);
+
+ if (line < 0) {
+ printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
+ " %d irq %d failed\n", i, uport.irq);
+ kfree(port);
+ continue;
+ }
+
+ port->line = line;
+ port->next = hp300_ports;
+ hp300_ports = port;
+
+ num_ports++;
+ }
+#endif
+
+ /* Any boards found? */
+ if (!num_ports)
+ return -ENODEV;
+
+ return 0;
+}
+
+#ifdef CONFIG_HPDCA
+static void __devexit hpdca_remove_one(struct dio_dev *d)
+{
+ int line;
+
+ line = (int) dio_get_drvdata(d);
+ if (d->resource.start) {
+ /* Disable board-interrupts */
+ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
+ }
+ serial8250_unregister_port(line);
+}
+#endif
+
+static void __exit hp300_8250_exit(void)
+{
+#ifdef CONFIG_HPAPCI
+ struct hp300_port *port, *to_free;
+
+ for (port = hp300_ports; port; ) {
+ serial8250_unregister_port(port->line);
+ to_free = port;
+ port = port->next;
+ kfree(to_free);
+ }
+
+ hp300_ports = NULL;
+#endif
+#ifdef CONFIG_HPDCA
+ dio_unregister_driver(&hpdca_driver);
+#endif
+}
+
+module_init(hp300_8250_init);
+module_exit(hp300_8250_exit);
+MODULE_DESCRIPTION("HP DCA/APCI serial driver");
+MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Copyright (C) 2005 Russell King.
+ * Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define HUB6(card,port) \
+ { \
+ .iobase = 0x302, \
+ .irq = 3, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_HUB6, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ .hub6 = (card) << 6 | (port) << 3 | 1, \
+ }
+
+static struct plat_serial8250_port hub6_data[] = {
+ HUB6(0, 0),
+ HUB6(0, 1),
+ HUB6(0, 2),
+ HUB6(0, 3),
+ HUB6(0, 4),
+ HUB6(0, 5),
+ HUB6(1, 0),
+ HUB6(1, 1),
+ HUB6(1, 2),
+ HUB6(1, 3),
+ HUB6(1, 4),
+ HUB6(1, 5),
+ { },
+};
+
+static struct platform_device hub6_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_HUB6,
+ .dev = {
+ .platform_data = hub6_data,
+ },
+};
+
+static int __init hub6_init(void)
+{
+ return platform_device_register(&hub6_device);
+}
+
+module_init(hub6_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for Hub6 cards");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Copyright (C) 2005 Russell King.
+ * Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mca.h>
+#include <linux/serial_8250.h>
+
+/*
+ * FIXME: Should we be doing AUTO_IRQ here?
+ */
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
+#define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ
+#else
+#define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
+#endif
+
+#define PORT(_base,_irq) \
+ { \
+ .iobase = _base, \
+ .irq = _irq, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = MCA_FLAGS, \
+ }
+
+static struct plat_serial8250_port mca_data[] = {
+ PORT(0x3220, 3),
+ PORT(0x3228, 3),
+ PORT(0x4220, 3),
+ PORT(0x4228, 3),
+ PORT(0x5220, 3),
+ PORT(0x5228, 3),
+ { },
+};
+
+static struct platform_device mca_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_MCA,
+ .dev = {
+ .platform_data = mca_data,
+ },
+};
+
+static int __init mca_init(void)
+{
+ if (!MCA_bus)
+ return -ENODEV;
+ return platform_device_register(&mca_device);
+}
+
+module_init(mca_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for MCA ports");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Probe module for 8250/16550-type PCI serial ports.
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/8250_pci.h>
+#include <linux/bitops.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include "8250.h"
+
+#undef SERIAL_DEBUG_PCI
+
+/*
+ * init function returns:
+ * > 0 - number of ports
+ * = 0 - use board->num_ports
+ * < 0 - error
+ */
+struct pci_serial_quirk {
+ u32 vendor;
+ u32 device;
+ u32 subvendor;
+ u32 subdevice;
+ int (*probe)(struct pci_dev *dev);
+ int (*init)(struct pci_dev *dev);
+ int (*setup)(struct serial_private *,
+ const struct pciserial_board *,
+ struct uart_port *, int);
+ void (*exit)(struct pci_dev *dev);
+};
+
+#define PCI_NUM_BAR_RESOURCES 6
+
+struct serial_private {
+ struct pci_dev *dev;
+ unsigned int nr;
+ void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES];
+ struct pci_serial_quirk *quirk;
+ int line[0];
+};
+
+static int pci_default_setup(struct serial_private*,
+ const struct pciserial_board*, struct uart_port*, int);
+
+static void moan_device(const char *str, struct pci_dev *dev)
+{
+ printk(KERN_WARNING
+ "%s: %s\n"
+ "Please send the output of lspci -vv, this\n"
+ "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+ "manufacturer and name of serial board or\n"
+ "modem board to rmk+serial@arm.linux.org.uk.\n",
+ pci_name(dev), str, dev->vendor, dev->device,
+ dev->subsystem_vendor, dev->subsystem_device);
+}
+
+static int
+setup_port(struct serial_private *priv, struct uart_port *port,
+ int bar, int offset, int regshift)
+{
+ struct pci_dev *dev = priv->dev;
+ unsigned long base, len;
+
+ if (bar >= PCI_NUM_BAR_RESOURCES)
+ return -EINVAL;
+
+ base = pci_resource_start(dev, bar);
+
+ if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
+ len = pci_resource_len(dev, bar);
+
+ if (!priv->remapped_bar[bar])
+ priv->remapped_bar[bar] = ioremap_nocache(base, len);
+ if (!priv->remapped_bar[bar])
+ return -ENOMEM;
+
+ port->iotype = UPIO_MEM;
+ port->iobase = 0;
+ port->mapbase = base + offset;
+ port->membase = priv->remapped_bar[bar] + offset;
+ port->regshift = regshift;
+ } else {
+ port->iotype = UPIO_PORT;
+ port->iobase = base + offset;
+ port->mapbase = 0;
+ port->membase = NULL;
+ port->regshift = 0;
+ }
+ return 0;
+}
+
+/*
+ * ADDI-DATA GmbH communication cards <info@addi-data.com>
+ */
+static int addidata_apci7800_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar = 0, offset = board->first_offset;
+ bar = FL_GET_BASE(board->flags);
+
+ if (idx < 2) {
+ offset += idx * board->uart_offset;
+ } else if ((idx >= 2) && (idx < 4)) {
+ bar += 1;
+ offset += ((idx - 2) * board->uart_offset);
+ } else if ((idx >= 4) && (idx < 6)) {
+ bar += 2;
+ offset += ((idx - 4) * board->uart_offset);
+ } else if (idx >= 6) {
+ bar += 3;
+ offset += ((idx - 6) * board->uart_offset);
+ }
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * AFAVLAB uses a different mixture of BARs and offsets
+ * Not that ugly ;) -- HW
+ */
+static int
+afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar, offset = board->first_offset;
+
+ bar = FL_GET_BASE(board->flags);
+ if (idx < 4)
+ bar += idx;
+ else {
+ bar = 4;
+ offset += (idx - 4) * board->uart_offset;
+ }
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * HP's Remote Management Console. The Diva chip came in several
+ * different versions. N-class, L2000 and A500 have two Diva chips, each
+ * with 3 UARTs (the third UART on the second chip is unused). Superdome
+ * and Keystone have one Diva chip with 3 UARTs. Some later machines have
+ * one Diva chip, but it has been expanded to 5 UARTs.
+ */
+static int pci_hp_diva_init(struct pci_dev *dev)
+{
+ int rc = 0;
+
+ switch (dev->subsystem_device) {
+ case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
+ case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
+ case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
+ case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+ rc = 3;
+ break;
+ case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
+ rc = 2;
+ break;
+ case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+ rc = 4;
+ break;
+ case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
+ case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
+ rc = 1;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * HP's Diva chip puts the 4th/5th serial port further out, and
+ * some serial ports are supposed to be hidden on certain models.
+ */
+static int
+pci_hp_diva_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int offset = board->first_offset;
+ unsigned int bar = FL_GET_BASE(board->flags);
+
+ switch (priv->dev->subsystem_device) {
+ case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+ if (idx == 3)
+ idx++;
+ break;
+ case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+ if (idx > 0)
+ idx++;
+ if (idx > 2)
+ idx++;
+ break;
+ }
+ if (idx > 2)
+ offset = 0x18;
+
+ offset += idx * board->uart_offset;
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * Added for EKF Intel i960 serial boards
+ */
+static int pci_inteli960ni_init(struct pci_dev *dev)
+{
+ unsigned long oldval;
+
+ if (!(dev->subsystem_device & 0x1000))
+ return -ENODEV;
+
+ /* is firmware started? */
+ pci_read_config_dword(dev, 0x44, (void *)&oldval);
+ if (oldval == 0x00001000L) { /* RESET value */
+ printk(KERN_DEBUG "Local i960 firmware missing");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+/*
+ * Some PCI serial cards using the PLX 9050 PCI interface chip require
+ * that the card interrupt be explicitly enabled or disabled. This
+ * seems to be mainly needed on card using the PLX which also use I/O
+ * mapped memory.
+ */
+static int pci_plx9050_init(struct pci_dev *dev)
+{
+ u8 irq_config;
+ void __iomem *p;
+
+ if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
+ moan_device("no memory in bar 0", dev);
+ return 0;
+ }
+
+ irq_config = 0x41;
+ if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
+ dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
+ irq_config = 0x43;
+
+ if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
+ (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
+ /*
+ * As the megawolf cards have the int pins active
+ * high, and have 2 UART chips, both ints must be
+ * enabled on the 9050. Also, the UARTS are set in
+ * 16450 mode by default, so we have to enable the
+ * 16C950 'enhanced' mode so that we can use the
+ * deep FIFOs
+ */
+ irq_config = 0x5b;
+ /*
+ * enable/disable interrupts
+ */
+ p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
+ if (p == NULL)
+ return -ENOMEM;
+ writel(irq_config, p + 0x4c);
+
+ /*
+ * Read the register back to ensure that it took effect.
+ */
+ readl(p + 0x4c);
+ iounmap(p);
+
+ return 0;
+}
+
+static void __devexit pci_plx9050_exit(struct pci_dev *dev)
+{
+ u8 __iomem *p;
+
+ if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
+ return;
+
+ /*
+ * disable interrupts
+ */
+ p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
+ if (p != NULL) {
+ writel(0, p + 0x4c);
+
+ /*
+ * Read the register back to ensure that it took effect.
+ */
+ readl(p + 0x4c);
+ iounmap(p);
+ }
+}
+
+#define NI8420_INT_ENABLE_REG 0x38
+#define NI8420_INT_ENABLE_BIT 0x2000
+
+static void __devexit pci_ni8420_exit(struct pci_dev *dev)
+{
+ void __iomem *p;
+ unsigned long base, len;
+ unsigned int bar = 0;
+
+ if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+ moan_device("no memory in bar", dev);
+ return;
+ }
+
+ base = pci_resource_start(dev, bar);
+ len = pci_resource_len(dev, bar);
+ p = ioremap_nocache(base, len);
+ if (p == NULL)
+ return;
+
+ /* Disable the CPU Interrupt */
+ writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT),
+ p + NI8420_INT_ENABLE_REG);
+ iounmap(p);
+}
+
+
+/* MITE registers */
+#define MITE_IOWBSR1 0xc4
+#define MITE_IOWCR1 0xf4
+#define MITE_LCIMR1 0x08
+#define MITE_LCIMR2 0x10
+
+#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
+
+static void __devexit pci_ni8430_exit(struct pci_dev *dev)
+{
+ void __iomem *p;
+ unsigned long base, len;
+ unsigned int bar = 0;
+
+ if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+ moan_device("no memory in bar", dev);
+ return;
+ }
+
+ base = pci_resource_start(dev, bar);
+ len = pci_resource_len(dev, bar);
+ p = ioremap_nocache(base, len);
+ if (p == NULL)
+ return;
+
+ /* Disable the CPU Interrupt */
+ writel(MITE_LCIMR2_CLR_CPU_IE, p + MITE_LCIMR2);
+ iounmap(p);
+}
+
+/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
+static int
+sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar, offset = board->first_offset;
+
+ bar = 0;
+
+ if (idx < 4) {
+ /* first four channels map to 0, 0x100, 0x200, 0x300 */
+ offset += idx * board->uart_offset;
+ } else if (idx < 8) {
+ /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
+ offset += idx * board->uart_offset + 0xC00;
+ } else /* we have only 8 ports on PMC-OCTALPRO */
+ return 1;
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+* This does initialization for PMC OCTALPRO cards:
+* maps the device memory, resets the UARTs (needed, bc
+* if the module is removed and inserted again, the card
+* is in the sleep mode) and enables global interrupt.
+*/
+
+/* global control register offset for SBS PMC-OctalPro */
+#define OCT_REG_CR_OFF 0x500
+
+static int sbs_init(struct pci_dev *dev)
+{
+ u8 __iomem *p;
+
+ p = pci_ioremap_bar(dev, 0);
+
+ if (p == NULL)
+ return -ENOMEM;
+ /* Set bit-4 Control Register (UART RESET) in to reset the uarts */
+ writeb(0x10, p + OCT_REG_CR_OFF);
+ udelay(50);
+ writeb(0x0, p + OCT_REG_CR_OFF);
+
+ /* Set bit-2 (INTENABLE) of Control Register */
+ writeb(0x4, p + OCT_REG_CR_OFF);
+ iounmap(p);
+
+ return 0;
+}
+
+/*
+ * Disables the global interrupt of PMC-OctalPro
+ */
+
+static void __devexit sbs_exit(struct pci_dev *dev)
+{
+ u8 __iomem *p;
+
+ p = pci_ioremap_bar(dev, 0);
+ /* FIXME: What if resource_len < OCT_REG_CR_OFF */
+ if (p != NULL)
+ writeb(0, p + OCT_REG_CR_OFF);
+ iounmap(p);
+}
+
+/*
+ * SIIG serial cards have an PCI interface chip which also controls
+ * the UART clocking frequency. Each UART can be clocked independently
+ * (except cards equipped with 4 UARTs) and initial clocking settings
+ * are stored in the EEPROM chip. It can cause problems because this
+ * version of serial driver doesn't support differently clocked UART's
+ * on single PCI card. To prevent this, initialization functions set
+ * high frequency clocking for all UART's on given card. It is safe (I
+ * hope) because it doesn't touch EEPROM settings to prevent conflicts
+ * with other OSes (like M$ DOS).
+ *
+ * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
+ *
+ * There is two family of SIIG serial cards with different PCI
+ * interface chip and different configuration methods:
+ * - 10x cards have control registers in IO and/or memory space;
+ * - 20x cards have control registers in standard PCI configuration space.
+ *
+ * Note: all 10x cards have PCI device ids 0x10..
+ * all 20x cards have PCI device ids 0x20..
+ *
+ * There are also Quartet Serial cards which use Oxford Semiconductor
+ * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
+ *
+ * Note: some SIIG cards are probed by the parport_serial object.
+ */
+
+#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
+#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
+
+static int pci_siig10x_init(struct pci_dev *dev)
+{
+ u16 data;
+ void __iomem *p;
+
+ switch (dev->device & 0xfff8) {
+ case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
+ data = 0xffdf;
+ break;
+ case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
+ data = 0xf7ff;
+ break;
+ default: /* 1S1P, 4S */
+ data = 0xfffb;
+ break;
+ }
+
+ p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
+ if (p == NULL)
+ return -ENOMEM;
+
+ writew(readw(p + 0x28) & data, p + 0x28);
+ readw(p + 0x28);
+ iounmap(p);
+ return 0;
+}
+
+#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
+#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
+
+static int pci_siig20x_init(struct pci_dev *dev)
+{
+ u8 data;
+
+ /* Change clock frequency for the first UART. */
+ pci_read_config_byte(dev, 0x6f, &data);
+ pci_write_config_byte(dev, 0x6f, data & 0xef);
+
+ /* If this card has 2 UART, we have to do the same with second UART. */
+ if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
+ ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
+ pci_read_config_byte(dev, 0x73, &data);
+ pci_write_config_byte(dev, 0x73, data & 0xef);
+ }
+ return 0;
+}
+
+static int pci_siig_init(struct pci_dev *dev)
+{
+ unsigned int type = dev->device & 0xff00;
+
+ if (type == 0x1000)
+ return pci_siig10x_init(dev);
+ else if (type == 0x2000)
+ return pci_siig20x_init(dev);
+
+ moan_device("Unknown SIIG card", dev);
+ return -ENODEV;
+}
+
+static int pci_siig_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
+
+ if (idx > 3) {
+ bar = 4;
+ offset = (idx - 4) * 8;
+ }
+
+ return setup_port(priv, port, bar, offset, 0);
+}
+
+/*
+ * Timedia has an explosion of boards, and to avoid the PCI table from
+ * growing *huge*, we use this function to collapse some 70 entries
+ * in the PCI table into one, for sanity's and compactness's sake.
+ */
+static const unsigned short timedia_single_port[] = {
+ 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
+};
+
+static const unsigned short timedia_dual_port[] = {
+ 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
+ 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
+ 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
+ 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
+ 0xD079, 0
+};
+
+static const unsigned short timedia_quad_port[] = {
+ 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
+ 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
+ 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
+ 0xB157, 0
+};
+
+static const unsigned short timedia_eight_port[] = {
+ 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
+ 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
+};
+
+static const struct timedia_struct {
+ int num;
+ const unsigned short *ids;
+} timedia_data[] = {
+ { 1, timedia_single_port },
+ { 2, timedia_dual_port },
+ { 4, timedia_quad_port },
+ { 8, timedia_eight_port }
+};
+
+/*
+ * There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of
+ * listing them individually, this driver merely grabs them all with
+ * PCI_ANY_ID. Some of these devices, however, also feature a parallel port,
+ * and should be left free to be claimed by parport_serial instead.
+ */
+static int pci_timedia_probe(struct pci_dev *dev)
+{
+ /*
+ * Check the third digit of the subdevice ID
+ * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
+ */
+ if ((dev->subsystem_device & 0x00f0) >= 0x70) {
+ dev_info(&dev->dev,
+ "ignoring Timedia subdevice %04x for parport_serial\n",
+ dev->subsystem_device);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int pci_timedia_init(struct pci_dev *dev)
+{
+ const unsigned short *ids;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
+ ids = timedia_data[i].ids;
+ for (j = 0; ids[j]; j++)
+ if (dev->subsystem_device == ids[j])
+ return timedia_data[i].num;
+ }
+ return 0;
+}
+
+/*
+ * Timedia/SUNIX uses a mixture of BARs and offsets
+ * Ugh, this is ugly as all hell --- TYT
+ */
+static int
+pci_timedia_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar = 0, offset = board->first_offset;
+
+ switch (idx) {
+ case 0:
+ bar = 0;
+ break;
+ case 1:
+ offset = board->uart_offset;
+ bar = 0;
+ break;
+ case 2:
+ bar = 1;
+ break;
+ case 3:
+ offset = board->uart_offset;
+ /* FALLTHROUGH */
+ case 4: /* BAR 2 */
+ case 5: /* BAR 3 */
+ case 6: /* BAR 4 */
+ case 7: /* BAR 5 */
+ bar = idx - 2;
+ }
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * Some Titan cards are also a little weird
+ */
+static int
+titan_400l_800l_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar, offset = board->first_offset;
+
+ switch (idx) {
+ case 0:
+ bar = 1;
+ break;
+ case 1:
+ bar = 2;
+ break;
+ default:
+ bar = 4;
+ offset = (idx - 2) * board->uart_offset;
+ }
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+static int pci_xircom_init(struct pci_dev *dev)
+{
+ msleep(100);
+ return 0;
+}
+
+static int pci_ni8420_init(struct pci_dev *dev)
+{
+ void __iomem *p;
+ unsigned long base, len;
+ unsigned int bar = 0;
+
+ if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+ moan_device("no memory in bar", dev);
+ return 0;
+ }
+
+ base = pci_resource_start(dev, bar);
+ len = pci_resource_len(dev, bar);
+ p = ioremap_nocache(base, len);
+ if (p == NULL)
+ return -ENOMEM;
+
+ /* Enable CPU Interrupt */
+ writel(readl(p + NI8420_INT_ENABLE_REG) | NI8420_INT_ENABLE_BIT,
+ p + NI8420_INT_ENABLE_REG);
+
+ iounmap(p);
+ return 0;
+}
+
+#define MITE_IOWBSR1_WSIZE 0xa
+#define MITE_IOWBSR1_WIN_OFFSET 0x800
+#define MITE_IOWBSR1_WENAB (1 << 7)
+#define MITE_LCIMR1_IO_IE_0 (1 << 24)
+#define MITE_LCIMR2_SET_CPU_IE (1 << 31)
+#define MITE_IOWCR1_RAMSEL_MASK 0xfffffffe
+
+static int pci_ni8430_init(struct pci_dev *dev)
+{
+ void __iomem *p;
+ unsigned long base, len;
+ u32 device_window;
+ unsigned int bar = 0;
+
+ if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+ moan_device("no memory in bar", dev);
+ return 0;
+ }
+
+ base = pci_resource_start(dev, bar);
+ len = pci_resource_len(dev, bar);
+ p = ioremap_nocache(base, len);
+ if (p == NULL)
+ return -ENOMEM;
+
+ /* Set device window address and size in BAR0 */
+ device_window = ((base + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00)
+ | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE;
+ writel(device_window, p + MITE_IOWBSR1);
+
+ /* Set window access to go to RAMSEL IO address space */
+ writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
+ p + MITE_IOWCR1);
+
+ /* Enable IO Bus Interrupt 0 */
+ writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
+
+ /* Enable CPU Interrupt */
+ writel(MITE_LCIMR2_SET_CPU_IE, p + MITE_LCIMR2);
+
+ iounmap(p);
+ return 0;
+}
+
+/* UART Port Control Register */
+#define NI8430_PORTCON 0x0f
+#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
+
+static int
+pci_ni8430_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ void __iomem *p;
+ unsigned long base, len;
+ unsigned int bar, offset = board->first_offset;
+
+ if (idx >= board->num_ports)
+ return 1;
+
+ bar = FL_GET_BASE(board->flags);
+ offset += idx * board->uart_offset;
+
+ base = pci_resource_start(priv->dev, bar);
+ len = pci_resource_len(priv->dev, bar);
+ p = ioremap_nocache(base, len);
+
+ /* enable the transceiver */
+ writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
+ p + offset + NI8430_PORTCON);
+
+ iounmap(p);
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+static int pci_netmos_9900_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar;
+
+ if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
+ /* netmos apparently orders BARs by datasheet layout, so serial
+ * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
+ */
+ bar = 3 * idx;
+
+ return setup_port(priv, port, bar, 0, board->reg_shift);
+ } else {
+ return pci_default_setup(priv, board, port, idx);
+ }
+}
+
+/* the 99xx series comes with a range of device IDs and a variety
+ * of capabilities:
+ *
+ * 9900 has varying capabilities and can cascade to sub-controllers
+ * (cascading should be purely internal)
+ * 9904 is hardwired with 4 serial ports
+ * 9912 and 9922 are hardwired with 2 serial ports
+ */
+static int pci_netmos_9900_numports(struct pci_dev *dev)
+{
+ unsigned int c = dev->class;
+ unsigned int pi;
+ unsigned short sub_serports;
+
+ pi = (c & 0xff);
+
+ if (pi == 2) {
+ return 1;
+ } else if ((pi == 0) &&
+ (dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
+ /* two possibilities: 0x30ps encodes number of parallel and
+ * serial ports, or 0x1000 indicates *something*. This is not
+ * immediately obvious, since the 2s1p+4s configuration seems
+ * to offer all functionality on functions 0..2, while still
+ * advertising the same function 3 as the 4s+2s1p config.
+ */
+ sub_serports = dev->subsystem_device & 0xf;
+ if (sub_serports > 0) {
+ return sub_serports;
+ } else {
+ printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+ return 0;
+ }
+ }
+
+ moan_device("unknown NetMos/Mostech program interface", dev);
+ return 0;
+}
+
+static int pci_netmos_init(struct pci_dev *dev)
+{
+ /* subdevice 0x00PS means <P> parallel, <S> serial */
+ unsigned int num_serial = dev->subsystem_device & 0xf;
+
+ if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
+ (dev->device == PCI_DEVICE_ID_NETMOS_9865))
+ return 0;
+
+ if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
+ dev->subsystem_device == 0x0299)
+ return 0;
+
+ switch (dev->device) { /* FALLTHROUGH on all */
+ case PCI_DEVICE_ID_NETMOS_9904:
+ case PCI_DEVICE_ID_NETMOS_9912:
+ case PCI_DEVICE_ID_NETMOS_9922:
+ case PCI_DEVICE_ID_NETMOS_9900:
+ num_serial = pci_netmos_9900_numports(dev);
+ break;
+
+ default:
+ if (num_serial == 0 ) {
+ moan_device("unknown NetMos/Mostech device", dev);
+ }
+ }
+
+ if (num_serial == 0)
+ return -ENODEV;
+
+ return num_serial;
+}
+
+/*
+ * These chips are available with optionally one parallel port and up to
+ * two serial ports. Unfortunately they all have the same product id.
+ *
+ * Basic configuration is done over a region of 32 I/O ports. The base
+ * ioport is called INTA or INTC, depending on docs/other drivers.
+ *
+ * The region of the 32 I/O ports is configured in POSIO0R...
+ */
+
+/* registers */
+#define ITE_887x_MISCR 0x9c
+#define ITE_887x_INTCBAR 0x78
+#define ITE_887x_UARTBAR 0x7c
+#define ITE_887x_PS0BAR 0x10
+#define ITE_887x_POSIO0 0x60
+
+/* I/O space size */
+#define ITE_887x_IOSIZE 32
+/* I/O space size (bits 26-24; 8 bytes = 011b) */
+#define ITE_887x_POSIO_IOSIZE_8 (3 << 24)
+/* I/O space size (bits 26-24; 32 bytes = 101b) */
+#define ITE_887x_POSIO_IOSIZE_32 (5 << 24)
+/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */
+#define ITE_887x_POSIO_SPEED (3 << 29)
+/* enable IO_Space bit */
+#define ITE_887x_POSIO_ENABLE (1 << 31)
+
+static int pci_ite887x_init(struct pci_dev *dev)
+{
+ /* inta_addr are the configuration addresses of the ITE */
+ static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
+ 0x200, 0x280, 0 };
+ int ret, i, type;
+ struct resource *iobase = NULL;
+ u32 miscr, uartbar, ioport;
+
+ /* search for the base-ioport */
+ i = 0;
+ while (inta_addr[i] && iobase == NULL) {
+ iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
+ "ite887x");
+ if (iobase != NULL) {
+ /* write POSIO0R - speed | size | ioport */
+ pci_write_config_dword(dev, ITE_887x_POSIO0,
+ ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
+ ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]);
+ /* write INTCBAR - ioport */
+ pci_write_config_dword(dev, ITE_887x_INTCBAR,
+ inta_addr[i]);
+ ret = inb(inta_addr[i]);
+ if (ret != 0xff) {
+ /* ioport connected */
+ break;
+ }
+ release_region(iobase->start, ITE_887x_IOSIZE);
+ iobase = NULL;
+ }
+ i++;
+ }
+
+ if (!inta_addr[i]) {
+ printk(KERN_ERR "ite887x: could not find iobase\n");
+ return -ENODEV;
+ }
+
+ /* start of undocumented type checking (see parport_pc.c) */
+ type = inb(iobase->start + 0x18) & 0x0f;
+
+ switch (type) {
+ case 0x2: /* ITE8871 (1P) */
+ case 0xa: /* ITE8875 (1P) */
+ ret = 0;
+ break;
+ case 0xe: /* ITE8872 (2S1P) */
+ ret = 2;
+ break;
+ case 0x6: /* ITE8873 (1S) */
+ ret = 1;
+ break;
+ case 0x8: /* ITE8874 (2S) */
+ ret = 2;
+ break;
+ default:
+ moan_device("Unknown ITE887x", dev);
+ ret = -ENODEV;
+ }
+
+ /* configure all serial ports */
+ for (i = 0; i < ret; i++) {
+ /* read the I/O port from the device */
+ pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),
+ &ioport);
+ ioport &= 0x0000FF00; /* the actual base address */
+ pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),
+ ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
+ ITE_887x_POSIO_IOSIZE_8 | ioport);
+
+ /* write the ioport to the UARTBAR */
+ pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);
+ uartbar &= ~(0xffff << (16 * i)); /* clear half the reg */
+ uartbar |= (ioport << (16 * i)); /* set the ioport */
+ pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);
+
+ /* get current config */
+ pci_read_config_dword(dev, ITE_887x_MISCR, &miscr);
+ /* disable interrupts (UARTx_Routing[3:0]) */
+ miscr &= ~(0xf << (12 - 4 * i));
+ /* activate the UART (UARTx_En) */
+ miscr |= 1 << (23 - i);
+ /* write new config with activated UART */
+ pci_write_config_dword(dev, ITE_887x_MISCR, miscr);
+ }
+
+ if (ret <= 0) {
+ /* the device has no UARTs if we get here */
+ release_region(iobase->start, ITE_887x_IOSIZE);
+ }
+
+ return ret;
+}
+
+static void __devexit pci_ite887x_exit(struct pci_dev *dev)
+{
+ u32 ioport;
+ /* the ioport is bit 0-15 in POSIO0R */
+ pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
+ ioport &= 0xffff;
+ release_region(ioport, ITE_887x_IOSIZE);
+}
+
+/*
+ * Oxford Semiconductor Inc.
+ * Check that device is part of the Tornado range of devices, then determine
+ * the number of ports available on the device.
+ */
+static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+{
+ u8 __iomem *p;
+ unsigned long deviceID;
+ unsigned int number_uarts = 0;
+
+ /* OxSemi Tornado devices are all 0xCxxx */
+ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+ (dev->device & 0xF000) != 0xC000)
+ return 0;
+
+ p = pci_iomap(dev, 0, 5);
+ if (p == NULL)
+ return -ENOMEM;
+
+ deviceID = ioread32(p);
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+ printk(KERN_DEBUG
+ "%d ports detected on Oxford PCI Express device\n",
+ number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+}
+
+static int
+pci_default_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar, offset = board->first_offset, maxnr;
+
+ bar = FL_GET_BASE(board->flags);
+ if (board->flags & FL_BASE_BARS)
+ bar += idx;
+ else
+ offset += idx * board->uart_offset;
+
+ maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
+ (board->reg_shift + 3);
+
+ if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
+ return 1;
+
+ return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+static int
+ce4100_serial_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ int ret;
+
+ ret = setup_port(priv, port, 0, 0, board->reg_shift);
+ port->iotype = UPIO_MEM32;
+ port->type = PORT_XSCALE;
+ port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+ port->regshift = 2;
+
+ return ret;
+}
+
+static int
+pci_omegapci_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ return setup_port(priv, port, 2, idx * 8, 0);
+}
+
+static int skip_tx_en_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ port->flags |= UPF_NO_TXEN_TEST;
+ printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
+ "[%04x:%04x] subsystem [%04x:%04x]\n",
+ priv->dev->vendor,
+ priv->dev->device,
+ priv->dev->subsystem_vendor,
+ priv->dev->subsystem_device);
+
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int kt_serial_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ port->flags |= UPF_IIR_ONCE;
+ return skip_tx_en_setup(priv, board, port, idx);
+}
+
+static int pci_eg20t_init(struct pci_dev *dev)
+{
+#if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE)
+ return -ENODEV;
+#else
+ return 0;
+#endif
+}
+
+static int
+pci_xr17c154_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ port->flags |= UPF_EXAR_EFR;
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int try_enable_msi(struct pci_dev *dev)
+{
+ /* use msi if available, but fallback to legacy otherwise */
+ pci_enable_msi(dev);
+ return 0;
+}
+
+static void disable_msi(struct pci_dev *dev)
+{
+ pci_disable_msi(dev);
+}
+
+#define PCI_VENDOR_ID_SBSMODULARIO 0x124B
+#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
+#define PCI_DEVICE_ID_OCTPRO 0x0001
+#define PCI_SUBDEVICE_ID_OCTPRO232 0x0108
+#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208
+#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
+#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
+#define PCI_VENDOR_ID_ADVANTECH 0x13fe
+#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
+#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
+#define PCI_DEVICE_ID_TITAN_200I 0x8028
+#define PCI_DEVICE_ID_TITAN_400I 0x8048
+#define PCI_DEVICE_ID_TITAN_800I 0x8088
+#define PCI_DEVICE_ID_TITAN_800EH 0xA007
+#define PCI_DEVICE_ID_TITAN_800EHB 0xA008
+#define PCI_DEVICE_ID_TITAN_400EH 0xA009
+#define PCI_DEVICE_ID_TITAN_100E 0xA010
+#define PCI_DEVICE_ID_TITAN_200E 0xA012
+#define PCI_DEVICE_ID_TITAN_400E 0xA013
+#define PCI_DEVICE_ID_TITAN_800E 0xA014
+#define PCI_DEVICE_ID_TITAN_200EI 0xA016
+#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
+#define PCI_DEVICE_ID_TITAN_400V3 0xA310
+#define PCI_DEVICE_ID_TITAN_410V3 0xA312
+#define PCI_DEVICE_ID_TITAN_800V3 0xA314
+#define PCI_DEVICE_ID_TITAN_800V3B 0xA315
+#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
+#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
+#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
+#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+
+/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
+
+/*
+ * Master list of serial port init/setup/exit quirks.
+ * This does not describe the general nature of the port.
+ * (ie, baud base, number and location of ports, etc)
+ *
+ * This list is ordered alphabetically by vendor then device.
+ * Specific entries must come before more generic entries.
+ */
+static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ /*
+ * ADDI-DATA GmbH communication cards <info@addi-data.com>
+ */
+ {
+ .vendor = PCI_VENDOR_ID_ADDIDATA_OLD,
+ .device = PCI_DEVICE_ID_ADDIDATA_APCI7800,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = addidata_apci7800_setup,
+ },
+ /*
+ * AFAVLAB cards - these may be called via parport_serial
+ * It is not clear whether this applies to all products.
+ */
+ {
+ .vendor = PCI_VENDOR_ID_AFAVLAB,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = afavlab_setup,
+ },
+ /*
+ * HP Diva
+ */
+ {
+ .vendor = PCI_VENDOR_ID_HP,
+ .device = PCI_DEVICE_ID_HP_DIVA,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_hp_diva_init,
+ .setup = pci_hp_diva_setup,
+ },
+ /*
+ * Intel
+ */
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_80960_RP,
+ .subvendor = 0xe4bf,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_inteli960ni_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_8257X_SOL,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = skip_tx_en_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82573L_SOL,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = skip_tx_en_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82573E_SOL,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = skip_tx_en_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_CE4100_UART,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = ce4100_serial_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = try_enable_msi,
+ .setup = kt_serial_setup,
+ .exit = disable_msi,
+ },
+ /*
+ * ITE
+ */
+ {
+ .vendor = PCI_VENDOR_ID_ITE,
+ .device = PCI_DEVICE_ID_ITE_8872,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ite887x_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ite887x_exit),
+ },
+ /*
+ * National Instruments
+ */
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI23216,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI2328,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI2324,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI2322,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI2324I,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI2322I,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8420_23216,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8420_2328,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8420_2324,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8420_2322,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8422_2324,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI8422_2322,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8420_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_ni8420_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_ni8430_init,
+ .setup = pci_ni8430_setup,
+ .exit = __devexit_p(pci_ni8430_exit),
+ },
+ /*
+ * Panacom
+ */
+ {
+ .vendor = PCI_VENDOR_ID_PANACOM,
+ .device = PCI_DEVICE_ID_PANACOM_QUADMODEM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PANACOM,
+ .device = PCI_DEVICE_ID_PANACOM_DUALMODEM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ /*
+ * PLX
+ */
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = PCI_SUBVENDOR_ID_PERLE,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_SUBVENDOR_ID_EXSYS,
+ .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_SUBVENDOR_ID_KEYSPAN,
+ .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_VENDOR_ID_PLX,
+ .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_ROMULUS,
+ .subvendor = PCI_VENDOR_ID_PLX,
+ .subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ /*
+ * SBS Technologies, Inc., PMC-OCTALPRO 232
+ */
+ {
+ .vendor = PCI_VENDOR_ID_SBSMODULARIO,
+ .device = PCI_DEVICE_ID_OCTPRO,
+ .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
+ .subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
+ .init = sbs_init,
+ .setup = sbs_setup,
+ .exit = __devexit_p(sbs_exit),
+ },
+ /*
+ * SBS Technologies, Inc., PMC-OCTALPRO 422
+ */
+ {
+ .vendor = PCI_VENDOR_ID_SBSMODULARIO,
+ .device = PCI_DEVICE_ID_OCTPRO,
+ .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
+ .subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
+ .init = sbs_init,
+ .setup = sbs_setup,
+ .exit = __devexit_p(sbs_exit),
+ },
+ /*
+ * SBS Technologies, Inc., P-Octal 232
+ */
+ {
+ .vendor = PCI_VENDOR_ID_SBSMODULARIO,
+ .device = PCI_DEVICE_ID_OCTPRO,
+ .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
+ .subdevice = PCI_SUBDEVICE_ID_POCTAL232,
+ .init = sbs_init,
+ .setup = sbs_setup,
+ .exit = __devexit_p(sbs_exit),
+ },
+ /*
+ * SBS Technologies, Inc., P-Octal 422
+ */
+ {
+ .vendor = PCI_VENDOR_ID_SBSMODULARIO,
+ .device = PCI_DEVICE_ID_OCTPRO,
+ .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
+ .subdevice = PCI_SUBDEVICE_ID_POCTAL422,
+ .init = sbs_init,
+ .setup = sbs_setup,
+ .exit = __devexit_p(sbs_exit),
+ },
+ /*
+ * SIIG cards - these may be called via parport_serial
+ */
+ {
+ .vendor = PCI_VENDOR_ID_SIIG,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_siig_init,
+ .setup = pci_siig_setup,
+ },
+ /*
+ * Titan cards
+ */
+ {
+ .vendor = PCI_VENDOR_ID_TITAN,
+ .device = PCI_DEVICE_ID_TITAN_400L,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = titan_400l_800l_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_TITAN,
+ .device = PCI_DEVICE_ID_TITAN_800L,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = titan_400l_800l_setup,
+ },
+ /*
+ * Timedia cards
+ */
+ {
+ .vendor = PCI_VENDOR_ID_TIMEDIA,
+ .device = PCI_DEVICE_ID_TIMEDIA_1889,
+ .subvendor = PCI_VENDOR_ID_TIMEDIA,
+ .subdevice = PCI_ANY_ID,
+ .probe = pci_timedia_probe,
+ .init = pci_timedia_init,
+ .setup = pci_timedia_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_TIMEDIA,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_timedia_setup,
+ },
+ /*
+ * Exar cards
+ */
+ {
+ .vendor = PCI_VENDOR_ID_EXAR,
+ .device = PCI_DEVICE_ID_EXAR_XR17C152,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17c154_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_EXAR,
+ .device = PCI_DEVICE_ID_EXAR_XR17C154,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17c154_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_EXAR,
+ .device = PCI_DEVICE_ID_EXAR_XR17C158,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17c154_setup,
+ },
+ /*
+ * Xircom cards
+ */
+ {
+ .vendor = PCI_VENDOR_ID_XIRCOM,
+ .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_xircom_init,
+ .setup = pci_default_setup,
+ },
+ /*
+ * Netmos cards - these may be called via parport_serial
+ */
+ {
+ .vendor = PCI_VENDOR_ID_NETMOS,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_netmos_init,
+ .setup = pci_netmos_9900_setup,
+ },
+ /*
+ * For Oxford Semiconductor Tornado based devices
+ */
+ {
+ .vendor = PCI_VENDOR_ID_OXSEMI,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_MAINPINE,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_DIGI,
+ .device = PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ .subvendor = PCI_SUBVENDOR_ID_IBM,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8811,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8812,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8813,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8814,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = 0x10DB,
+ .device = 0x8027,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = 0x10DB,
+ .device = 0x8028,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = 0x10DB,
+ .device = 0x8029,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = 0x10DB,
+ .device = 0x800C,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = 0x10DB,
+ .device = 0x800D,
+ .init = pci_eg20t_init,
+ .setup = pci_default_setup,
+ },
+ /*
+ * Cronyx Omega PCI (PLX-chip based)
+ */
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_omegapci_setup,
+ },
+ /*
+ * Default "match everything" terminator entry
+ */
+ {
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_default_setup,
+ }
+};
+
+static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
+{
+ return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
+}
+
+static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
+{
+ struct pci_serial_quirk *quirk;
+
+ for (quirk = pci_serial_quirks; ; quirk++)
+ if (quirk_id_matches(quirk->vendor, dev->vendor) &&
+ quirk_id_matches(quirk->device, dev->device) &&
+ quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
+ quirk_id_matches(quirk->subdevice, dev->subsystem_device))
+ break;
+ return quirk;
+}
+
+static inline int get_pci_irq(struct pci_dev *dev,
+ const struct pciserial_board *board)
+{
+ if (board->flags & FL_NOIRQ)
+ return 0;
+ else
+ return dev->irq;
+}
+
+/*
+ * This is the configuration table for all of the PCI serial boards
+ * which we support. It is directly indexed by the pci_board_num_t enum
+ * value, which is encoded in the pci_device_id PCI probe table's
+ * driver_data member.
+ *
+ * The makeup of these names are:
+ * pbn_bn{_bt}_n_baud{_offsetinhex}
+ *
+ * bn = PCI BAR number
+ * bt = Index using PCI BARs
+ * n = number of serial ports
+ * baud = baud rate
+ * offsetinhex = offset for each sequential port (in hex)
+ *
+ * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
+ *
+ * Please note: in theory if n = 1, _bt infix should make no difference.
+ * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
+ */
+enum pci_board_num_t {
+ pbn_default = 0,
+
+ pbn_b0_1_115200,
+ pbn_b0_2_115200,
+ pbn_b0_4_115200,
+ pbn_b0_5_115200,
+ pbn_b0_8_115200,
+
+ pbn_b0_1_921600,
+ pbn_b0_2_921600,
+ pbn_b0_4_921600,
+
+ pbn_b0_2_1130000,
+
+ pbn_b0_4_1152000,
+
+ pbn_b0_2_1843200,
+ pbn_b0_4_1843200,
+
+ pbn_b0_2_1843200_200,
+ pbn_b0_4_1843200_200,
+ pbn_b0_8_1843200_200,
+
+ pbn_b0_1_4000000,
+
+ pbn_b0_bt_1_115200,
+ pbn_b0_bt_2_115200,
+ pbn_b0_bt_4_115200,
+ pbn_b0_bt_8_115200,
+
+ pbn_b0_bt_1_460800,
+ pbn_b0_bt_2_460800,
+ pbn_b0_bt_4_460800,
+
+ pbn_b0_bt_1_921600,
+ pbn_b0_bt_2_921600,
+ pbn_b0_bt_4_921600,
+ pbn_b0_bt_8_921600,
+
+ pbn_b1_1_115200,
+ pbn_b1_2_115200,
+ pbn_b1_4_115200,
+ pbn_b1_8_115200,
+ pbn_b1_16_115200,
+
+ pbn_b1_1_921600,
+ pbn_b1_2_921600,
+ pbn_b1_4_921600,
+ pbn_b1_8_921600,
+
+ pbn_b1_2_1250000,
+
+ pbn_b1_bt_1_115200,
+ pbn_b1_bt_2_115200,
+ pbn_b1_bt_4_115200,
+
+ pbn_b1_bt_2_921600,
+
+ pbn_b1_1_1382400,
+ pbn_b1_2_1382400,
+ pbn_b1_4_1382400,
+ pbn_b1_8_1382400,
+
+ pbn_b2_1_115200,
+ pbn_b2_2_115200,
+ pbn_b2_4_115200,
+ pbn_b2_8_115200,
+
+ pbn_b2_1_460800,
+ pbn_b2_4_460800,
+ pbn_b2_8_460800,
+ pbn_b2_16_460800,
+
+ pbn_b2_1_921600,
+ pbn_b2_4_921600,
+ pbn_b2_8_921600,
+
+ pbn_b2_8_1152000,
+
+ pbn_b2_bt_1_115200,
+ pbn_b2_bt_2_115200,
+ pbn_b2_bt_4_115200,
+
+ pbn_b2_bt_2_921600,
+ pbn_b2_bt_4_921600,
+
+ pbn_b3_2_115200,
+ pbn_b3_4_115200,
+ pbn_b3_8_115200,
+
+ pbn_b4_bt_2_921600,
+ pbn_b4_bt_4_921600,
+ pbn_b4_bt_8_921600,
+
+ /*
+ * Board-specific versions.
+ */
+ pbn_panacom,
+ pbn_panacom2,
+ pbn_panacom4,
+ pbn_exsys_4055,
+ pbn_plx_romulus,
+ pbn_oxsemi,
+ pbn_oxsemi_1_4000000,
+ pbn_oxsemi_2_4000000,
+ pbn_oxsemi_4_4000000,
+ pbn_oxsemi_8_4000000,
+ pbn_intel_i960,
+ pbn_sgi_ioc3,
+ pbn_computone_4,
+ pbn_computone_6,
+ pbn_computone_8,
+ pbn_sbsxrsio,
+ pbn_exar_XR17C152,
+ pbn_exar_XR17C154,
+ pbn_exar_XR17C158,
+ pbn_exar_ibm_saturn,
+ pbn_pasemi_1682M,
+ pbn_ni8430_2,
+ pbn_ni8430_4,
+ pbn_ni8430_8,
+ pbn_ni8430_16,
+ pbn_ADDIDATA_PCIe_1_3906250,
+ pbn_ADDIDATA_PCIe_2_3906250,
+ pbn_ADDIDATA_PCIe_4_3906250,
+ pbn_ADDIDATA_PCIe_8_3906250,
+ pbn_ce4100_1_115200,
+ pbn_omegapci,
+ pbn_NETMOS9900_2s_115200,
+};
+
+/*
+ * uart_offset - the space between channels
+ * reg_shift - describes how the UART registers are mapped
+ * to PCI memory by the card.
+ * For example IER register on SBS, Inc. PMC-OctPro is located at
+ * offset 0x10 from the UART base, while UART_IER is defined as 1
+ * in include/linux/serial_reg.h,
+ * see first lines of serial_in() and serial_out() in 8250.c
+*/
+
+static struct pciserial_board pci_boards[] __devinitdata = {
+ [pbn_default] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_1_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_2_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_4_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_5_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 5,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_8_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_1_921600] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b0_2_921600] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b0_4_921600] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_2_1130000] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1130000,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_4_1152000] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1152000,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_2_1843200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1843200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_4_1843200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1843200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_2_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_4_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_8_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_1_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 4000000,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_bt_1_115200] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_2_115200] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_4_115200] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_8_115200] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_bt_1_460800] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_2_460800] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_4_460800] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_bt_1_921600] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_2_921600] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_4_921600] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b0_bt_8_921600] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
+ [pbn_b1_1_115200] = {
+ .flags = FL_BASE1,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b1_2_115200] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b1_4_115200] = {
+ .flags = FL_BASE1,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b1_8_115200] = {
+ .flags = FL_BASE1,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b1_16_115200] = {
+ .flags = FL_BASE1,
+ .num_ports = 16,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b1_1_921600] = {
+ .flags = FL_BASE1,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b1_2_921600] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b1_4_921600] = {
+ .flags = FL_BASE1,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b1_8_921600] = {
+ .flags = FL_BASE1,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b1_2_1250000] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+ .base_baud = 1250000,
+ .uart_offset = 8,
+ },
+
+ [pbn_b1_bt_1_115200] = {
+ .flags = FL_BASE1|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b1_bt_2_115200] = {
+ .flags = FL_BASE1|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b1_bt_4_115200] = {
+ .flags = FL_BASE1|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b1_bt_2_921600] = {
+ .flags = FL_BASE1|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
+ [pbn_b1_1_1382400] = {
+ .flags = FL_BASE1,
+ .num_ports = 1,
+ .base_baud = 1382400,
+ .uart_offset = 8,
+ },
+ [pbn_b1_2_1382400] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+ .base_baud = 1382400,
+ .uart_offset = 8,
+ },
+ [pbn_b1_4_1382400] = {
+ .flags = FL_BASE1,
+ .num_ports = 4,
+ .base_baud = 1382400,
+ .uart_offset = 8,
+ },
+ [pbn_b1_8_1382400] = {
+ .flags = FL_BASE1,
+ .num_ports = 8,
+ .base_baud = 1382400,
+ .uart_offset = 8,
+ },
+
+ [pbn_b2_1_115200] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b2_2_115200] = {
+ .flags = FL_BASE2,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b2_4_115200] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b2_8_115200] = {
+ .flags = FL_BASE2,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b2_1_460800] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [pbn_b2_4_460800] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [pbn_b2_8_460800] = {
+ .flags = FL_BASE2,
+ .num_ports = 8,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [pbn_b2_16_460800] = {
+ .flags = FL_BASE2,
+ .num_ports = 16,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+
+ [pbn_b2_1_921600] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b2_4_921600] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b2_8_921600] = {
+ .flags = FL_BASE2,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
+ [pbn_b2_8_1152000] = {
+ .flags = FL_BASE2,
+ .num_ports = 8,
+ .base_baud = 1152000,
+ .uart_offset = 8,
+ },
+
+ [pbn_b2_bt_1_115200] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b2_bt_2_115200] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b2_bt_4_115200] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b2_bt_2_921600] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b2_bt_4_921600] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
+ [pbn_b3_2_115200] = {
+ .flags = FL_BASE3,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b3_4_115200] = {
+ .flags = FL_BASE3,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_b3_8_115200] = {
+ .flags = FL_BASE3,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b4_bt_2_921600] = {
+ .flags = FL_BASE4,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b4_bt_4_921600] = {
+ .flags = FL_BASE4,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b4_bt_8_921600] = {
+ .flags = FL_BASE4,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
+ /*
+ * Entries following this are board-specific.
+ */
+
+ /*
+ * Panacom - IOMEM
+ */
+ [pbn_panacom] = {
+ .flags = FL_BASE2,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 0x400,
+ .reg_shift = 7,
+ },
+ [pbn_panacom2] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 0x400,
+ .reg_shift = 7,
+ },
+ [pbn_panacom4] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 0x400,
+ .reg_shift = 7,
+ },
+
+ [pbn_exsys_4055] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
+ /* I think this entry is broken - the first_offset looks wrong --rmk */
+ [pbn_plx_romulus] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8 << 2,
+ .reg_shift = 2,
+ .first_offset = 0x03,
+ },
+
+ /*
+ * This board uses the size of PCI Base region 0 to
+ * signal now many ports are available
+ */
+ [pbn_oxsemi] = {
+ .flags = FL_BASE0|FL_REGION_SZ_CAP,
+ .num_ports = 32,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [pbn_oxsemi_1_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_oxsemi_2_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_oxsemi_4_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_oxsemi_8_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+
+
+ /*
+ * EKF addition for i960 Boards form EKF with serial port.
+ * Max 256 ports.
+ */
+ [pbn_intel_i960] = {
+ .flags = FL_BASE0,
+ .num_ports = 32,
+ .base_baud = 921600,
+ .uart_offset = 8 << 2,
+ .reg_shift = 2,
+ .first_offset = 0x10000,
+ },
+ [pbn_sgi_ioc3] = {
+ .flags = FL_BASE0|FL_NOIRQ,
+ .num_ports = 1,
+ .base_baud = 458333,
+ .uart_offset = 8,
+ .reg_shift = 0,
+ .first_offset = 0x20178,
+ },
+
+ /*
+ * Computone - uses IOMEM.
+ */
+ [pbn_computone_4] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 0x40,
+ .reg_shift = 2,
+ .first_offset = 0x200,
+ },
+ [pbn_computone_6] = {
+ .flags = FL_BASE0,
+ .num_ports = 6,
+ .base_baud = 921600,
+ .uart_offset = 0x40,
+ .reg_shift = 2,
+ .first_offset = 0x200,
+ },
+ [pbn_computone_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 0x40,
+ .reg_shift = 2,
+ .first_offset = 0x200,
+ },
+ [pbn_sbsxrsio] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 460800,
+ .uart_offset = 256,
+ .reg_shift = 4,
+ },
+ /*
+ * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+ * Only basic 16550A support.
+ * XR17C15[24] are not tested, but they should work.
+ */
+ [pbn_exar_XR17C152] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 0x200,
+ },
+ [pbn_exar_XR17C154] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 0x200,
+ },
+ [pbn_exar_XR17C158] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 0x200,
+ },
+ [pbn_exar_ibm_saturn] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 0x200,
+ },
+
+ /*
+ * PA Semi PWRficient PA6T-1682M on-chip UART
+ */
+ [pbn_pasemi_1682M] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 8333333,
+ },
+ /*
+ * National Instruments 843x
+ */
+ [pbn_ni8430_16] = {
+ .flags = FL_BASE0,
+ .num_ports = 16,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8430_8] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8430_4] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ [pbn_ni8430_2] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 3686400,
+ .uart_offset = 0x10,
+ .first_offset = 0x800,
+ },
+ /*
+ * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
+ */
+ [pbn_ADDIDATA_PCIe_1_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ADDIDATA_PCIe_2_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ADDIDATA_PCIe_4_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ADDIDATA_PCIe_8_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ce4100_1_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .reg_shift = 2,
+ },
+ [pbn_omegapci] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 0x200,
+ },
+ [pbn_NETMOS9900_2s_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 115200,
+ },
+};
+
+static const struct pci_device_id softmodem_blacklist[] = {
+ { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
+ { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
+ { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
+};
+
+/*
+ * Given a complete unknown PCI device, try to use some heuristics to
+ * guess what the configuration might be, based on the pitiful PCI
+ * serial specs. Returns 0 on success, 1 on failure.
+ */
+static int __devinit
+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
+{
+ const struct pci_device_id *blacklist;
+ int num_iomem, num_port, first_port = -1, i;
+
+ /*
+ * If it is not a communications device or the programming
+ * interface is greater than 6, give up.
+ *
+ * (Should we try to make guesses for multiport serial devices
+ * later?)
+ */
+ if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
+ ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
+ (dev->class & 0xff) > 6)
+ return -ENODEV;
+
+ /*
+ * Do not access blacklisted devices that are known not to
+ * feature serial ports.
+ */
+ for (blacklist = softmodem_blacklist;
+ blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
+ blacklist++) {
+ if (dev->vendor == blacklist->vendor &&
+ dev->device == blacklist->device)
+ return -ENODEV;
+ }
+
+ num_iomem = num_port = 0;
+ for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+ if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
+ num_port++;
+ if (first_port == -1)
+ first_port = i;
+ }
+ if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
+ num_iomem++;
+ }
+
+ /*
+ * If there is 1 or 0 iomem regions, and exactly one port,
+ * use it. We guess the number of ports based on the IO
+ * region size.
+ */
+ if (num_iomem <= 1 && num_port == 1) {
+ board->flags = first_port;
+ board->num_ports = pci_resource_len(dev, first_port) / 8;
+ return 0;
+ }
+
+ /*
+ * Now guess if we've got a board which indexes by BARs.
+ * Each IO BAR should be 8 bytes, and they should follow
+ * consecutively.
+ */
+ first_port = -1;
+ num_port = 0;
+ for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+ if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
+ pci_resource_len(dev, i) == 8 &&
+ (first_port == -1 || (first_port + num_port) == i)) {
+ num_port++;
+ if (first_port == -1)
+ first_port = i;
+ }
+ }
+
+ if (num_port > 1) {
+ board->flags = first_port | FL_BASE_BARS;
+ board->num_ports = num_port;
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+static inline int
+serial_pci_matches(const struct pciserial_board *board,
+ const struct pciserial_board *guessed)
+{
+ return
+ board->num_ports == guessed->num_ports &&
+ board->base_baud == guessed->base_baud &&
+ board->uart_offset == guessed->uart_offset &&
+ board->reg_shift == guessed->reg_shift &&
+ board->first_offset == guessed->first_offset;
+}
+
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
+{
+ struct uart_port serial_port;
+ struct serial_private *priv;
+ struct pci_serial_quirk *quirk;
+ int rc, nr_ports, i;
+
+ nr_ports = board->num_ports;
+
+ /*
+ * Find an init and setup quirks.
+ */
+ quirk = find_quirk(dev);
+
+ /*
+ * Run the new-style initialization function.
+ * The initialization function returns:
+ * <0 - error
+ * 0 - use board->num_ports
+ * >0 - number of ports
+ */
+ if (quirk->init) {
+ rc = quirk->init(dev);
+ if (rc < 0) {
+ priv = ERR_PTR(rc);
+ goto err_out;
+ }
+ if (rc)
+ nr_ports = rc;
+ }
+
+ priv = kzalloc(sizeof(struct serial_private) +
+ sizeof(unsigned int) * nr_ports,
+ GFP_KERNEL);
+ if (!priv) {
+ priv = ERR_PTR(-ENOMEM);
+ goto err_deinit;
+ }
+
+ priv->dev = dev;
+ priv->quirk = quirk;
+
+ memset(&serial_port, 0, sizeof(struct uart_port));
+ serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ serial_port.uartclk = board->base_baud * 16;
+ serial_port.irq = get_pci_irq(dev, board);
+ serial_port.dev = &dev->dev;
+
+ for (i = 0; i < nr_ports; i++) {
+ if (quirk->setup(priv, board, &serial_port, i))
+ break;
+
+#ifdef SERIAL_DEBUG_PCI
+ printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
+ serial_port.iobase, serial_port.irq, serial_port.iotype);
+#endif
+
+ priv->line[i] = serial8250_register_port(&serial_port);
+ if (priv->line[i] < 0) {
+ printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
+ break;
+ }
+ }
+ priv->nr = i;
+ return priv;
+
+err_deinit:
+ if (quirk->exit)
+ quirk->exit(dev);
+err_out:
+ return priv;
+}
+EXPORT_SYMBOL_GPL(pciserial_init_ports);
+
+void pciserial_remove_ports(struct serial_private *priv)
+{
+ struct pci_serial_quirk *quirk;
+ int i;
+
+ for (i = 0; i < priv->nr; i++)
+ serial8250_unregister_port(priv->line[i]);
+
+ for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+ if (priv->remapped_bar[i])
+ iounmap(priv->remapped_bar[i]);
+ priv->remapped_bar[i] = NULL;
+ }
+
+ /*
+ * Find the exit quirks.
+ */
+ quirk = find_quirk(priv->dev);
+ if (quirk->exit)
+ quirk->exit(priv->dev);
+
+ kfree(priv);
+}
+EXPORT_SYMBOL_GPL(pciserial_remove_ports);
+
+void pciserial_suspend_ports(struct serial_private *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->nr; i++)
+ if (priv->line[i] >= 0)
+ serial8250_suspend_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
+
+void pciserial_resume_ports(struct serial_private *priv)
+{
+ int i;
+
+ /*
+ * Ensure that the board is correctly configured.
+ */
+ if (priv->quirk->init)
+ priv->quirk->init(priv->dev);
+
+ for (i = 0; i < priv->nr; i++)
+ if (priv->line[i] >= 0)
+ serial8250_resume_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_resume_ports);
+
+/*
+ * Probe one serial board. Unfortunately, there is no rhyme nor reason
+ * to the arrangement of serial ports on a PCI card.
+ */
+static int __devinit
+pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+ struct pci_serial_quirk *quirk;
+ struct serial_private *priv;
+ const struct pciserial_board *board;
+ struct pciserial_board tmp;
+ int rc;
+
+ quirk = find_quirk(dev);
+ if (quirk->probe) {
+ rc = quirk->probe(dev);
+ if (rc)
+ return rc;
+ }
+
+ if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+ printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
+ ent->driver_data);
+ return -EINVAL;
+ }
+
+ board = &pci_boards[ent->driver_data];
+
+ rc = pci_enable_device(dev);
+ pci_save_state(dev);
+ if (rc)
+ return rc;
+
+ if (ent->driver_data == pbn_default) {
+ /*
+ * Use a copy of the pci_board entry for this;
+ * avoid changing entries in the table.
+ */
+ memcpy(&tmp, board, sizeof(struct pciserial_board));
+ board = &tmp;
+
+ /*
+ * We matched one of our class entries. Try to
+ * determine the parameters of this board.
+ */
+ rc = serial_pci_guess_board(dev, &tmp);
+ if (rc)
+ goto disable;
+ } else {
+ /*
+ * We matched an explicit entry. If we are able to
+ * detect this boards settings with our heuristic,
+ * then we no longer need this entry.
+ */
+ memcpy(&tmp, &pci_boards[pbn_default],
+ sizeof(struct pciserial_board));
+ rc = serial_pci_guess_board(dev, &tmp);
+ if (rc == 0 && serial_pci_matches(board, &tmp))
+ moan_device("Redundant entry in serial pci_table.",
+ dev);
+ }
+
+ priv = pciserial_init_ports(dev, board);
+ if (!IS_ERR(priv)) {
+ pci_set_drvdata(dev, priv);
+ return 0;
+ }
+
+ rc = PTR_ERR(priv);
+
+ disable:
+ pci_disable_device(dev);
+ return rc;
+}
+
+static void __devexit pciserial_remove_one(struct pci_dev *dev)
+{
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ pci_set_drvdata(dev, NULL);
+
+ pciserial_remove_ports(priv);
+
+ pci_disable_device(dev);
+}
+
+#ifdef CONFIG_PM
+static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
+{
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ if (priv)
+ pciserial_suspend_ports(priv);
+
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ return 0;
+}
+
+static int pciserial_resume_one(struct pci_dev *dev)
+{
+ int err;
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ if (priv) {
+ /*
+ * The device may have been disabled. Re-enable it.
+ */
+ err = pci_enable_device(dev);
+ /* FIXME: We cannot simply error out here */
+ if (err)
+ printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
+ pciserial_resume_ports(priv);
+ }
+ return 0;
+}
+#endif
+
+static struct pci_device_id serial_pci_tbl[] = {
+ /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
+ { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
+ PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
+ pbn_b2_8_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
+ pbn_b1_8_1382400 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
+ pbn_b1_4_1382400 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
+ pbn_b1_2_1382400 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
+ pbn_b1_8_1382400 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
+ pbn_b1_4_1382400 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
+ pbn_b1_2_1382400 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
+ pbn_b1_8_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
+ pbn_b1_8_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
+ pbn_b1_4_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
+ pbn_b1_4_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
+ pbn_b1_2_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
+ pbn_b1_8_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
+ pbn_b1_8_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
+ pbn_b1_4_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
+ pbn_b1_2_1250000 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
+ pbn_b0_2_1843200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
+ pbn_b0_4_1843200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_VENDOR_ID_AFAVLAB,
+ PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
+ pbn_b0_4_1152000 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
+ 0, 0, pbn_exar_ibm_saturn },
+
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_1_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_4_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_4_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_8_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_8_460800 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_8_115200 },
+
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_115200 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_921600 },
+ /*
+ * VScom SPCOM800, from sl@s.pl
+ */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_8_921600 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_4_921600 },
+ /* Unknown card - subdevice 0x1584 */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_VENDOR_ID_PLX,
+ PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
+ pbn_b0_4_115200 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_KEYSPAN,
+ PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
+ pbn_panacom },
+ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_panacom4 },
+ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_panacom2 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+ PCI_VENDOR_ID_ESDGMBH,
+ PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0,
+ pbn_b2_4_115200 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
+ pbn_b2_4_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
+ pbn_b2_8_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
+ pbn_b2_16_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
+ pbn_b2_16_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+ PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
+ pbn_b2_4_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+ PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
+ pbn_b2_8_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_EXSYS,
+ PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
+ pbn_exsys_4055 },
+ /*
+ * Megawolf Romulus PCI Serial Card, from Mike Hudson
+ * (Exoray@isys.ca)
+ */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
+ 0x10b5, 0x106a, 0, 0,
+ pbn_plx_romulus },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_4_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_8_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_8_115200 },
+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
+ 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL,
+ 0, 0,
+ pbn_b0_4_1152000 },
+ { PCI_VENDOR_ID_OXSEMI, 0x9505,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
+
+ /*
+ * The below card is a little controversial since it is the
+ * subject of a PCI vendor/device ID clash. (See
+ * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html).
+ * For now just used the hex ID 0x950a.
+ */
+ { PCI_VENDOR_ID_OXSEMI, 0x950a,
+ PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
+ pbn_b0_2_115200 },
+ { PCI_VENDOR_ID_OXSEMI, 0x950a,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_2_1130000 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950,
+ PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0,
+ pbn_b0_1_921600 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_115200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
+ PCI_ANY_ID , PCI_ANY_ID, 0, 0,
+ pbn_b2_8_1152000 },
+
+ /*
+ * Oxford Semiconductor Inc. Tornado PCI express device range.
+ */
+ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ /*
+ * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
+ pbn_oxsemi_8_4000000 },
+
+ /*
+ * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+
+ /*
+ * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
+ * from skokodyn@yahoo.com
+ */
+ { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+ PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0,
+ pbn_sbsxrsio },
+ { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+ PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0,
+ pbn_sbsxrsio },
+ { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+ PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0,
+ pbn_sbsxrsio },
+ { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+ PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0,
+ pbn_sbsxrsio },
+
+ /*
+ * Digitan DS560-558, from jimd@esoft.com
+ */
+ { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_1_115200 },
+
+ /*
+ * Titan Electronic cards
+ * The 400L and 800L have a custom setup quirk.
+ */
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_2_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_1_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_2_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b4_bt_2_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b4_bt_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b4_bt_8_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_410V3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_1_460800 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_1_460800 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_1_460800 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+
+ /*
+ * Computone devices submitted by Doug McNash dmcnash@computone.com
+ */
+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
+ 0, 0, pbn_computone_4 },
+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
+ 0, 0, pbn_computone_8 },
+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
+ 0, 0, pbn_computone_6 },
+
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi },
+ { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
+ PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_1_921600 },
+
+ /*
+ * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
+ */
+ { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_115200 },
+ { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_115200 },
+
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_115200 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_115200 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_115200 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_115200 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_115200 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_4_460800 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_4_460800 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_460800 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_460800 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_460800 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_1_115200 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_1_460800 },
+
+ /*
+ * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
+ * Cards are identified by their subsystem vendor IDs, which
+ * (in hex) match the model number.
+ *
+ * Note that JC140x are RS422/485 cards which require ox950
+ * ACR = 0x10, and as such are not currently fully supported.
+ */
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1204, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1402, 0x0002, 0, 0,
+ pbn_b0_2_921600 }, */
+/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1404, 0x0004, 0, 0,
+ pbn_b0_4_921600 }, */
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
+ 0x1204, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+ /*
+ * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
+ */
+ { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_1_1382400 },
+
+ /*
+ * Dell Remote Access Card III - Tim_T_Murphy@Dell.com
+ */
+ { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_1_1382400 },
+
+ /*
+ * RAStel 2 port modem, gerg@moreton.com.au
+ */
+ { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_bt_2_115200 },
+
+ /*
+ * EKF addition for i960 Boards form EKF with serial port
+ */
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
+ 0xE4BF, PCI_ANY_ID, 0, 0,
+ pbn_intel_i960 },
+
+ /*
+ * Xircom Cardbus/Ethernet combos
+ */
+ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_115200 },
+ /*
+ * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
+ */
+ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_115200 },
+
+ /*
+ * Untested PCI modems, sent in from various folks...
+ */
+
+ /*
+ * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
+ */
+ { PCI_VENDOR_ID_ROCKWELL, 0x1004,
+ 0x1048, 0x1500, 0, 0,
+ pbn_b1_1_115200 },
+
+ { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+ 0xFF00, 0, 0, 0,
+ pbn_sgi_ioc3 },
+
+ /*
+ * HP Diva card
+ */
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0,
+ pbn_b1_1_115200 },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_5_115200 },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_1_115200 },
+
+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b3_2_115200 },
+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b3_4_115200 },
+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b3_8_115200 },
+
+ /*
+ * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+ */
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17C152 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17C154 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17C158 },
+
+ /*
+ * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
+ */
+ { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_115200 },
+ /*
+ * ITE
+ */
+ { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ pbn_b1_bt_1_115200 },
+
+ /*
+ * IntaShield IS-200
+ */
+ { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */
+ pbn_b2_2_115200 },
+ /*
+ * IntaShield IS-400
+ */
+ { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
+ pbn_b2_4_115200 },
+ /*
+ * Perle PCI-RAS cards
+ */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+ PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
+ 0, 0, pbn_b2_4_921600 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+ PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
+ 0, 0, pbn_b2_8_921600 },
+
+ /*
+ * Mainpine series cards: Fairly standard layout but fools
+ * parts of the autodetect in some cases and uses otherwise
+ * unmatched communications subclasses in the PCI Express case
+ */
+
+ { /* RockForceDUO */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0200,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceQUATRO */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0300,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceDUO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0400,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceQUATRO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0500,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForce+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0600,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForce+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0700,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceOCTO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0800,
+ 0, 0, pbn_b0_8_115200 },
+ { /* RockForceDUO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0C00,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceQUARTRO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0D00,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceOCTO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x1D00,
+ 0, 0, pbn_b0_8_115200 },
+ { /* RockForceD1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2000,
+ 0, 0, pbn_b0_1_115200 },
+ { /* RockForceF1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2100,
+ 0, 0, pbn_b0_1_115200 },
+ { /* RockForceD2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2200,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceF2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2300,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceD4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2400,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceF4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2500,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceD8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2600,
+ 0, 0, pbn_b0_8_115200 },
+ { /* RockForceF8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2700,
+ 0, 0, pbn_b0_8_115200 },
+ { /* IQ Express D1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3000,
+ 0, 0, pbn_b0_1_115200 },
+ { /* IQ Express F1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3100,
+ 0, 0, pbn_b0_1_115200 },
+ { /* IQ Express D2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3200,
+ 0, 0, pbn_b0_2_115200 },
+ { /* IQ Express F2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3300,
+ 0, 0, pbn_b0_2_115200 },
+ { /* IQ Express D4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3400,
+ 0, 0, pbn_b0_4_115200 },
+ { /* IQ Express F4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3500,
+ 0, 0, pbn_b0_4_115200 },
+ { /* IQ Express D8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3C00,
+ 0, 0, pbn_b0_8_115200 },
+ { /* IQ Express F8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3D00,
+ 0, 0, pbn_b0_8_115200 },
+
+
+ /*
+ * PA Semi PA6T-1682M on-chip UART
+ */
+ { PCI_VENDOR_ID_PASEMI, 0xa004,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_pasemi_1682M },
+
+ /*
+ * National Instruments
+ */
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI23216,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_16_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2328,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_8_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_4_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_2_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_4_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_2_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_23216,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_16_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2328,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_8_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_4_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_2_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_4_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_bt_2_115200 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_4 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_4 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2328,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_8 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2328,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_8 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_23216,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_16 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_23216,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_16 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_2 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_4 },
+ { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ni8430_4 },
+
+ /*
+ * ADDI-DATA GmbH communication cards <info@addi-data.com>
+ */
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7500,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_4_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7420,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_2_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7300,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA_OLD,
+ PCI_DEVICE_ID_ADDIDATA_APCI7800,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b1_8_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7500_2,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_4_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7420_2,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_2_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7300_2,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7500_3,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_4_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7420_3,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_2_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7300_3,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCI7800_3,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_8_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7500,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_4_3906250 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7420,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_2_3906250 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7300,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_1_3906250 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7800,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_8_3906250 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+ PCI_VENDOR_ID_IBM, 0x0299,
+ 0, 0, pbn_b0_bt_2_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
+ 0xA000, 0x1000,
+ 0, 0, pbn_b0_1_115200 },
+
+ /* the 9901 is a rebranded 9912 */
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+ 0xA000, 0x1000,
+ 0, 0, pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
+ 0xA000, 0x1000,
+ 0, 0, pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
+ 0xA000, 0x1000,
+ 0, 0, pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x1000,
+ 0, 0, pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+ 0xA000, 0x3002,
+ 0, 0, pbn_NETMOS9900_2s_115200 },
+
+ /*
+ * Best Connectivity and Rosewill PCI Multi I/O cards
+ */
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+ 0xA000, 0x1000,
+ 0, 0, pbn_b0_1_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+ 0xA000, 0x3002,
+ 0, 0, pbn_b0_bt_2_115200 },
+
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+ 0xA000, 0x3004,
+ 0, 0, pbn_b0_bt_4_115200 },
+ /* Intel CE4100 */
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_ce4100_1_115200 },
+
+ /*
+ * Cronyx Omega PCI
+ */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_omegapci },
+
+ /*
+ * These entries match devices with class COMMUNICATION_SERIAL,
+ * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
+ */
+ { PCI_ANY_ID, PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_COMMUNICATION_SERIAL << 8,
+ 0xffff00, pbn_default },
+ { PCI_ANY_ID, PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_COMMUNICATION_MODEM << 8,
+ 0xffff00, pbn_default },
+ { PCI_ANY_ID, PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8,
+ 0xffff00, pbn_default },
+ { 0, }
+};
+
+static pci_ers_result_t serial8250_io_error_detected(struct pci_dev *dev,
+ pci_channel_state_t state)
+{
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ if (priv)
+ pciserial_suspend_ports(priv);
+
+ pci_disable_device(dev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
+{
+ int rc;
+
+ rc = pci_enable_device(dev);
+
+ if (rc)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ pci_restore_state(dev);
+ pci_save_state(dev);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void serial8250_io_resume(struct pci_dev *dev)
+{
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ if (priv)
+ pciserial_resume_ports(priv);
+}
+
+static struct pci_error_handlers serial8250_err_handler = {
+ .error_detected = serial8250_io_error_detected,
+ .slot_reset = serial8250_io_slot_reset,
+ .resume = serial8250_io_resume,
+};
+
+static struct pci_driver serial_pci_driver = {
+ .name = "serial",
+ .probe = pciserial_init_one,
+ .remove = __devexit_p(pciserial_remove_one),
+#ifdef CONFIG_PM
+ .suspend = pciserial_suspend_one,
+ .resume = pciserial_resume_one,
+#endif
+ .id_table = serial_pci_tbl,
+ .err_handler = &serial8250_err_handler,
+};
+
+static int __init serial8250_pci_init(void)
+{
+ return pci_register_driver(&serial_pci_driver);
+}
+
+static void __exit serial8250_pci_exit(void)
+{
+ pci_unregister_driver(&serial_pci_driver);
+}
+
+module_init(serial8250_pci_init);
+module_exit(serial8250_pci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
+MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
--- /dev/null
+/*
+ * Probe module for 8250/16550-type ISAPNP serial ports.
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * Ported to the Linux PnP Layer - (C) Adam Belay.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pnp.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/serial_core.h>
+#include <linux/bitops.h>
+
+#include <asm/byteorder.h>
+
+#include "8250.h"
+
+#define UNKNOWN_DEV 0x3000
+
+
+static const struct pnp_device_id pnp_dev_table[] = {
+ /* Archtek America Corp. */
+ /* Archtek SmartLink Modem 3334BT Plug & Play */
+ { "AAC000F", 0 },
+ /* Anchor Datacomm BV */
+ /* SXPro 144 External Data Fax Modem Plug & Play */
+ { "ADC0001", 0 },
+ /* SXPro 288 External Data Fax Modem Plug & Play */
+ { "ADC0002", 0 },
+ /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
+ { "AEI0250", 0 },
+ /* Actiontec ISA PNP 56K X2 Fax Modem */
+ { "AEI1240", 0 },
+ /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+ { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
+ /* AZT3005 PnP SOUND DEVICE */
+ { "AZT4001", 0 },
+ /* Best Data Products Inc. Smart One 336F PnP Modem */
+ { "BDP3336", 0 },
+ /* Boca Research */
+ /* Boca Complete Ofc Communicator 14.4 Data-FAX */
+ { "BRI0A49", 0 },
+ /* Boca Research 33,600 ACF Modem */
+ { "BRI1400", 0 },
+ /* Boca 33.6 Kbps Internal FD34FSVD */
+ { "BRI3400", 0 },
+ /* Boca 33.6 Kbps Internal FD34FSVD */
+ { "BRI0A49", 0 },
+ /* Best Data Products Inc. Smart One 336F PnP Modem */
+ { "BDP3336", 0 },
+ /* Computer Peripherals Inc */
+ /* EuroViVa CommCenter-33.6 SP PnP */
+ { "CPI4050", 0 },
+ /* Creative Labs */
+ /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
+ { "CTL3001", 0 },
+ /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
+ { "CTL3011", 0 },
+ /* Davicom ISA 33.6K Modem */
+ { "DAV0336", 0 },
+ /* Creative */
+ /* Creative Modem Blaster Flash56 DI5601-1 */
+ { "DMB1032", 0 },
+ /* Creative Modem Blaster V.90 DI5660 */
+ { "DMB2001", 0 },
+ /* E-Tech */
+ /* E-Tech CyberBULLET PC56RVP */
+ { "ETT0002", 0 },
+ /* FUJITSU */
+ /* Fujitsu 33600 PnP-I2 R Plug & Play */
+ { "FUJ0202", 0 },
+ /* Fujitsu FMV-FX431 Plug & Play */
+ { "FUJ0205", 0 },
+ /* Fujitsu 33600 PnP-I4 R Plug & Play */
+ { "FUJ0206", 0 },
+ /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
+ { "FUJ0209", 0 },
+ /* Archtek America Corp. */
+ /* Archtek SmartLink Modem 3334BT Plug & Play */
+ { "GVC000F", 0 },
+ /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
+ { "GVC0303", 0 },
+ /* Hayes */
+ /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
+ { "HAY0001", 0 },
+ /* Hayes Optima 336 V.34 + FAX + Voice PnP */
+ { "HAY000C", 0 },
+ /* Hayes Optima 336B V.34 + FAX + Voice PnP */
+ { "HAY000D", 0 },
+ /* Hayes Accura 56K Ext Fax Modem PnP */
+ { "HAY5670", 0 },
+ /* Hayes Accura 56K Ext Fax Modem PnP */
+ { "HAY5674", 0 },
+ /* Hayes Accura 56K Fax Modem PnP */
+ { "HAY5675", 0 },
+ /* Hayes 288, V.34 + FAX */
+ { "HAYF000", 0 },
+ /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
+ { "HAYF001", 0 },
+ /* IBM */
+ /* IBM Thinkpad 701 Internal Modem Voice */
+ { "IBM0033", 0 },
+ /* Intermec */
+ /* Intermec CV60 touchscreen port */
+ { "PNP4972", 0 },
+ /* Intertex */
+ /* Intertex 28k8 33k6 Voice EXT PnP */
+ { "IXDC801", 0 },
+ /* Intertex 33k6 56k Voice EXT PnP */
+ { "IXDC901", 0 },
+ /* Intertex 28k8 33k6 Voice SP EXT PnP */
+ { "IXDD801", 0 },
+ /* Intertex 33k6 56k Voice SP EXT PnP */
+ { "IXDD901", 0 },
+ /* Intertex 28k8 33k6 Voice SP INT PnP */
+ { "IXDF401", 0 },
+ /* Intertex 28k8 33k6 Voice SP EXT PnP */
+ { "IXDF801", 0 },
+ /* Intertex 33k6 56k Voice SP EXT PnP */
+ { "IXDF901", 0 },
+ /* Kortex International */
+ /* KORTEX 28800 Externe PnP */
+ { "KOR4522", 0 },
+ /* KXPro 33.6 Vocal ASVD PnP */
+ { "KORF661", 0 },
+ /* Lasat */
+ /* LASAT Internet 33600 PnP */
+ { "LAS4040", 0 },
+ /* Lasat Safire 560 PnP */
+ { "LAS4540", 0 },
+ /* Lasat Safire 336 PnP */
+ { "LAS5440", 0 },
+ /* Microcom, Inc. */
+ /* Microcom TravelPorte FAST V.34 Plug & Play */
+ { "MNP0281", 0 },
+ /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
+ { "MNP0336", 0 },
+ /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
+ { "MNP0339", 0 },
+ /* Microcom DeskPorte 28.8P Plug & Play */
+ { "MNP0342", 0 },
+ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+ { "MNP0500", 0 },
+ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+ { "MNP0501", 0 },
+ /* Microcom DeskPorte 28.8S Internal Plug & Play */
+ { "MNP0502", 0 },
+ /* Motorola */
+ /* Motorola BitSURFR Plug & Play */
+ { "MOT1105", 0 },
+ /* Motorola TA210 Plug & Play */
+ { "MOT1111", 0 },
+ /* Motorola HMTA 200 (ISDN) Plug & Play */
+ { "MOT1114", 0 },
+ /* Motorola BitSURFR Plug & Play */
+ { "MOT1115", 0 },
+ /* Motorola Lifestyle 28.8 Internal */
+ { "MOT1190", 0 },
+ /* Motorola V.3400 Plug & Play */
+ { "MOT1501", 0 },
+ /* Motorola Lifestyle 28.8 V.34 Plug & Play */
+ { "MOT1502", 0 },
+ /* Motorola Power 28.8 V.34 Plug & Play */
+ { "MOT1505", 0 },
+ /* Motorola ModemSURFR External 28.8 Plug & Play */
+ { "MOT1509", 0 },
+ /* Motorola Premier 33.6 Desktop Plug & Play */
+ { "MOT150A", 0 },
+ /* Motorola VoiceSURFR 56K External PnP */
+ { "MOT150F", 0 },
+ /* Motorola ModemSURFR 56K External PnP */
+ { "MOT1510", 0 },
+ /* Motorola ModemSURFR 56K Internal PnP */
+ { "MOT1550", 0 },
+ /* Motorola ModemSURFR Internal 28.8 Plug & Play */
+ { "MOT1560", 0 },
+ /* Motorola Premier 33.6 Internal Plug & Play */
+ { "MOT1580", 0 },
+ /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
+ { "MOT15B0", 0 },
+ /* Motorola VoiceSURFR 56K Internal PnP */
+ { "MOT15F0", 0 },
+ /* Com 1 */
+ /* Deskline K56 Phone System PnP */
+ { "MVX00A1", 0 },
+ /* PC Rider K56 Phone System PnP */
+ { "MVX00F2", 0 },
+ /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
+ { "nEC8241", 0 },
+ /* Pace 56 Voice Internal Plug & Play Modem */
+ { "PMC2430", 0 },
+ /* Generic */
+ /* Generic standard PC COM port */
+ { "PNP0500", 0 },
+ /* Generic 16550A-compatible COM port */
+ { "PNP0501", 0 },
+ /* Compaq 14400 Modem */
+ { "PNPC000", 0 },
+ /* Compaq 2400/9600 Modem */
+ { "PNPC001", 0 },
+ /* Dial-Up Networking Serial Cable between 2 PCs */
+ { "PNPC031", 0 },
+ /* Dial-Up Networking Parallel Cable between 2 PCs */
+ { "PNPC032", 0 },
+ /* Standard 9600 bps Modem */
+ { "PNPC100", 0 },
+ /* Standard 14400 bps Modem */
+ { "PNPC101", 0 },
+ /* Standard 28800 bps Modem*/
+ { "PNPC102", 0 },
+ /* Standard Modem*/
+ { "PNPC103", 0 },
+ /* Standard 9600 bps Modem*/
+ { "PNPC104", 0 },
+ /* Standard 14400 bps Modem*/
+ { "PNPC105", 0 },
+ /* Standard 28800 bps Modem*/
+ { "PNPC106", 0 },
+ /* Standard Modem */
+ { "PNPC107", 0 },
+ /* Standard 9600 bps Modem */
+ { "PNPC108", 0 },
+ /* Standard 14400 bps Modem */
+ { "PNPC109", 0 },
+ /* Standard 28800 bps Modem */
+ { "PNPC10A", 0 },
+ /* Standard Modem */
+ { "PNPC10B", 0 },
+ /* Standard 9600 bps Modem */
+ { "PNPC10C", 0 },
+ /* Standard 14400 bps Modem */
+ { "PNPC10D", 0 },
+ /* Standard 28800 bps Modem */
+ { "PNPC10E", 0 },
+ /* Standard Modem */
+ { "PNPC10F", 0 },
+ /* Standard PCMCIA Card Modem */
+ { "PNP2000", 0 },
+ /* Rockwell */
+ /* Modular Technology */
+ /* Rockwell 33.6 DPF Internal PnP */
+ /* Modular Technology 33.6 Internal PnP */
+ { "ROK0030", 0 },
+ /* Kortex International */
+ /* KORTEX 14400 Externe PnP */
+ { "ROK0100", 0 },
+ /* Rockwell 28.8 */
+ { "ROK4120", 0 },
+ /* Viking Components, Inc */
+ /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
+ { "ROK4920", 0 },
+ /* Rockwell */
+ /* British Telecom */
+ /* Modular Technology */
+ /* Rockwell 33.6 DPF External PnP */
+ /* BT Prologue 33.6 External PnP */
+ /* Modular Technology 33.6 External PnP */
+ { "RSS00A0", 0 },
+ /* Viking 56K FAX INT */
+ { "RSS0262", 0 },
+ /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
+ { "RSS0250", 0 },
+ /* SupraExpress 28.8 Data/Fax PnP modem */
+ { "SUP1310", 0 },
+ /* SupraExpress 336i PnP Voice Modem */
+ { "SUP1381", 0 },
+ /* SupraExpress 33.6 Data/Fax PnP modem */
+ { "SUP1421", 0 },
+ /* SupraExpress 33.6 Data/Fax PnP modem */
+ { "SUP1590", 0 },
+ /* SupraExpress 336i Sp ASVD */
+ { "SUP1620", 0 },
+ /* SupraExpress 33.6 Data/Fax PnP modem */
+ { "SUP1760", 0 },
+ /* SupraExpress 56i Sp Intl */
+ { "SUP2171", 0 },
+ /* Phoebe Micro */
+ /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
+ { "TEX0011", 0 },
+ /* Archtek America Corp. */
+ /* Archtek SmartLink Modem 3334BT Plug & Play */
+ { "UAC000F", 0 },
+ /* 3Com Corp. */
+ /* Gateway Telepath IIvi 33.6 */
+ { "USR0000", 0 },
+ /* U.S. Robotics Sporster 33.6K Fax INT PnP */
+ { "USR0002", 0 },
+ /* Sportster Vi 14.4 PnP FAX Voicemail */
+ { "USR0004", 0 },
+ /* U.S. Robotics 33.6K Voice INT PnP */
+ { "USR0006", 0 },
+ /* U.S. Robotics 33.6K Voice EXT PnP */
+ { "USR0007", 0 },
+ /* U.S. Robotics Courier V.Everything INT PnP */
+ { "USR0009", 0 },
+ /* U.S. Robotics 33.6K Voice INT PnP */
+ { "USR2002", 0 },
+ /* U.S. Robotics 56K Voice INT PnP */
+ { "USR2070", 0 },
+ /* U.S. Robotics 56K Voice EXT PnP */
+ { "USR2080", 0 },
+ /* U.S. Robotics 56K FAX INT */
+ { "USR3031", 0 },
+ /* U.S. Robotics 56K FAX INT */
+ { "USR3050", 0 },
+ /* U.S. Robotics 56K Voice INT PnP */
+ { "USR3070", 0 },
+ /* U.S. Robotics 56K Voice EXT PnP */
+ { "USR3080", 0 },
+ /* U.S. Robotics 56K Voice INT PnP */
+ { "USR3090", 0 },
+ /* U.S. Robotics 56K Message */
+ { "USR9100", 0 },
+ /* U.S. Robotics 56K FAX EXT PnP*/
+ { "USR9160", 0 },
+ /* U.S. Robotics 56K FAX INT PnP*/
+ { "USR9170", 0 },
+ /* U.S. Robotics 56K Voice EXT PnP*/
+ { "USR9180", 0 },
+ /* U.S. Robotics 56K Voice INT PnP*/
+ { "USR9190", 0 },
+ /* Wacom tablets */
+ { "WACFXXX", 0 },
+ /* Compaq touchscreen */
+ { "FPI2002", 0 },
+ /* Fujitsu Stylistic touchscreens */
+ { "FUJ02B2", 0 },
+ { "FUJ02B3", 0 },
+ /* Fujitsu Stylistic LT touchscreens */
+ { "FUJ02B4", 0 },
+ /* Passive Fujitsu Stylistic touchscreens */
+ { "FUJ02B6", 0 },
+ { "FUJ02B7", 0 },
+ { "FUJ02B8", 0 },
+ { "FUJ02B9", 0 },
+ { "FUJ02BC", 0 },
+ /* Fujitsu Wacom Tablet PC device */
+ { "FUJ02E5", 0 },
+ /* Fujitsu P-series tablet PC device */
+ { "FUJ02E6", 0 },
+ /* Fujitsu Wacom 2FGT Tablet PC device */
+ { "FUJ02E7", 0 },
+ /* Fujitsu Wacom 1FGT Tablet PC device */
+ { "FUJ02E9", 0 },
+ /*
+ * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
+ * disguise)
+ */
+ { "LTS0001", 0 },
+ /* Rockwell's (PORALiNK) 33600 INT PNP */
+ { "WCI0003", 0 },
+ /* Unknown PnP modems */
+ { "PNPCXXX", UNKNOWN_DEV },
+ /* More unknown PnP modems */
+ { "PNPDXXX", UNKNOWN_DEV },
+ { "", 0 }
+};
+
+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+
+static char *modem_names[] __devinitdata = {
+ "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
+ "56K", "56k", "K56", "33.6", "28.8", "14.4",
+ "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
+ "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
+};
+
+static int __devinit check_name(char *name)
+{
+ char **tmp;
+
+ for (tmp = modem_names; *tmp; tmp++)
+ if (strstr(name, *tmp))
+ return 1;
+
+ return 0;
+}
+
+static int __devinit check_resources(struct pnp_dev *dev)
+{
+ resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(base); i++) {
+ if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Given a complete unknown PnP device, try to use some heuristics to
+ * detect modems. Currently use such heuristic set:
+ * - dev->name or dev->bus->name must contain "modem" substring;
+ * - device must have only one IO region (8 byte long) with base address
+ * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
+ *
+ * Such detection looks very ugly, but can detect at least some of numerous
+ * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
+ * table.
+ */
+static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
+{
+ if (!(check_name(pnp_dev_name(dev)) ||
+ (dev->card && check_name(dev->card->name))))
+ return -ENODEV;
+
+ if (check_resources(dev))
+ return 0;
+
+ return -ENODEV;
+}
+
+static int __devinit
+serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+{
+ struct uart_port port;
+ int ret, line, flags = dev_id->driver_data;
+
+ if (flags & UNKNOWN_DEV) {
+ ret = serial_pnp_guess_board(dev, &flags);
+ if (ret < 0)
+ return ret;
+ }
+
+ memset(&port, 0, sizeof(struct uart_port));
+ if (pnp_irq_valid(dev, 0))
+ port.irq = pnp_irq(dev, 0);
+ if (pnp_port_valid(dev, 0)) {
+ port.iobase = pnp_port_start(dev, 0);
+ port.iotype = UPIO_PORT;
+ } else if (pnp_mem_valid(dev, 0)) {
+ port.mapbase = pnp_mem_start(dev, 0);
+ port.iotype = UPIO_MEM;
+ port.flags = UPF_IOREMAP;
+ } else
+ return -ENODEV;
+
+#ifdef SERIAL_DEBUG_PNP
+ printk(KERN_DEBUG
+ "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
+ port.iobase, port.mapbase, port.irq, port.iotype);
+#endif
+
+ port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
+ port.flags |= UPF_SHARE_IRQ;
+ port.uartclk = 1843200;
+ port.dev = &dev->dev;
+
+ line = serial8250_register_port(&port);
+ if (line < 0)
+ return -ENODEV;
+
+ pnp_set_drvdata(dev, (void *)((long)line + 1));
+ return 0;
+}
+
+static void __devexit serial_pnp_remove(struct pnp_dev *dev)
+{
+ long line = (long)pnp_get_drvdata(dev);
+ if (line)
+ serial8250_unregister_port(line - 1);
+}
+
+#ifdef CONFIG_PM
+static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
+{
+ long line = (long)pnp_get_drvdata(dev);
+
+ if (!line)
+ return -ENODEV;
+ serial8250_suspend_port(line - 1);
+ return 0;
+}
+
+static int serial_pnp_resume(struct pnp_dev *dev)
+{
+ long line = (long)pnp_get_drvdata(dev);
+
+ if (!line)
+ return -ENODEV;
+ serial8250_resume_port(line - 1);
+ return 0;
+}
+#else
+#define serial_pnp_suspend NULL
+#define serial_pnp_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pnp_driver serial_pnp_driver = {
+ .name = "serial",
+ .probe = serial_pnp_probe,
+ .remove = __devexit_p(serial_pnp_remove),
+ .suspend = serial_pnp_suspend,
+ .resume = serial_pnp_resume,
+ .id_table = pnp_dev_table,
+};
+
+static int __init serial8250_pnp_init(void)
+{
+ return pnp_register_driver(&serial_pnp_driver);
+}
+
+static void __exit serial8250_pnp_exit(void)
+{
+ pnp_unregister_driver(&serial_pnp_driver);
+}
+
+module_init(serial8250_pnp_init);
+module_exit(serial8250_pnp_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
--- /dev/null
+#
+# The 8250/16550 serial drivers. You shouldn't be in this list unless
+# you somehow have an implicit or explicit dependency on SERIAL_8250.
+#
+
+config SERIAL_8250
+ tristate "8250/16550 and compatible serial support"
+ select SERIAL_CORE
+ ---help---
+ This selects whether you want to include the driver for the standard
+ serial ports. The standard answer is Y. People who might say N
+ here are those that are setting up dedicated Ethernet WWW/FTP
+ servers, or users that have one of the various bus mice instead of a
+ serial mouse and don't intend to use their machine's standard serial
+ port for anything. (Note that the Cyclades and Stallion multi
+ serial port drivers do not need this driver built in for them to
+ work.)
+
+ To compile this driver as a module, choose M here: the
+ module will be called 8250.
+ [WARNING: Do not compile this driver as a module if you are using
+ non-standard serial ports, since the configuration information will
+ be lost when the driver is unloaded. This limitation may be lifted
+ in the future.]
+
+ BTW1: If you have a mouseman serial mouse which is not recognized by
+ the X window system, try running gpm first.
+
+ BTW2: If you intend to use a software modem (also called Winmodem)
+ under Linux, forget it. These modems are crippled and require
+ proprietary drivers which are only available under Windows.
+
+ Most people will say Y or M here, so that they can use serial mice,
+ modems and similar devices connecting to the standard serial ports.
+
+config SERIAL_8250_CONSOLE
+ bool "Console on 8250/16550 and compatible serial port"
+ depends on SERIAL_8250=y
+ select SERIAL_CORE_CONSOLE
+ ---help---
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode). This could be useful if some terminal or printer is connected
+ to that serial port.
+
+ Even if you say Y here, the currently visible virtual console
+ (/dev/tty0) will still be used as the system console by default, but
+ you can alter that using a kernel command line option such as
+ "console=ttyS1". (Try "man bootparam" or see the documentation of
+ your boot loader (grub or lilo or loadlin) about how to pass options
+ to the kernel at boot time.)
+
+ If you don't have a VGA card installed and you say Y here, the
+ kernel will automatically use the first serial line, /dev/ttyS0, as
+ system console.
+
+ You can set that using a kernel command line option such as
+ "console=uart8250,io,0x3f8,9600n8"
+ "console=uart8250,mmio,0xff5e0000,115200n8".
+ and it will switch to normal serial console when the corresponding
+ port is ready.
+ "earlycon=uart8250,io,0x3f8,9600n8"
+ "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+ it will not only setup early console.
+
+ If unsure, say N.
+
+config FIX_EARLYCON_MEM
+ bool
+ depends on X86
+ default y
+
+config SERIAL_8250_GSC
+ tristate
+ depends on SERIAL_8250 && GSC
+ default SERIAL_8250
+
+config SERIAL_8250_PCI
+ tristate "8250/16550 PCI device support" if EXPERT
+ depends on SERIAL_8250 && PCI
+ default SERIAL_8250
+ help
+ This builds standard PCI serial support. You may be able to
+ disable this feature if you only need legacy serial support.
+ Saves about 9K.
+
+config SERIAL_8250_PNP
+ tristate "8250/16550 PNP device support" if EXPERT
+ depends on SERIAL_8250 && PNP
+ default SERIAL_8250
+ help
+ This builds standard PNP serial support. You may be able to
+ disable this feature if you only need legacy serial support.
+
+config SERIAL_8250_HP300
+ tristate
+ depends on SERIAL_8250 && HP300
+ default SERIAL_8250
+
+config SERIAL_8250_CS
+ tristate "8250/16550 PCMCIA device support"
+ depends on PCMCIA && SERIAL_8250
+ ---help---
+ Say Y here to enable support for 16-bit PCMCIA serial devices,
+ including serial port cards, modems, and the modem functions of
+ multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
+ credit-card size devices often used with laptops.)
+
+ To compile this driver as a module, choose M here: the
+ module will be called serial_cs.
+
+ If unsure, say N.
+
+config SERIAL_8250_NR_UARTS
+ int "Maximum number of 8250/16550 serial ports"
+ depends on SERIAL_8250
+ default "4"
+ help
+ Set this to the number of serial ports you want the driver
+ to support. This includes any ports discovered via ACPI or
+ PCI enumeration and any ports that may be added at run-time
+ via hot-plug, or any ISA multi-port serial cards.
+
+config SERIAL_8250_RUNTIME_UARTS
+ int "Number of 8250/16550 serial ports to register at runtime"
+ depends on SERIAL_8250
+ range 0 SERIAL_8250_NR_UARTS
+ default "4"
+ help
+ Set this to the maximum number of serial ports you want
+ the kernel to register at boot time. This can be overridden
+ with the module parameter "nr_uarts", or boot-time parameter
+ 8250.nr_uarts
+
+config SERIAL_8250_EXTENDED
+ bool "Extended 8250/16550 serial driver options"
+ depends on SERIAL_8250
+ help
+ If you wish to use any non-standard features of the standard "dumb"
+ driver, say Y here. This includes HUB6 support, shared serial
+ interrupts, special multiport support, support for more than the
+ four COM 1/2/3/4 boards, etc.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about serial driver options. If unsure, say N.
+
+config SERIAL_8250_MANY_PORTS
+ bool "Support more than 4 legacy serial ports"
+ depends on SERIAL_8250_EXTENDED && !IA64
+ help
+ Say Y here if you have dumb serial boards other than the four
+ standard COM 1/2/3/4 ports. This may happen if you have an AST
+ FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>), or other custom
+ serial port hardware which acts similar to standard serial port
+ hardware. If you only use the standard COM 1/2/3/4 ports, you can
+ say N here to save some memory. You can also say Y if you have an
+ "intelligent" multiport card such as Cyclades, Digiboards, etc.
+
+#
+# Multi-port serial cards
+#
+
+config SERIAL_8250_FOURPORT
+ tristate "Support Fourport cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have an AST FourPort serial board.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_fourport.
+
+config SERIAL_8250_ACCENT
+ tristate "Support Accent cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have an Accent Async serial board.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_accent.
+
+config SERIAL_8250_BOCA
+ tristate "Support Boca cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have a Boca serial board. Please read the Boca
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_boca.
+
+config SERIAL_8250_EXAR_ST16C554
+ tristate "Support Exar ST16C554/554D Quad UART"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
+ tinkering with your Envoy TU301, or have a machine with this UART,
+ say Y here.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_exar_st16c554.
+
+config SERIAL_8250_HUB6
+ tristate "Support Hub6 cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have a HUB6 serial board.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_hub6.
+
+#
+# Misc. options/drivers.
+#
+
+config SERIAL_8250_SHARE_IRQ
+ bool "Support for sharing serial interrupts"
+ depends on SERIAL_8250_EXTENDED
+ help
+ Some serial boards have hardware support which allows multiple dumb
+ serial ports on the same board to share a single IRQ. To enable
+ support for this in the serial driver, say Y here.
+
+config SERIAL_8250_DETECT_IRQ
+ bool "Autodetect IRQ on standard ports (unsafe)"
+ depends on SERIAL_8250_EXTENDED
+ help
+ Say Y here if you want the kernel to try to guess which IRQ
+ to use for your serial port.
+
+ This is considered unsafe; it is far better to configure the IRQ in
+ a boot script using the setserial command.
+
+ If unsure, say N.
+
+config SERIAL_8250_RSA
+ bool "Support RSA serial ports"
+ depends on SERIAL_8250_EXTENDED
+ help
+ ::: To be written :::
+
+config SERIAL_8250_MCA
+ tristate "Support 8250-type ports on MCA buses"
+ depends on SERIAL_8250 != n && MCA
+ help
+ Say Y here if you have a MCA serial ports.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_mca.
+
+config SERIAL_8250_ACORN
+ tristate "Acorn expansion card serial port support"
+ depends on ARCH_ACORN && SERIAL_8250
+ help
+ If you have an Atomwide Serial card or Serial Port card for an Acorn
+ system, say Y to this option. The driver can handle 1, 2, or 3 port
+ cards. If unsure, say N.
+
+config SERIAL_8250_RM9K
+ bool "Support for MIPS RM9xxx integrated serial port"
+ depends on SERIAL_8250 != n && SERIAL_RM9000
+ select SERIAL_8250_SHARE_IRQ
+ help
+ Selecting this option will add support for the integrated serial
+ port hardware found on MIPS RM9122 and similar processors.
+ If unsure, say N.
+
+config SERIAL_8250_FSL
+ bool
+ depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
+ default PPC
+
+config SERIAL_8250_DW
+ tristate "Support for Synopsys DesignWare 8250 quirks"
+ depends on SERIAL_8250 && OF
+ help
+ Selecting this option will enable handling of the extra features
+ present in the Synopsys DesignWare APB UART.
--- /dev/null
+#
+# Makefile for the 8250 serial device drivers.
+#
+
+obj-$(CONFIG_SERIAL_8250) += 8250.o
+obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
+obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
+obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
+obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
+obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
+obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
+obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
+obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
+obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
+obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
+obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
+obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
--- /dev/null
+/*
+ * m32r_sio.c
+ *
+ * Driver for M32R serial ports
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Based on drivers/serial/8250.c.
+ *
+ * Copyright (C) 2001 Russell King.
+ * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ *
+ * 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.
+ */
+
+/*
+ * A note about mapbase / membase
+ *
+ * mapbase is the physical address of the IO port. Currently, we don't
+ * support this very well, and it may well be dropped from this driver
+ * in future. As such, mapbase should be NULL.
+ *
+ * membase is an 'ioremapped' cookie. This is compatible with the old
+ * serial.c driver, and is currently the preferred form.
+ */
+
+#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/delay.h>
+
+#include <asm/m32r.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define PORT_M32R_BASE PORT_M32R_SIO
+#define PORT_INDEX(x) (x - PORT_M32R_BASE + 1)
+#define BAUD_RATE 115200
+
+#include <linux/serial_core.h>
+#include "m32r_sio.h"
+#include "m32r_sio_reg.h"
+
+/*
+ * Debugging.
+ */
+#if 0
+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
+#endif
+
+#if 0
+#define DEBUG_INTR(fmt...) printk(fmt)
+#else
+#define DEBUG_INTR(fmt...) do { } while (0)
+#endif
+
+#define PASS_LIMIT 256
+
+/*
+ * We default to IRQ0 for the "no irq" hack. Some
+ * machine types want others as well - they're free
+ * to redefine this in their header file.
+ */
+#define is_real_interrupt(irq) ((irq) != 0)
+
+#define BASE_BAUD 115200
+
+/* Standard COM flags */
+#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
+
+/*
+ * SERIAL_PORT_DFNS tells us about built-in ports that have no
+ * standard enumeration mechanism. Platforms that can find all
+ * serial ports via mechanisms like ACPI or PCI need not supply it.
+ */
+#if defined(CONFIG_PLAT_USRV)
+
+#define SERIAL_PORT_DFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */
+
+#else /* !CONFIG_PLAT_USRV */
+
+#if defined(CONFIG_SERIAL_M32R_PLDSIO)
+#define SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, \
+ STD_COM_FLAGS }, /* ttyS0 */
+#else
+#define SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, \
+ STD_COM_FLAGS }, /* ttyS0 */
+#endif
+
+#endif /* !CONFIG_PLAT_USRV */
+
+static struct old_serial_port old_serial_port[] = {
+ SERIAL_PORT_DFNS
+};
+
+#define UART_NR ARRAY_SIZE(old_serial_port)
+
+struct uart_sio_port {
+ struct uart_port port;
+ struct timer_list timer; /* "no irq" timer */
+ struct list_head list; /* ports on this IRQ */
+ unsigned short rev;
+ unsigned char acr;
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr_mask; /* mask of user bits */
+ unsigned char mcr_force; /* mask of forced bits */
+ unsigned char lsr_break_flag;
+
+ /*
+ * We provide a per-port pm hook.
+ */
+ void (*pm)(struct uart_port *port,
+ unsigned int state, unsigned int old);
+};
+
+struct irq_info {
+ spinlock_t lock;
+ struct list_head *head;
+};
+
+static struct irq_info irq_lists[NR_IRQS];
+
+/*
+ * Here we define the default xmit fifo size used for each type of UART.
+ */
+static const struct serial_uart_config uart_config[] = {
+ [PORT_UNKNOWN] = {
+ .name = "unknown",
+ .dfl_xmit_fifo_size = 1,
+ .flags = 0,
+ },
+ [PORT_INDEX(PORT_M32R_SIO)] = {
+ .name = "M32RSIO",
+ .dfl_xmit_fifo_size = 1,
+ .flags = 0,
+ },
+};
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+
+#define __sio_in(x) inw((unsigned long)(x))
+#define __sio_out(v,x) outw((v),(unsigned long)(x))
+
+static inline void sio_set_baud_rate(unsigned long baud)
+{
+ unsigned short sbaud;
+ sbaud = (boot_cpu_data.bus_clock / (baud * 4))-1;
+ __sio_out(sbaud, PLD_ESIO0BAUR);
+}
+
+static void sio_reset(void)
+{
+ unsigned short tmp;
+
+ tmp = __sio_in(PLD_ESIO0RXB);
+ tmp = __sio_in(PLD_ESIO0RXB);
+ tmp = __sio_in(PLD_ESIO0CR);
+ sio_set_baud_rate(BAUD_RATE);
+ __sio_out(0x0300, PLD_ESIO0CR);
+ __sio_out(0x0003, PLD_ESIO0CR);
+}
+
+static void sio_init(void)
+{
+ unsigned short tmp;
+
+ tmp = __sio_in(PLD_ESIO0RXB);
+ tmp = __sio_in(PLD_ESIO0RXB);
+ tmp = __sio_in(PLD_ESIO0CR);
+ __sio_out(0x0300, PLD_ESIO0CR);
+ __sio_out(0x0003, PLD_ESIO0CR);
+}
+
+static void sio_error(int *status)
+{
+ printk("SIO0 error[%04x]\n", *status);
+ do {
+ sio_init();
+ } while ((*status = __sio_in(PLD_ESIO0CR)) != 3);
+}
+
+#else /* not CONFIG_SERIAL_M32R_PLDSIO */
+
+#define __sio_in(x) inl(x)
+#define __sio_out(v,x) outl((v),(x))
+
+static inline void sio_set_baud_rate(unsigned long baud)
+{
+ unsigned long i, j;
+
+ i = boot_cpu_data.bus_clock / (baud * 16);
+ j = (boot_cpu_data.bus_clock - (i * baud * 16)) / baud;
+ i -= 1;
+ j = (j + 1) >> 1;
+
+ __sio_out(i, M32R_SIO0_BAUR_PORTL);
+ __sio_out(j, M32R_SIO0_RBAUR_PORTL);
+}
+
+static void sio_reset(void)
+{
+ __sio_out(0x00000300, M32R_SIO0_CR_PORTL); /* init status */
+ __sio_out(0x00000800, M32R_SIO0_MOD1_PORTL); /* 8bit */
+ __sio_out(0x00000080, M32R_SIO0_MOD0_PORTL); /* 1stop non */
+ sio_set_baud_rate(BAUD_RATE);
+ __sio_out(0x00000000, M32R_SIO0_TRCR_PORTL);
+ __sio_out(0x00000003, M32R_SIO0_CR_PORTL); /* RXCEN */
+}
+
+static void sio_init(void)
+{
+ unsigned int tmp;
+
+ tmp = __sio_in(M32R_SIO0_RXB_PORTL);
+ tmp = __sio_in(M32R_SIO0_RXB_PORTL);
+ tmp = __sio_in(M32R_SIO0_STS_PORTL);
+ __sio_out(0x00000003, M32R_SIO0_CR_PORTL);
+}
+
+static void sio_error(int *status)
+{
+ printk("SIO0 error[%04x]\n", *status);
+ do {
+ sio_init();
+ } while ((*status = __sio_in(M32R_SIO0_CR_PORTL)) != 3);
+}
+
+#endif /* CONFIG_SERIAL_M32R_PLDSIO */
+
+static unsigned int sio_in(struct uart_sio_port *up, int offset)
+{
+ return __sio_in(up->port.iobase + offset);
+}
+
+static void sio_out(struct uart_sio_port *up, int offset, int value)
+{
+ __sio_out(value, up->port.iobase + offset);
+}
+
+static unsigned int serial_in(struct uart_sio_port *up, int offset)
+{
+ if (!offset)
+ return 0;
+
+ return __sio_in(offset);
+}
+
+static void serial_out(struct uart_sio_port *up, int offset, int value)
+{
+ if (!offset)
+ return;
+
+ __sio_out(value, offset);
+}
+
+static void m32r_sio_stop_tx(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ if (up->ier & UART_IER_THRI) {
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ }
+}
+
+static void m32r_sio_start_tx(struct uart_port *port)
+{
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ struct circ_buf *xmit = &up->port.state->xmit;
+
+ if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ up->port.icount.tx++;
+ }
+ while((serial_in(up, UART_LSR) & UART_EMPTY) != UART_EMPTY);
+#else
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ }
+#endif
+}
+
+static void m32r_sio_stop_rx(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+}
+
+static void m32r_sio_enable_ms(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ up->ier |= UART_IER_MSI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+static void receive_chars(struct uart_sio_port *up, int *status)
+{
+ struct tty_struct *tty = up->port.state->port.tty;
+ unsigned char ch;
+ unsigned char flag;
+ int max_count = 256;
+
+ do {
+ ch = sio_in(up, SIORXB);
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
+ UART_LSR_FE | UART_LSR_OE))) {
+ /*
+ * For statistics only
+ */
+ if (*status & UART_LSR_BI) {
+ *status &= ~(UART_LSR_FE | UART_LSR_PE);
+ up->port.icount.brk++;
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(&up->port))
+ goto ignore_char;
+ } else if (*status & UART_LSR_PE)
+ up->port.icount.parity++;
+ else if (*status & UART_LSR_FE)
+ up->port.icount.frame++;
+ if (*status & UART_LSR_OE)
+ up->port.icount.overrun++;
+
+ /*
+ * Mask off conditions which should be ingored.
+ */
+ *status &= up->port.read_status_mask;
+
+ if (up->port.line == up->port.cons->index) {
+ /* Recover the break flag from console xmit */
+ *status |= up->lsr_break_flag;
+ up->lsr_break_flag = 0;
+ }
+
+ if (*status & UART_LSR_BI) {
+ DEBUG_INTR("handling break....");
+ flag = TTY_BREAK;
+ } else if (*status & UART_LSR_PE)
+ flag = TTY_PARITY;
+ else if (*status & UART_LSR_FE)
+ flag = TTY_FRAME;
+ }
+ if (uart_handle_sysrq_char(&up->port, ch))
+ goto ignore_char;
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (*status & UART_LSR_OE) {
+ /*
+ * Overrun is special, since it's reported
+ * immediately, and doesn't affect the current
+ * character.
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
+ ignore_char:
+ *status = serial_in(up, UART_LSR);
+ } while ((*status & UART_LSR_DR) && (max_count-- > 0));
+ tty_flip_buffer_push(tty);
+}
+
+static void transmit_chars(struct uart_sio_port *up)
+{
+ struct circ_buf *xmit = &up->port.state->xmit;
+ int count;
+
+ if (up->port.x_char) {
+#ifndef CONFIG_SERIAL_M32R_PLDSIO /* XXX */
+ serial_out(up, UART_TX, up->port.x_char);
+#endif
+ up->port.icount.tx++;
+ up->port.x_char = 0;
+ return;
+ }
+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ m32r_sio_stop_tx(&up->port);
+ return;
+ }
+
+ count = up->port.fifosize;
+ do {
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ up->port.icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ while (!(serial_in(up, UART_LSR) & UART_LSR_THRE));
+
+ } while (--count > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+
+ DEBUG_INTR("THRE...");
+
+ if (uart_circ_empty(xmit))
+ m32r_sio_stop_tx(&up->port);
+}
+
+/*
+ * This handles the interrupt from one port.
+ */
+static inline void m32r_sio_handle_port(struct uart_sio_port *up,
+ unsigned int status)
+{
+ DEBUG_INTR("status = %x...", status);
+
+ if (status & 0x04)
+ receive_chars(up, &status);
+ if (status & 0x01)
+ transmit_chars(up);
+}
+
+/*
+ * This is the serial driver's interrupt routine.
+ *
+ * Arjan thinks the old way was overly complex, so it got simplified.
+ * Alan disagrees, saying that need the complexity to handle the weird
+ * nature of ISA shared interrupts. (This is a special exception.)
+ *
+ * In order to handle ISA shared interrupts properly, we need to check
+ * that all ports have been serviced, and therefore the ISA interrupt
+ * line has been de-asserted.
+ *
+ * This means we need to loop through all ports. checking that they
+ * don't have an interrupt pending.
+ */
+static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id)
+{
+ struct irq_info *i = dev_id;
+ struct list_head *l, *end = NULL;
+ int pass_counter = 0;
+
+ DEBUG_INTR("m32r_sio_interrupt(%d)...", irq);
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+// if (irq == PLD_IRQ_SIO0_SND)
+// irq = PLD_IRQ_SIO0_RCV;
+#else
+ if (irq == M32R_IRQ_SIO0_S)
+ irq = M32R_IRQ_SIO0_R;
+#endif
+
+ spin_lock(&i->lock);
+
+ l = i->head;
+ do {
+ struct uart_sio_port *up;
+ unsigned int sts;
+
+ up = list_entry(l, struct uart_sio_port, list);
+
+ sts = sio_in(up, SIOSTS);
+ if (sts & 0x5) {
+ spin_lock(&up->port.lock);
+ m32r_sio_handle_port(up, sts);
+ spin_unlock(&up->port.lock);
+
+ end = NULL;
+ } else if (end == NULL)
+ end = l;
+
+ l = l->next;
+
+ if (l == i->head && pass_counter++ > PASS_LIMIT) {
+ if (sts & 0xe0)
+ sio_error(&sts);
+ break;
+ }
+ } while (l != end);
+
+ spin_unlock(&i->lock);
+
+ DEBUG_INTR("end.\n");
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * To support ISA shared interrupts, we need to have one interrupt
+ * handler that ensures that the IRQ line has been deasserted
+ * before returning. Failing to do this will result in the IRQ
+ * line being stuck active, and, since ISA irqs are edge triggered,
+ * no more IRQs will be seen.
+ */
+static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up)
+{
+ spin_lock_irq(&i->lock);
+
+ if (!list_empty(i->head)) {
+ if (i->head == &up->list)
+ i->head = i->head->next;
+ list_del(&up->list);
+ } else {
+ BUG_ON(i->head != &up->list);
+ i->head = NULL;
+ }
+
+ spin_unlock_irq(&i->lock);
+}
+
+static int serial_link_irq_chain(struct uart_sio_port *up)
+{
+ struct irq_info *i = irq_lists + up->port.irq;
+ int ret, irq_flags = 0;
+
+ spin_lock_irq(&i->lock);
+
+ if (i->head) {
+ list_add(&up->list, i->head);
+ spin_unlock_irq(&i->lock);
+
+ ret = 0;
+ } else {
+ INIT_LIST_HEAD(&up->list);
+ i->head = &up->list;
+ spin_unlock_irq(&i->lock);
+
+ ret = request_irq(up->port.irq, m32r_sio_interrupt,
+ irq_flags, "SIO0-RX", i);
+ ret |= request_irq(up->port.irq + 1, m32r_sio_interrupt,
+ irq_flags, "SIO0-TX", i);
+ if (ret < 0)
+ serial_do_unlink(i, up);
+ }
+
+ return ret;
+}
+
+static void serial_unlink_irq_chain(struct uart_sio_port *up)
+{
+ struct irq_info *i = irq_lists + up->port.irq;
+
+ BUG_ON(i->head == NULL);
+
+ if (list_empty(i->head)) {
+ free_irq(up->port.irq, i);
+ free_irq(up->port.irq + 1, i);
+ }
+
+ serial_do_unlink(i, up);
+}
+
+/*
+ * This function is used to handle ports that do not have an interrupt.
+ */
+static void m32r_sio_timeout(unsigned long data)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)data;
+ unsigned int timeout;
+ unsigned int sts;
+
+ sts = sio_in(up, SIOSTS);
+ if (sts & 0x5) {
+ spin_lock(&up->port.lock);
+ m32r_sio_handle_port(up, sts);
+ spin_unlock(&up->port.lock);
+ }
+
+ timeout = up->port.timeout;
+ timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
+ mod_timer(&up->timer, jiffies + timeout);
+}
+
+static unsigned int m32r_sio_tx_empty(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return ret;
+}
+
+static unsigned int m32r_sio_get_mctrl(struct uart_port *port)
+{
+ return 0;
+}
+
+static void m32r_sio_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+
+}
+
+static void m32r_sio_break_ctl(struct uart_port *port, int break_state)
+{
+
+}
+
+static int m32r_sio_startup(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ int retval;
+
+ sio_init();
+
+ /*
+ * If the "interrupt" for this port doesn't correspond with any
+ * hardware interrupt, we use a timer-based system. The original
+ * driver used to do this with IRQ0.
+ */
+ if (!is_real_interrupt(up->port.irq)) {
+ unsigned int timeout = up->port.timeout;
+
+ timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
+
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies + timeout);
+ } else {
+ retval = serial_link_irq_chain(up);
+ if (retval)
+ return retval;
+ }
+
+ /*
+ * Finally, enable interrupts. Note: Modem status interrupts
+ * are set via set_termios(), which will be occurring imminently
+ * anyway, so we don't enable them here.
+ * - M32R_SIO: 0x0c
+ * - M32R_PLDSIO: 0x04
+ */
+ up->ier = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+ sio_out(up, SIOTRCR, up->ier);
+
+ /*
+ * And clear the interrupt registers again for luck.
+ */
+ sio_reset();
+
+ return 0;
+}
+
+static void m32r_sio_shutdown(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ /*
+ * Disable interrupts from this port
+ */
+ up->ier = 0;
+ sio_out(up, SIOTRCR, 0);
+
+ /*
+ * Disable break condition and FIFOs
+ */
+
+ sio_init();
+
+ if (!is_real_interrupt(up->port.irq))
+ del_timer_sync(&up->timer);
+ else
+ serial_unlink_irq_chain(up);
+}
+
+static unsigned int m32r_sio_get_divisor(struct uart_port *port,
+ unsigned int baud)
+{
+ return uart_get_divisor(port, baud);
+}
+
+static void m32r_sio_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ unsigned char cval = 0;
+ unsigned long flags;
+ unsigned int baud, quot;
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ cval = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ cval = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ cval = UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ cval = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ cval |= UART_LCR_STOP;
+ if (termios->c_cflag & PARENB)
+ cval |= UART_LCR_PARITY;
+ if (!(termios->c_cflag & PARODD))
+ cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+ if (termios->c_cflag & CMSPAR)
+ cval |= UART_LCR_SPAR;
+#endif
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
+#else
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+#endif
+ quot = m32r_sio_get_divisor(port, baud);
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ sio_set_baud_rate(baud);
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (termios->c_iflag & INPCK)
+ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ up->port.read_status_mask |= UART_LSR_BI;
+
+ /*
+ * Characteres to ignore
+ */
+ up->port.ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ up->port.ignore_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_OE;
+ }
+
+ /*
+ * ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= UART_LSR_DR;
+
+ /*
+ * CTS flow control flag and modem status interrupts
+ */
+ up->ier &= ~UART_IER_MSI;
+ if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+ up->ier |= UART_IER_MSI;
+
+ serial_out(up, UART_IER, up->ier);
+
+ up->lcr = cval; /* Save LCR */
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void m32r_sio_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ if (up->pm)
+ up->pm(port, state, oldstate);
+}
+
+/*
+ * Resource handling. This is complicated by the fact that resources
+ * depend on the port type. Maybe we should be claiming the standard
+ * 8250 ports, and then trying to get other resources as necessary?
+ */
+static int
+m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res)
+{
+ unsigned int size = 8 << up->port.regshift;
+#ifndef CONFIG_SERIAL_M32R_PLDSIO
+ unsigned long start;
+#endif
+ int ret = 0;
+
+ switch (up->port.iotype) {
+ case UPIO_MEM:
+ if (up->port.mapbase) {
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+ *res = request_mem_region(up->port.mapbase, size, "serial");
+#else
+ start = up->port.mapbase;
+ *res = request_mem_region(start, size, "serial");
+#endif
+ if (!*res)
+ ret = -EBUSY;
+ }
+ break;
+
+ case UPIO_PORT:
+ *res = request_region(up->port.iobase, size, "serial");
+ if (!*res)
+ ret = -EBUSY;
+ break;
+ }
+ return ret;
+}
+
+static void m32r_sio_release_port(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ unsigned long start, offset = 0, size = 0;
+
+ size <<= up->port.regshift;
+
+ switch (up->port.iotype) {
+ case UPIO_MEM:
+ if (up->port.mapbase) {
+ /*
+ * Unmap the area.
+ */
+ iounmap(up->port.membase);
+ up->port.membase = NULL;
+
+ start = up->port.mapbase;
+
+ if (size)
+ release_mem_region(start + offset, size);
+ release_mem_region(start, 8 << up->port.regshift);
+ }
+ break;
+
+ case UPIO_PORT:
+ start = up->port.iobase;
+
+ if (size)
+ release_region(start + offset, size);
+ release_region(start + offset, 8 << up->port.regshift);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static int m32r_sio_request_port(struct uart_port *port)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ struct resource *res = NULL;
+ int ret = 0;
+
+ ret = m32r_sio_request_std_resource(up, &res);
+
+ /*
+ * If we have a mapbase, then request that as well.
+ */
+ if (ret == 0 && up->port.flags & UPF_IOREMAP) {
+ int size = resource_size(res);
+
+ up->port.membase = ioremap(up->port.mapbase, size);
+ if (!up->port.membase)
+ ret = -ENOMEM;
+ }
+
+ if (ret < 0) {
+ if (res)
+ release_resource(res);
+ }
+
+ return ret;
+}
+
+static void m32r_sio_config_port(struct uart_port *port, int unused)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
+ up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int
+m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if (ser->irq >= nr_irqs || ser->irq < 0 ||
+ ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+ ser->type >= ARRAY_SIZE(uart_config))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *
+m32r_sio_type(struct uart_port *port)
+{
+ int type = port->type;
+
+ if (type >= ARRAY_SIZE(uart_config))
+ type = 0;
+ return uart_config[type].name;
+}
+
+static struct uart_ops m32r_sio_pops = {
+ .tx_empty = m32r_sio_tx_empty,
+ .set_mctrl = m32r_sio_set_mctrl,
+ .get_mctrl = m32r_sio_get_mctrl,
+ .stop_tx = m32r_sio_stop_tx,
+ .start_tx = m32r_sio_start_tx,
+ .stop_rx = m32r_sio_stop_rx,
+ .enable_ms = m32r_sio_enable_ms,
+ .break_ctl = m32r_sio_break_ctl,
+ .startup = m32r_sio_startup,
+ .shutdown = m32r_sio_shutdown,
+ .set_termios = m32r_sio_set_termios,
+ .pm = m32r_sio_pm,
+ .type = m32r_sio_type,
+ .release_port = m32r_sio_release_port,
+ .request_port = m32r_sio_request_port,
+ .config_port = m32r_sio_config_port,
+ .verify_port = m32r_sio_verify_port,
+};
+
+static struct uart_sio_port m32r_sio_ports[UART_NR];
+
+static void __init m32r_sio_init_ports(void)
+{
+ struct uart_sio_port *up;
+ static int first = 1;
+ int i;
+
+ if (!first)
+ return;
+ first = 0;
+
+ for (i = 0, up = m32r_sio_ports; i < ARRAY_SIZE(old_serial_port);
+ i++, up++) {
+ up->port.iobase = old_serial_port[i].port;
+ up->port.irq = irq_canonicalize(old_serial_port[i].irq);
+ up->port.uartclk = old_serial_port[i].baud_base * 16;
+ up->port.flags = old_serial_port[i].flags;
+ up->port.membase = old_serial_port[i].iomem_base;
+ up->port.iotype = old_serial_port[i].io_type;
+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ up->port.ops = &m32r_sio_pops;
+ }
+}
+
+static void __init m32r_sio_register_ports(struct uart_driver *drv)
+{
+ int i;
+
+ m32r_sio_init_ports();
+
+ for (i = 0; i < UART_NR; i++) {
+ struct uart_sio_port *up = &m32r_sio_ports[i];
+
+ up->port.line = i;
+ up->port.ops = &m32r_sio_pops;
+ init_timer(&up->timer);
+ up->timer.function = m32r_sio_timeout;
+
+ up->mcr_mask = ~0;
+ up->mcr_force = 0;
+
+ uart_add_one_port(drv, &up->port);
+ }
+}
+
+#ifdef CONFIG_SERIAL_M32R_SIO_CONSOLE
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_sio_port *up)
+{
+ unsigned int status, tmout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ do {
+ status = sio_in(up, SIOSTS);
+
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while ((status & UART_EMPTY) != UART_EMPTY);
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ tmout = 1000000;
+ while (--tmout)
+ udelay(1);
+ }
+}
+
+static void m32r_sio_console_putchar(struct uart_port *port, int ch)
+{
+ struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+ wait_for_xmitr(up);
+ sio_out(up, SIOTXB, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void m32r_sio_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_sio_port *up = &m32r_sio_ports[co->index];
+ unsigned int ier;
+
+ /*
+ * First save the UER then disable the interrupts
+ */
+ ier = sio_in(up, SIOTRCR);
+ sio_out(up, SIOTRCR, 0);
+
+ uart_console_write(&up->port, s, count, m32r_sio_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up);
+ sio_out(up, SIOTRCR, ier);
+}
+
+static int __init m32r_sio_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (co->index >= UART_NR)
+ co->index = 0;
+ port = &m32r_sio_ports[co->index].port;
+
+ /*
+ * Temporary fix.
+ */
+ spin_lock_init(&port->lock);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver m32r_sio_reg;
+static struct console m32r_sio_console = {
+ .name = "ttyS",
+ .write = m32r_sio_console_write,
+ .device = uart_console_device,
+ .setup = m32r_sio_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &m32r_sio_reg,
+};
+
+static int __init m32r_sio_console_init(void)
+{
+ sio_reset();
+ sio_init();
+ m32r_sio_init_ports();
+ register_console(&m32r_sio_console);
+ return 0;
+}
+console_initcall(m32r_sio_console_init);
+
+#define M32R_SIO_CONSOLE &m32r_sio_console
+#else
+#define M32R_SIO_CONSOLE NULL
+#endif
+
+static struct uart_driver m32r_sio_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "sio",
+ .dev_name = "ttyS",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = UART_NR,
+ .cons = M32R_SIO_CONSOLE,
+};
+
+/**
+ * m32r_sio_suspend_port - suspend one serial port
+ * @line: serial line number
+ *
+ * Suspend one serial port.
+ */
+void m32r_sio_suspend_port(int line)
+{
+ uart_suspend_port(&m32r_sio_reg, &m32r_sio_ports[line].port);
+}
+
+/**
+ * m32r_sio_resume_port - resume one serial port
+ * @line: serial line number
+ *
+ * Resume one serial port.
+ */
+void m32r_sio_resume_port(int line)
+{
+ uart_resume_port(&m32r_sio_reg, &m32r_sio_ports[line].port);
+}
+
+static int __init m32r_sio_init(void)
+{
+ int ret, i;
+
+ printk(KERN_INFO "Serial: M32R SIO driver\n");
+
+ for (i = 0; i < nr_irqs; i++)
+ spin_lock_init(&irq_lists[i].lock);
+
+ ret = uart_register_driver(&m32r_sio_reg);
+ if (ret >= 0)
+ m32r_sio_register_ports(&m32r_sio_reg);
+
+ return ret;
+}
+
+static void __exit m32r_sio_exit(void)
+{
+ int i;
+
+ for (i = 0; i < UART_NR; i++)
+ uart_remove_one_port(&m32r_sio_reg, &m32r_sio_ports[i].port);
+
+ uart_unregister_driver(&m32r_sio_reg);
+}
+
+module_init(m32r_sio_init);
+module_exit(m32r_sio_exit);
+
+EXPORT_SYMBOL(m32r_sio_suspend_port);
+EXPORT_SYMBOL(m32r_sio_resume_port);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic M32R SIO serial driver");
--- /dev/null
+/*
+ * m32r_sio.h
+ *
+ * Driver for M32R serial ports
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Based on drivers/serial/8250.h.
+ *
+ * Copyright (C) 2001 Russell King.
+ * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ *
+ * 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.
+ */
+
+
+struct m32r_sio_probe {
+ struct module *owner;
+ int (*pci_init_one)(struct pci_dev *dev);
+ void (*pci_remove_one)(struct pci_dev *dev);
+ void (*pnp_init)(void);
+};
+
+int m32r_sio_register_probe(struct m32r_sio_probe *probe);
+void m32r_sio_unregister_probe(struct m32r_sio_probe *probe);
+void m32r_sio_get_irq_map(unsigned int *map);
+void m32r_sio_suspend_port(int line);
+void m32r_sio_resume_port(int line);
+
+struct old_serial_port {
+ unsigned int uart;
+ unsigned int baud_base;
+ unsigned int port;
+ unsigned int irq;
+ unsigned int flags;
+ unsigned char io_type;
+ unsigned char __iomem *iomem_base;
+ unsigned short iomem_reg_shift;
+};
+
+#define _INLINE_ inline
+
+#define PROBE_RSA (1 << 0)
+#define PROBE_ANY (~0)
+
+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
--- /dev/null
+/*
+ * m32r_sio_reg.h
+ *
+ * Copyright (C) 1992, 1994 by Theodore Ts'o.
+ * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ *
+ * These are the UART port assignments, expressed as offsets from the base
+ * register. These assignments should hold for any serial port based on
+ * a 8250, 16450, or 16550(A).
+ */
+
+#ifndef _M32R_SIO_REG_H
+#define _M32R_SIO_REG_H
+
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+
+#define SIOCR 0x000
+#define SIOMOD0 0x002
+#define SIOMOD1 0x004
+#define SIOSTS 0x006
+#define SIOTRCR 0x008
+#define SIOBAUR 0x00a
+// #define SIORBAUR 0x018
+#define SIOTXB 0x00c
+#define SIORXB 0x00e
+
+#define UART_RX ((unsigned long) PLD_ESIO0RXB)
+ /* In: Receive buffer (DLAB=0) */
+#define UART_TX ((unsigned long) PLD_ESIO0TXB)
+ /* Out: Transmit buffer (DLAB=0) */
+#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
+#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
+ * In: Fifo count
+ * Out: Fifo custom trigger levels
+ * XR16C85x only */
+
+#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
+#define UART_IER ((unsigned long) PLD_ESIO0INTCR)
+ /* Out: Interrupt Enable Register */
+#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
+ * XR16C85x only */
+
+#define UART_IIR 0 /* In: Interrupt ID Register */
+#define UART_FCR 0 /* Out: FIFO Control Register */
+#define UART_EFR 0 /* I/O: Extended Features Register */
+ /* (DLAB=1, 16C660 only) */
+
+#define UART_LCR 0 /* Out: Line Control Register */
+#define UART_MCR 0 /* Out: Modem Control Register */
+#define UART_LSR ((unsigned long) PLD_ESIO0STS)
+ /* In: Line Status Register */
+#define UART_MSR 0 /* In: Modem Status Register */
+#define UART_SCR 0 /* I/O: Scratch Register */
+#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
+ * FCTR bit 6 selects SCR or EMSR
+ * XR16c85x only */
+
+#else /* not CONFIG_SERIAL_M32R_PLDSIO */
+
+#define SIOCR 0x000
+#define SIOMOD0 0x004
+#define SIOMOD1 0x008
+#define SIOSTS 0x00c
+#define SIOTRCR 0x010
+#define SIOBAUR 0x014
+#define SIORBAUR 0x018
+#define SIOTXB 0x01c
+#define SIORXB 0x020
+
+#define UART_RX M32R_SIO0_RXB_PORTL /* In: Receive buffer (DLAB=0) */
+#define UART_TX M32R_SIO0_TXB_PORTL /* Out: Transmit buffer (DLAB=0) */
+#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
+#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
+ * In: Fifo count
+ * Out: Fifo custom trigger levels
+ * XR16C85x only */
+
+#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
+#define UART_IER M32R_SIO0_TRCR_PORTL /* Out: Interrupt Enable Register */
+#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
+ * XR16C85x only */
+
+#define UART_IIR 0 /* In: Interrupt ID Register */
+#define UART_FCR 0 /* Out: FIFO Control Register */
+#define UART_EFR 0 /* I/O: Extended Features Register */
+ /* (DLAB=1, 16C660 only) */
+
+#define UART_LCR 0 /* Out: Line Control Register */
+#define UART_MCR 0 /* Out: Modem Control Register */
+#define UART_LSR M32R_SIO0_STS_PORTL /* In: Line Status Register */
+#define UART_MSR 0 /* In: Modem Status Register */
+#define UART_SCR 0 /* I/O: Scratch Register */
+#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
+ * FCTR bit 6 selects SCR or EMSR
+ * XR16c85x only */
+
+#endif /* CONFIG_SERIAL_M32R_PLDSIO */
+
+#define UART_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ * These are the definitions for the Line Control Register
+ *
+ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
+ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
+ */
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+#define UART_LCR_SBC 0x40 /* Set break control */
+#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
+#define UART_LCR_EPAR 0x10 /* Even parity select */
+#define UART_LCR_PARITY 0x08 /* Parity Enable */
+#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
+#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
+#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
+#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
+#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
+
+/*
+ * These are the definitions for the Line Status Register
+ */
+#define UART_LSR_TEMT 0x02 /* Transmitter empty */
+#define UART_LSR_THRE 0x01 /* Transmit-hold-register empty */
+#define UART_LSR_BI 0x00 /* Break interrupt indicator */
+#define UART_LSR_FE 0x80 /* Frame error indicator */
+#define UART_LSR_PE 0x40 /* Parity error indicator */
+#define UART_LSR_OE 0x20 /* Overrun error indicator */
+#define UART_LSR_DR 0x04 /* Receiver data ready */
+
+/*
+ * These are the definitions for the Interrupt Identification Register
+ */
+#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
+
+#define UART_IIR_MSI 0x00 /* Modem status interrupt */
+#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
+#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
+#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
+
+/*
+ * These are the definitions for the Interrupt Enable Register
+ */
+#define UART_IER_MSI 0x00 /* Enable Modem status interrupt */
+#define UART_IER_RLSI 0x08 /* Enable receiver line status interrupt */
+#define UART_IER_THRI 0x03 /* Enable Transmitter holding register int. */
+#define UART_IER_RDI 0x04 /* Enable receiver data interrupt */
+
+#endif /* _M32R_SIO_REG_H */
--- /dev/null
+/*======================================================================
+
+ A driver for PCMCIA serial devices
+
+ serial_cs.c 1.134 2002/05/04 05:48:53
+
+ The contents of this file are subject to the Mozilla Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ The initial developer of the original code is David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the GNU General Public License version 2 (the "GPL"), in which
+ case the provisions of the GPL are applicable instead of the
+ above. If you wish to allow the use of your version of this file
+ only under the terms of the GPL and not to allow others to use
+ your version of this file under the MPL, indicate your decision
+ by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this
+ file under either the MPL or the GPL.
+
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/serial_core.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include "8250.h"
+
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* Enable the speaker? */
+static int do_sound = 1;
+/* Skip strict UART tests? */
+static int buggy_uart;
+
+module_param(do_sound, int, 0444);
+module_param(buggy_uart, int, 0444);
+
+/*====================================================================*/
+
+/* Table of multi-port card ID's */
+
+struct serial_quirk {
+ unsigned int manfid;
+ unsigned int prodid;
+ int multi; /* 1 = multifunction, > 1 = # ports */
+ void (*config)(struct pcmcia_device *);
+ void (*setup)(struct pcmcia_device *, struct uart_port *);
+ void (*wakeup)(struct pcmcia_device *);
+ int (*post)(struct pcmcia_device *);
+};
+
+struct serial_info {
+ struct pcmcia_device *p_dev;
+ int ndev;
+ int multi;
+ int slave;
+ int manfid;
+ int prodid;
+ int c950ctrl;
+ int line[4];
+ const struct serial_quirk *quirk;
+};
+
+struct serial_cfg_mem {
+ tuple_t tuple;
+ cisparse_t parse;
+ u_char buf[256];
+};
+
+/*
+ * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6"
+ * manfid 0x0160, 0x0104
+ * This card appears to have a 14.7456MHz clock.
+ */
+/* Generic Modem: MD55x (GPRS/EDGE) have
+ * Elan VPU16551 UART with 14.7456MHz oscillator
+ * manfid 0x015D, 0x4C45
+ */
+static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
+{
+ port->uartclk = 14745600;
+}
+
+static int quirk_post_ibm(struct pcmcia_device *link)
+{
+ u8 val;
+ int ret;
+
+ ret = pcmcia_read_config_byte(link, 0x800, &val);
+ if (ret)
+ goto failed;
+
+ ret = pcmcia_write_config_byte(link, 0x800, val | 1);
+ if (ret)
+ goto failed;
+ return 0;
+
+ failed:
+ return -ENODEV;
+}
+
+/*
+ * Nokia cards are not really multiport cards. Shouldn't this
+ * be handled by setting the quirk entry .multi = 0 | 1 ?
+ */
+static void quirk_config_nokia(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+
+ if (info->multi > 1)
+ info->multi = 1;
+}
+
+static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+
+ if (info->c950ctrl)
+ outb(12, info->c950ctrl + 1);
+}
+
+/* request_region? oxsemi branch does no request_region too... */
+/*
+ * This sequence is needed to properly initialize MC45 attached to OXCF950.
+ * I tried decreasing these msleep()s, but it worked properly (survived
+ * 1000 stop/start operations) with these timeouts (or bigger).
+ */
+static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ unsigned int ctrl = info->c950ctrl;
+
+ outb(0xA, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(300);
+ outb(0xC, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(200);
+ outb(0xF, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(100);
+ outb(0xC, ctrl + 1);
+}
+
+/*
+ * Socket Dual IO: this enables irq's for second port
+ */
+static void quirk_config_socket(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+
+ if (info->multi)
+ link->config_flags |= CONF_ENABLE_ESR;
+}
+
+static const struct serial_quirk quirks[] = {
+ {
+ .manfid = 0x0160,
+ .prodid = 0x0104,
+ .multi = -1,
+ .setup = quirk_setup_brainboxes_0104,
+ }, {
+ .manfid = 0x015D,
+ .prodid = 0x4C45,
+ .multi = -1,
+ .setup = quirk_setup_brainboxes_0104,
+ }, {
+ .manfid = MANFID_IBM,
+ .prodid = ~0,
+ .multi = -1,
+ .post = quirk_post_ibm,
+ }, {
+ .manfid = MANFID_INTEL,
+ .prodid = PRODID_INTEL_DUAL_RS232,
+ .multi = 2,
+ }, {
+ .manfid = MANFID_NATINST,
+ .prodid = PRODID_NATINST_QUAD_RS232,
+ .multi = 4,
+ }, {
+ .manfid = MANFID_NOKIA,
+ .prodid = ~0,
+ .multi = -1,
+ .config = quirk_config_nokia,
+ }, {
+ .manfid = MANFID_OMEGA,
+ .prodid = PRODID_OMEGA_QSP_100,
+ .multi = 4,
+ }, {
+ .manfid = MANFID_OXSEMI,
+ .prodid = ~0,
+ .multi = -1,
+ .wakeup = quirk_wakeup_oxsemi,
+ }, {
+ .manfid = MANFID_POSSIO,
+ .prodid = PRODID_POSSIO_GCC,
+ .multi = -1,
+ .wakeup = quirk_wakeup_possio_gcc,
+ }, {
+ .manfid = MANFID_QUATECH,
+ .prodid = PRODID_QUATECH_DUAL_RS232,
+ .multi = 2,
+ }, {
+ .manfid = MANFID_QUATECH,
+ .prodid = PRODID_QUATECH_DUAL_RS232_D1,
+ .multi = 2,
+ }, {
+ .manfid = MANFID_QUATECH,
+ .prodid = PRODID_QUATECH_DUAL_RS232_G,
+ .multi = 2,
+ }, {
+ .manfid = MANFID_QUATECH,
+ .prodid = PRODID_QUATECH_QUAD_RS232,
+ .multi = 4,
+ }, {
+ .manfid = MANFID_SOCKET,
+ .prodid = PRODID_SOCKET_DUAL_RS232,
+ .multi = 2,
+ .config = quirk_config_socket,
+ }, {
+ .manfid = MANFID_SOCKET,
+ .prodid = ~0,
+ .multi = -1,
+ .config = quirk_config_socket,
+ }
+};
+
+
+static int serial_config(struct pcmcia_device * link);
+
+
+static void serial_remove(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i;
+
+ dev_dbg(&link->dev, "serial_release\n");
+
+ /*
+ * Recheck to see if the device is still configured.
+ */
+ for (i = 0; i < info->ndev; i++)
+ serial8250_unregister_port(info->line[i]);
+
+ if (!info->slave)
+ pcmcia_disable_device(link);
+}
+
+static int serial_suspend(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i;
+
+ for (i = 0; i < info->ndev; i++)
+ serial8250_suspend_port(info->line[i]);
+
+ return 0;
+}
+
+static int serial_resume(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i;
+
+ for (i = 0; i < info->ndev; i++)
+ serial8250_resume_port(info->line[i]);
+
+ if (info->quirk && info->quirk->wakeup)
+ info->quirk->wakeup(link);
+
+ return 0;
+}
+
+static int serial_probe(struct pcmcia_device *link)
+{
+ struct serial_info *info;
+
+ dev_dbg(&link->dev, "serial_attach()\n");
+
+ /* Create new serial device */
+ info = kzalloc(sizeof (*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->p_dev = link;
+ link->priv = info;
+
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ if (do_sound)
+ link->config_flags |= CONF_ENABLE_SPKR;
+
+ return serial_config(link);
+}
+
+static void serial_detach(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+
+ dev_dbg(&link->dev, "serial_detach\n");
+
+ /*
+ * Ensure that the ports have been released.
+ */
+ serial_remove(link);
+
+ /* free bits */
+ kfree(info);
+}
+
+/*====================================================================*/
+
+static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
+ unsigned int iobase, int irq)
+{
+ struct uart_port port;
+ int line;
+
+ memset(&port, 0, sizeof (struct uart_port));
+ port.iobase = iobase;
+ port.irq = irq;
+ port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+ port.uartclk = 1843200;
+ port.dev = &handle->dev;
+ if (buggy_uart)
+ port.flags |= UPF_BUGGY_UART;
+
+ if (info->quirk && info->quirk->setup)
+ info->quirk->setup(handle, &port);
+
+ line = serial8250_register_port(&port);
+ if (line < 0) {
+ printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
+ "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
+ return -EINVAL;
+ }
+
+ info->line[info->ndev] = line;
+ info->ndev++;
+
+ return 0;
+}
+
+/*====================================================================*/
+
+static int pfc_config(struct pcmcia_device *p_dev)
+{
+ unsigned int port = 0;
+ struct serial_info *info = p_dev->priv;
+
+ if ((p_dev->resource[1]->end != 0) &&
+ (resource_size(p_dev->resource[1]) == 8)) {
+ port = p_dev->resource[1]->start;
+ info->slave = 1;
+ } else if ((info->manfid == MANFID_OSITECH) &&
+ (resource_size(p_dev->resource[0]) == 0x40)) {
+ port = p_dev->resource[0]->start + 0x28;
+ info->slave = 1;
+ }
+ if (info->slave)
+ return setup_serial(p_dev, info, port, p_dev->irq);
+
+ dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
+ return -ENODEV;
+}
+
+static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
+{
+ static const int size_table[2] = { 8, 16 };
+ int *try = priv_data;
+
+ if (p_dev->resource[0]->start == 0)
+ return -ENODEV;
+
+ if ((*try & 0x1) == 0)
+ p_dev->io_lines = 16;
+
+ if (p_dev->resource[0]->end != size_table[(*try >> 1)])
+ return -ENODEV;
+
+ p_dev->resource[0]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ return pcmcia_request_io(p_dev);
+}
+
+static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
+ void *priv_data)
+{
+ static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ int j;
+
+ if (p_dev->io_lines > 3)
+ return -ENODEV;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = 8;
+
+ for (j = 0; j < 5; j++) {
+ p_dev->resource[0]->start = base[j];
+ p_dev->io_lines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev))
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static int simple_config(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i = -ENODEV, try;
+
+ /* First pass: look for a config entry that looks normal.
+ * Two tries: without IO aliases, then with aliases */
+ link->config_flags |= CONF_AUTO_SET_VPP;
+ for (try = 0; try < 4; try++)
+ if (!pcmcia_loop_config(link, simple_config_check, &try))
+ goto found_port;
+
+ /* Second pass: try to find an entry that isn't picky about
+ its base address, then try to grab any standard serial port
+ address, and finally try to get any free port. */
+ if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
+ goto found_port;
+
+ dev_warn(&link->dev, "no usable port range found, giving up\n");
+ return -1;
+
+found_port:
+ if (info->multi && (info->manfid == MANFID_3COM))
+ link->config_index &= ~(0x08);
+
+ /*
+ * Apply any configuration quirks.
+ */
+ if (info->quirk && info->quirk->config)
+ info->quirk->config(link);
+
+ i = pcmcia_enable_device(link);
+ if (i != 0)
+ return -1;
+ return setup_serial(link, info, link->resource[0]->start, link->irq);
+}
+
+static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
+{
+ int *multi = priv_data;
+
+ if (p_dev->resource[1]->end)
+ return -EINVAL;
+
+ /* The quad port cards have bad CIS's, so just look for a
+ window larger than 8 ports and assume it will be right */
+ if (p_dev->resource[0]->end <= 8)
+ return -EINVAL;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = *multi * 8;
+
+ if (pcmcia_request_io(p_dev))
+ return -ENODEV;
+ return 0;
+}
+
+static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
+ void *priv_data)
+{
+ int *base2 = priv_data;
+
+ if (!p_dev->resource[0]->end || !p_dev->resource[1]->end ||
+ p_dev->resource[0]->start + 8 != p_dev->resource[1]->start)
+ return -ENODEV;
+
+ p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ if (pcmcia_request_io(p_dev))
+ return -ENODEV;
+
+ *base2 = p_dev->resource[0]->start + 8;
+ return 0;
+}
+
+static int multi_config(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i, base2 = 0;
+
+ /* First, look for a generic full-sized window */
+ if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
+ base2 = link->resource[0]->start + 8;
+ else {
+ /* If that didn't work, look for two windows */
+ info->multi = 2;
+ if (pcmcia_loop_config(link, multi_config_check_notpicky,
+ &base2)) {
+ dev_warn(&link->dev, "no usable port range "
+ "found, giving up\n");
+ return -ENODEV;
+ }
+ }
+
+ if (!link->irq)
+ dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
+
+ /*
+ * Apply any configuration quirks.
+ */
+ if (info->quirk && info->quirk->config)
+ info->quirk->config(link);
+
+ i = pcmcia_enable_device(link);
+ if (i != 0)
+ return -ENODEV;
+
+ /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
+ * 8 registers are for the UART, the others are extra registers.
+ * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
+ */
+ if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
+ info->prodid == PRODID_POSSIO_GCC)) {
+ int err;
+
+ if (link->config_index == 1 ||
+ link->config_index == 3) {
+ err = setup_serial(link, info, base2,
+ link->irq);
+ base2 = link->resource[0]->start;
+ } else {
+ err = setup_serial(link, info, link->resource[0]->start,
+ link->irq);
+ }
+ info->c950ctrl = base2;
+
+ /*
+ * FIXME: We really should wake up the port prior to
+ * handing it over to the serial layer.
+ */
+ if (info->quirk && info->quirk->wakeup)
+ info->quirk->wakeup(link);
+
+ return 0;
+ }
+
+ setup_serial(link, info, link->resource[0]->start, link->irq);
+ for (i = 0; i < info->multi - 1; i++)
+ setup_serial(link, info, base2 + (8 * i),
+ link->irq);
+ return 0;
+}
+
+static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data)
+{
+ struct serial_info *info = p_dev->priv;
+
+ if (!p_dev->resource[0]->end)
+ return -EINVAL;
+
+ if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
+ info->multi = p_dev->resource[0]->end >> 3;
+
+ if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
+ && (p_dev->resource[1]->end == 8))
+ info->multi = 2;
+
+ return 0; /* break */
+}
+
+
+static int serial_config(struct pcmcia_device * link)
+{
+ struct serial_info *info = link->priv;
+ int i;
+
+ dev_dbg(&link->dev, "serial_config\n");
+
+ /* Is this a compliant multifunction card? */
+ info->multi = (link->socket->functions > 1);
+
+ /* Is this a multiport card? */
+ info->manfid = link->manf_id;
+ info->prodid = link->card_id;
+
+ for (i = 0; i < ARRAY_SIZE(quirks); i++)
+ if ((quirks[i].manfid == ~0 ||
+ quirks[i].manfid == info->manfid) &&
+ (quirks[i].prodid == ~0 ||
+ quirks[i].prodid == info->prodid)) {
+ info->quirk = &quirks[i];
+ break;
+ }
+
+ /* Another check for dual-serial cards: look for either serial or
+ multifunction cards that ask for appropriate IO port ranges */
+ if ((info->multi == 0) &&
+ (link->has_func_id) &&
+ (link->socket->pcmcia_pfc == 0) &&
+ ((link->func_id == CISTPL_FUNCID_MULTI) ||
+ (link->func_id == CISTPL_FUNCID_SERIAL)))
+ pcmcia_loop_config(link, serial_check_for_multi, info);
+
+ /*
+ * Apply any multi-port quirk.
+ */
+ if (info->quirk && info->quirk->multi != -1)
+ info->multi = info->quirk->multi;
+
+ dev_info(&link->dev,
+ "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
+ link->manf_id, link->card_id,
+ link->socket->pcmcia_pfc, info->multi, info->quirk);
+ if (link->socket->pcmcia_pfc)
+ i = pfc_config(link);
+ else if (info->multi > 1)
+ i = multi_config(link);
+ else
+ i = simple_config(link);
+
+ if (i || info->ndev == 0)
+ goto failed;
+
+ /*
+ * Apply any post-init quirk. FIXME: This should really happen
+ * before we register the port, since it might already be in use.
+ */
+ if (info->quirk && info->quirk->post)
+ if (info->quirk->post(link))
+ goto failed;
+
+ return 0;
+
+failed:
+ dev_warn(&link->dev, "failed to initialize\n");
+ serial_remove(link);
+ return -ENODEV;
+}
+
+static const struct pcmcia_device_id serial_ids[] = {
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
+ PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
+ PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
+ PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
+ PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
+ PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
+ PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
+ PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
+ PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
+ PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0b05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
+ PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
+ PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
+ PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
+ PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
+ PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
+ PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
+ PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
+ PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
+ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
+ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
+ PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
+ PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
+ PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
+ PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
+ PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
+ PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
+ PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
+ PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
+ PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
+ PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
+ PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
+ PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
+ PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
+ PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
+ PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
+ PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
+ PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
+ PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
+ PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
+ PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
+ PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
+ PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
+ PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
+ PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
+ PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
+ PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
+ PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
+ PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
+ PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
+ PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
+ PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
+ PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
+ PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
+ PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
+ PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
+ PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
+ PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
+ PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
+ PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
+ PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
+ PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
+ PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
+ PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
+ PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
+ PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
+ PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC860", 0xd85f6206, 0x698f93db, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC860 3G Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
+ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
+ PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b),
+ PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
+ PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490),
+ PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235),
+ PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3),
+ PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676),
+ PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
+ PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+ PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+ PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+ PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
+ /* too generic */
+ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
+ /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
+ PCMCIA_DEVICE_FUNC_ID(2),
+ PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, serial_ids);
+
+MODULE_FIRMWARE("cis/PCMLM28.cis");
+MODULE_FIRMWARE("cis/DP83903.cis");
+MODULE_FIRMWARE("cis/3CCFEM556.cis");
+MODULE_FIRMWARE("cis/3CXEM556.cis");
+MODULE_FIRMWARE("cis/SW_8xx_SER.cis");
+MODULE_FIRMWARE("cis/SW_7xx_SER.cis");
+MODULE_FIRMWARE("cis/SW_555_SER.cis");
+MODULE_FIRMWARE("cis/MT5634ZLX.cis");
+MODULE_FIRMWARE("cis/COMpad2.cis");
+MODULE_FIRMWARE("cis/COMpad4.cis");
+MODULE_FIRMWARE("cis/RS-COM-2P.cis");
+
+static struct pcmcia_driver serial_cs_driver = {
+ .owner = THIS_MODULE,
+ .name = "serial_cs",
+ .probe = serial_probe,
+ .remove = serial_detach,
+ .id_table = serial_ids,
+ .suspend = serial_suspend,
+ .resume = serial_resume,
+};
+
+static int __init init_serial_cs(void)
+{
+ return pcmcia_register_driver(&serial_cs_driver);
+}
+
+static void __exit exit_serial_cs(void)
+{
+ pcmcia_unregister_driver(&serial_cs_driver);
+}
+
+module_init(init_serial_cs);
+module_exit(exit_serial_cs);
+
+MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF, \
- }
-
-static struct plat_serial8250_port accent_data[] = {
- PORT(0x330, 4),
- PORT(0x338, 4),
- { },
-};
-
-static struct platform_device accent_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_ACCENT,
- .dev = {
- .platform_data = accent_data,
- },
-};
-
-static int __init accent_init(void)
-{
- return platform_device_register(&accent_device);
-}
-
-module_init(accent_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Accent Async cards");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * linux/drivers/serial/acorn.c
- *
- * Copyright (C) 1996-2003 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/ecard.h>
-#include <asm/string.h>
-
-#include "8250.h"
-
-#define MAX_PORTS 3
-
-struct serial_card_type {
- unsigned int num_ports;
- unsigned int uartclk;
- unsigned int type;
- unsigned int offset[MAX_PORTS];
-};
-
-struct serial_card_info {
- unsigned int num_ports;
- int ports[MAX_PORTS];
- void __iomem *vaddr;
-};
-
-static int __devinit
-serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
- struct serial_card_info *info;
- struct serial_card_type *type = id->data;
- struct uart_port port;
- unsigned long bus_addr;
- unsigned int i;
-
- info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- info->num_ports = type->num_ports;
-
- bus_addr = ecard_resource_start(ec, type->type);
- info->vaddr = ecardm_iomap(ec, type->type, 0, 0);
- if (!info->vaddr) {
- kfree(info);
- return -ENOMEM;
- }
-
- ecard_set_drvdata(ec, info);
-
- memset(&port, 0, sizeof(struct uart_port));
- port.irq = ec->irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- port.uartclk = type->uartclk;
- port.iotype = UPIO_MEM;
- port.regshift = 2;
- port.dev = &ec->dev;
-
- for (i = 0; i < info->num_ports; i ++) {
- port.membase = info->vaddr + type->offset[i];
- port.mapbase = bus_addr + type->offset[i];
-
- info->ports[i] = serial8250_register_port(&port);
- }
-
- return 0;
-}
-
-static void __devexit serial_card_remove(struct expansion_card *ec)
-{
- struct serial_card_info *info = ecard_get_drvdata(ec);
- int i;
-
- ecard_set_drvdata(ec, NULL);
-
- for (i = 0; i < info->num_ports; i++)
- if (info->ports[i] > 0)
- serial8250_unregister_port(info->ports[i]);
-
- kfree(info);
-}
-
-static struct serial_card_type atomwide_type = {
- .num_ports = 3,
- .uartclk = 7372800,
- .type = ECARD_RES_IOCSLOW,
- .offset = { 0x2800, 0x2400, 0x2000 },
-};
-
-static struct serial_card_type serport_type = {
- .num_ports = 2,
- .uartclk = 3686400,
- .type = ECARD_RES_IOCSLOW,
- .offset = { 0x2000, 0x2020 },
-};
-
-static const struct ecard_id serial_cids[] = {
- { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, &atomwide_type },
- { MANU_SERPORT, PROD_SERPORT_DSPORT, &serport_type },
- { 0xffff, 0xffff }
-};
-
-static struct ecard_driver serial_card_driver = {
- .probe = serial_card_probe,
- .remove = __devexit_p(serial_card_remove),
- .id_table = serial_cids,
- .drv = {
- .name = "8250_acorn",
- },
-};
-
-static int __init serial_card_init(void)
-{
- return ecard_register_driver(&serial_card_driver);
-}
-
-static void __exit serial_card_exit(void)
-{
- ecard_remove_driver(&serial_card_driver);
-}
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
-MODULE_LICENSE("GPL");
-
-module_init(serial_card_init);
-module_exit(serial_card_exit);
+++ /dev/null
-/*
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF, \
- }
-
-static struct plat_serial8250_port boca_data[] = {
- PORT(0x100, 12),
- PORT(0x108, 12),
- PORT(0x110, 12),
- PORT(0x118, 12),
- PORT(0x120, 12),
- PORT(0x128, 12),
- PORT(0x130, 12),
- PORT(0x138, 12),
- PORT(0x140, 12),
- PORT(0x148, 12),
- PORT(0x150, 12),
- PORT(0x158, 12),
- PORT(0x160, 12),
- PORT(0x168, 12),
- PORT(0x170, 12),
- PORT(0x178, 12),
- { },
-};
-
-static struct platform_device boca_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_BOCA,
- .dev = {
- .platform_data = boca_data,
- },
-};
-
-static int __init boca_init(void)
-{
- return platform_device_register(&boca_device);
-}
-
-module_init(boca_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Boca cards");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Synopsys DesignWare 8250 driver.
- *
- * Copyright 2011 Picochip, Jamie Iles.
- *
- * 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.
- *
- * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
- * LCR is written whilst busy. If it is, then a busy detect interrupt is
- * raised, the LCR needs to be rewritten and the uart status register read.
- */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-struct dw8250_data {
- int last_lcr;
- int line;
-};
-
-static void dw8250_serial_out(struct uart_port *p, int offset, int value)
-{
- struct dw8250_data *d = p->private_data;
-
- if (offset == UART_LCR)
- d->last_lcr = value;
-
- offset <<= p->regshift;
- writeb(value, p->membase + offset);
-}
-
-static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
-{
- offset <<= p->regshift;
-
- return readb(p->membase + offset);
-}
-
-static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
-{
- struct dw8250_data *d = p->private_data;
-
- if (offset == UART_LCR)
- d->last_lcr = value;
-
- offset <<= p->regshift;
- writel(value, p->membase + offset);
-}
-
-static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
-{
- offset <<= p->regshift;
-
- return readl(p->membase + offset);
-}
-
-/* Offset for the DesignWare's UART Status Register. */
-#define UART_USR 0x1f
-
-static int dw8250_handle_irq(struct uart_port *p)
-{
- struct dw8250_data *d = p->private_data;
- unsigned int iir = p->serial_in(p, UART_IIR);
-
- if (serial8250_handle_irq(p, iir)) {
- return 1;
- } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
- /* Clear the USR and write the LCR again. */
- (void)p->serial_in(p, UART_USR);
- p->serial_out(p, d->last_lcr, UART_LCR);
-
- return 1;
- }
-
- return 0;
-}
-
-static int __devinit dw8250_probe(struct platform_device *pdev)
-{
- struct uart_port port = {};
- struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- struct device_node *np = pdev->dev.of_node;
- u32 val;
- struct dw8250_data *data;
-
- if (!regs || !irq) {
- dev_err(&pdev->dev, "no registers/irq defined\n");
- return -EINVAL;
- }
-
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- port.private_data = data;
-
- spin_lock_init(&port.lock);
- port.mapbase = regs->start;
- port.irq = irq->start;
- port.handle_irq = dw8250_handle_irq;
- port.type = PORT_8250;
- port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
- UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port.dev = &pdev->dev;
-
- port.iotype = UPIO_MEM;
- port.serial_in = dw8250_serial_in;
- port.serial_out = dw8250_serial_out;
- if (!of_property_read_u32(np, "reg-io-width", &val)) {
- switch (val) {
- case 1:
- break;
- case 4:
- port.iotype = UPIO_MEM32;
- port.serial_in = dw8250_serial_in32;
- port.serial_out = dw8250_serial_out32;
- break;
- default:
- dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
- val);
- return -EINVAL;
- }
- }
-
- if (!of_property_read_u32(np, "reg-shift", &val))
- port.regshift = val;
-
- if (of_property_read_u32(np, "clock-frequency", &val)) {
- dev_err(&pdev->dev, "no clock-frequency property set\n");
- return -EINVAL;
- }
- port.uartclk = val;
-
- data->line = serial8250_register_port(&port);
- if (data->line < 0)
- return data->line;
-
- platform_set_drvdata(pdev, data);
-
- return 0;
-}
-
-static int __devexit dw8250_remove(struct platform_device *pdev)
-{
- struct dw8250_data *data = platform_get_drvdata(pdev);
-
- serial8250_unregister_port(data->line);
-
- return 0;
-}
-
-static const struct of_device_id dw8250_match[] = {
- { .compatible = "snps,dw-apb-uart" },
- { /* Sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, dw8250_match);
-
-static struct platform_driver dw8250_platform_driver = {
- .driver = {
- .name = "dw-apb-uart",
- .owner = THIS_MODULE,
- .of_match_table = dw8250_match,
- },
- .probe = dw8250_probe,
- .remove = __devexit_p(dw8250_remove),
-};
-
-module_platform_driver(dw8250_platform_driver);
-
-MODULE_AUTHOR("Jamie Iles");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
+++ /dev/null
-/*
- * Early serial console for 8250/16550 devices
- *
- * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
- * and on early_printk.c by Andi Kleen.
- *
- * This is for use before the serial driver has initialized, in
- * particular, before the UARTs have been discovered and named.
- * Instead of specifying the console device as, e.g., "ttyS0",
- * we locate the device directly by its MMIO or I/O port address.
- *
- * The user can specify the device directly, e.g.,
- * earlycon=uart8250,io,0x3f8,9600n8
- * earlycon=uart8250,mmio,0xff5e0000,115200n8
- * earlycon=uart8250,mmio32,0xff5e0000,115200n8
- * or
- * console=uart8250,io,0x3f8,9600n8
- * console=uart8250,mmio,0xff5e0000,115200n8
- * console=uart8250,mmio32,0xff5e0000,115200n8
- */
-
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <asm/io.h>
-#include <asm/serial.h>
-#ifdef CONFIG_FIX_EARLYCON_MEM
-#include <asm/pgtable.h>
-#include <asm/fixmap.h>
-#endif
-
-struct early_serial8250_device {
- struct uart_port port;
- char options[16]; /* e.g., 115200n8 */
- unsigned int baud;
-};
-
-static struct early_serial8250_device early_device;
-
-static unsigned int __init serial_in(struct uart_port *port, int offset)
-{
- switch (port->iotype) {
- case UPIO_MEM:
- return readb(port->membase + offset);
- case UPIO_MEM32:
- return readl(port->membase + (offset << 2));
- case UPIO_PORT:
- return inb(port->iobase + offset);
- default:
- return 0;
- }
-}
-
-static void __init serial_out(struct uart_port *port, int offset, int value)
-{
- switch (port->iotype) {
- case UPIO_MEM:
- writeb(value, port->membase + offset);
- break;
- case UPIO_MEM32:
- writel(value, port->membase + (offset << 2));
- break;
- case UPIO_PORT:
- outb(value, port->iobase + offset);
- break;
- }
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void __init wait_for_xmitr(struct uart_port *port)
-{
- unsigned int status;
-
- for (;;) {
- status = serial_in(port, UART_LSR);
- if ((status & BOTH_EMPTY) == BOTH_EMPTY)
- return;
- cpu_relax();
- }
-}
-
-static void __init serial_putc(struct uart_port *port, int c)
-{
- wait_for_xmitr(port);
- serial_out(port, UART_TX, c);
-}
-
-static void __init early_serial8250_write(struct console *console,
- const char *s, unsigned int count)
-{
- struct uart_port *port = &early_device.port;
- unsigned int ier;
-
- /* Save the IER and disable interrupts */
- ier = serial_in(port, UART_IER);
- serial_out(port, UART_IER, 0);
-
- uart_console_write(port, s, count, serial_putc);
-
- /* Wait for transmitter to become empty and restore the IER */
- wait_for_xmitr(port);
- serial_out(port, UART_IER, ier);
-}
-
-static unsigned int __init probe_baud(struct uart_port *port)
-{
- unsigned char lcr, dll, dlm;
- unsigned int quot;
-
- lcr = serial_in(port, UART_LCR);
- serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
- dll = serial_in(port, UART_DLL);
- dlm = serial_in(port, UART_DLM);
- serial_out(port, UART_LCR, lcr);
-
- quot = (dlm << 8) | dll;
- return (port->uartclk / 16) / quot;
-}
-
-static void __init init_port(struct early_serial8250_device *device)
-{
- struct uart_port *port = &device->port;
- unsigned int divisor;
- unsigned char c;
-
- serial_out(port, UART_LCR, 0x3); /* 8n1 */
- serial_out(port, UART_IER, 0); /* no interrupt */
- serial_out(port, UART_FCR, 0); /* no fifo */
- serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
-
- divisor = port->uartclk / (16 * device->baud);
- c = serial_in(port, UART_LCR);
- serial_out(port, UART_LCR, c | UART_LCR_DLAB);
- serial_out(port, UART_DLL, divisor & 0xff);
- serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
- serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
-}
-
-static int __init parse_options(struct early_serial8250_device *device,
- char *options)
-{
- struct uart_port *port = &device->port;
- int mmio, mmio32, length;
-
- if (!options)
- return -ENODEV;
-
- port->uartclk = BASE_BAUD * 16;
-
- mmio = !strncmp(options, "mmio,", 5);
- mmio32 = !strncmp(options, "mmio32,", 7);
- if (mmio || mmio32) {
- port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
- port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
- &options, 0);
- if (mmio32)
- port->regshift = 2;
-#ifdef CONFIG_FIX_EARLYCON_MEM
- set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
- port->mapbase & PAGE_MASK);
- port->membase =
- (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
- port->membase += port->mapbase & ~PAGE_MASK;
-#else
- port->membase = ioremap_nocache(port->mapbase, 64);
- if (!port->membase) {
- printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
- __func__,
- (unsigned long long) port->mapbase);
- return -ENOMEM;
- }
-#endif
- } else if (!strncmp(options, "io,", 3)) {
- port->iotype = UPIO_PORT;
- port->iobase = simple_strtoul(options + 3, &options, 0);
- mmio = 0;
- } else
- return -EINVAL;
-
- options = strchr(options, ',');
- if (options) {
- options++;
- device->baud = simple_strtoul(options, NULL, 0);
- length = min(strcspn(options, " "), sizeof(device->options));
- strncpy(device->options, options, length);
- } else {
- device->baud = probe_baud(port);
- snprintf(device->options, sizeof(device->options), "%u",
- device->baud);
- }
-
- if (mmio || mmio32)
- printk(KERN_INFO
- "Early serial console at MMIO%s 0x%llx (options '%s')\n",
- mmio32 ? "32" : "",
- (unsigned long long)port->mapbase,
- device->options);
- else
- printk(KERN_INFO
- "Early serial console at I/O port 0x%lx (options '%s')\n",
- port->iobase,
- device->options);
-
- return 0;
-}
-
-static struct console early_serial8250_console __initdata = {
- .name = "uart",
- .write = early_serial8250_write,
- .flags = CON_PRINTBUFFER | CON_BOOT,
- .index = -1,
-};
-
-static int __init early_serial8250_setup(char *options)
-{
- struct early_serial8250_device *device = &early_device;
- int err;
-
- if (device->port.membase || device->port.iobase)
- return 0;
-
- err = parse_options(device, options);
- if (err < 0)
- return err;
-
- init_port(device);
- return 0;
-}
-
-int __init setup_early_serial8250_console(char *cmdline)
-{
- char *options;
- int err;
-
- options = strstr(cmdline, "uart8250,");
- if (!options) {
- options = strstr(cmdline, "uart,");
- if (!options)
- return 0;
- }
-
- options = strchr(cmdline, ',') + 1;
- err = early_serial8250_setup(options);
- if (err < 0)
- return err;
-
- register_console(&early_serial8250_console);
-
- return 0;
-}
-
-int serial8250_find_port_for_earlycon(void)
-{
- struct early_serial8250_device *device = &early_device;
- struct uart_port *port = &device->port;
- int line;
- int ret;
-
- if (!device->port.membase && !device->port.iobase)
- return -ENODEV;
-
- line = serial8250_find_port(port);
- if (line < 0)
- return -ENODEV;
-
- ret = update_console_cmdline("uart", 8250,
- "ttyS", line, device->options);
- if (ret < 0)
- ret = update_console_cmdline("uart", 0,
- "ttyS", line, device->options);
-
- return ret;
-}
-
-early_param("earlycon", setup_early_serial8250_console);
+++ /dev/null
-/*
- * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
- * Based on 8250_boca.
- *
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF, \
- }
-
-static struct plat_serial8250_port exar_data[] = {
- PORT(0x100, 5),
- PORT(0x108, 5),
- PORT(0x110, 5),
- PORT(0x118, 5),
- { },
-};
-
-static struct platform_device exar_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_EXAR_ST16C554,
- .dev = {
- .platform_data = exar_data,
- },
-};
-
-static int __init exar_init(void)
-{
- return platform_device_register(&exar_device);
-}
-
-module_init(exar_init);
-
-MODULE_AUTHOR("Paul B Schroeder");
-MODULE_DESCRIPTION("8250 serial probe module for Exar cards");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \
- }
-
-static struct plat_serial8250_port fourport_data[] = {
- PORT(0x1a0, 9),
- PORT(0x1a8, 9),
- PORT(0x1b0, 9),
- PORT(0x1b8, 9),
- PORT(0x2a0, 5),
- PORT(0x2a8, 5),
- PORT(0x2b0, 5),
- PORT(0x2b8, 5),
- { },
-};
-
-static struct platform_device fourport_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_FOURPORT,
- .dev = {
- .platform_data = fourport_data,
- },
-};
-
-static int __init fourport_init(void)
-{
- return platform_device_register(&fourport_device);
-}
-
-module_init(fourport_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for AST Fourport cards");
-MODULE_LICENSE("GPL");
+++ /dev/null
-#include <linux/serial_reg.h>
-#include <linux/serial_8250.h>
-
-#include "8250.h"
-
-/*
- * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This isn't a full driver; it just provides an alternate IRQ
- * handler to deal with an errata. Everything else is just
- * using the bog standard 8250 support.
- *
- * We follow code flow of serial8250_default_handle_irq() but add
- * a check for a break and insert a dummy read on the Rx for the
- * immediately following IRQ event.
- *
- * We re-use the already existing "bug handling" lsr_saved_flags
- * field to carry the "what we just did" information from the one
- * IRQ event to the next one.
- */
-
-int fsl8250_handle_irq(struct uart_port *port)
-{
- unsigned char lsr, orig_lsr;
- unsigned long flags;
- unsigned int iir;
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- iir = port->serial_in(port, UART_IIR);
- if (iir & UART_IIR_NO_INT) {
- spin_unlock_irqrestore(&up->port.lock, flags);
- return 0;
- }
-
- /* This is the WAR; if last event was BRK, then read and return */
- if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
- up->lsr_saved_flags &= ~UART_LSR_BI;
- port->serial_in(port, UART_RX);
- spin_unlock_irqrestore(&up->port.lock, flags);
- return 1;
- }
-
- lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR);
-
- if (lsr & (UART_LSR_DR | UART_LSR_BI))
- lsr = serial8250_rx_chars(up, lsr);
-
- serial8250_modem_status(up);
-
- if (lsr & UART_LSR_THRE)
- serial8250_tx_chars(up);
-
- up->lsr_saved_flags = orig_lsr;
- spin_unlock_irqrestore(&up->port.lock, flags);
- return 1;
-}
+++ /dev/null
-/*
- * Serial Device Initialisation for Lasi/Asp/Wax/Dino
- *
- * (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002
- *
- * 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.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/serial_core.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-
-#include <asm/hardware.h>
-#include <asm/parisc-device.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-static int __init serial_init_chip(struct parisc_device *dev)
-{
- struct uart_port port;
- unsigned long address;
- int err;
-
- if (!dev->irq) {
- /* We find some unattached serial ports by walking native
- * busses. These should be silently ignored. Otherwise,
- * what we have here is a missing parent device, so tell
- * the user what they're missing.
- */
- if (parisc_parent(dev)->id.hw_type != HPHW_IOA)
- printk(KERN_INFO
- "Serial: device 0x%llx not configured.\n"
- "Enable support for Wax, Lasi, Asp or Dino.\n",
- (unsigned long long)dev->hpa.start);
- return -ENODEV;
- }
-
- address = dev->hpa.start;
- if (dev->id.sversion != 0x8d)
- address += 0x800;
-
- memset(&port, 0, sizeof(port));
- port.iotype = UPIO_MEM;
- /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
- port.uartclk = 7272727;
- port.mapbase = address;
- port.membase = ioremap_nocache(address, 16);
- port.irq = dev->irq;
- port.flags = UPF_BOOT_AUTOCONF;
- port.dev = &dev->dev;
-
- err = serial8250_register_port(&port);
- if (err < 0) {
- printk(KERN_WARNING
- "serial8250_register_port returned error %d\n", err);
- iounmap(port.membase);
- return err;
- }
-
- return 0;
-}
-
-static struct parisc_device_id serial_tbl[] = {
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 },
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c },
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d },
- { 0 }
-};
-
-/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1
- * attached to Dino. Unfortunately, Dino appears before Lasi in the device
- * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one
- * which only knows about Lasi and then a second which will find all the
- * other serial ports. HPUX ignores this problem.
- */
-static struct parisc_device_id lasi_tbl[] = {
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */
- { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */
- { 0 }
-};
-
-
-MODULE_DEVICE_TABLE(parisc, serial_tbl);
-
-static struct parisc_driver lasi_driver = {
- .name = "serial_1",
- .id_table = lasi_tbl,
- .probe = serial_init_chip,
-};
-
-static struct parisc_driver serial_driver = {
- .name = "serial",
- .id_table = serial_tbl,
- .probe = serial_init_chip,
-};
-
-static int __init probe_serial_gsc(void)
-{
- register_parisc_driver(&lasi_driver);
- register_parisc_driver(&serial_driver);
- return 0;
-}
-
-module_init(probe_serial_gsc);
-
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Driver for the 98626/98644/internal serial interface on hp300/hp400
- * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
- *
- * Ported from 2.2 and modified to use the normal 8250 driver
- * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-#include <linux/dio.h>
-#include <linux/console.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
-#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
-#endif
-
-#ifdef CONFIG_HPAPCI
-struct hp300_port
-{
- struct hp300_port *next; /* next port */
- int line; /* line (tty) number */
-};
-
-static struct hp300_port *hp300_ports;
-#endif
-
-#ifdef CONFIG_HPDCA
-
-static int __devinit hpdca_init_one(struct dio_dev *d,
- const struct dio_device_id *ent);
-static void __devexit hpdca_remove_one(struct dio_dev *d);
-
-static struct dio_device_id hpdca_dio_tbl[] = {
- { DIO_ID_DCA0 },
- { DIO_ID_DCA0REM },
- { DIO_ID_DCA1 },
- { DIO_ID_DCA1REM },
- { 0 }
-};
-
-static struct dio_driver hpdca_driver = {
- .name = "hpdca",
- .id_table = hpdca_dio_tbl,
- .probe = hpdca_init_one,
- .remove = __devexit_p(hpdca_remove_one),
-};
-
-#endif
-
-static unsigned int num_ports;
-
-extern int hp300_uart_scode;
-
-/* Offset to UART registers from base of DCA */
-#define UART_OFFSET 17
-
-#define DCA_ID 0x01 /* ID (read), reset (write) */
-#define DCA_IC 0x03 /* Interrupt control */
-
-/* Interrupt control */
-#define DCA_IC_IE 0x80 /* Master interrupt enable */
-
-#define HPDCA_BAUD_BASE 153600
-
-/* Base address of the Frodo part */
-#define FRODO_BASE (0x41c000)
-
-/*
- * Where we find the 8250-like APCI ports, and how far apart they are.
- */
-#define FRODO_APCIBASE 0x0
-#define FRODO_APCISPACE 0x20
-#define FRODO_APCI_OFFSET(x) (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
-
-#define HPAPCI_BAUD_BASE 500400
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-/*
- * Parse the bootinfo to find descriptions for headless console and
- * debug serial ports and register them with the 8250 driver.
- * This function should be called before serial_console_init() is called
- * to make sure the serial console will be available for use. IA-64 kernel
- * calls this function from setup_arch() after the EFI and ACPI tables have
- * been parsed.
- */
-int __init hp300_setup_serial_console(void)
-{
- int scode;
- struct uart_port port;
-
- memset(&port, 0, sizeof(port));
-
- if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
- return 0;
-
- if (DIO_SCINHOLE(hp300_uart_scode))
- return 0;
-
- scode = hp300_uart_scode;
-
- /* Memory mapped I/O */
- port.iotype = UPIO_MEM;
- port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
- port.type = PORT_UNKNOWN;
-
- /* Check for APCI console */
- if (scode == 256) {
-#ifdef CONFIG_HPAPCI
- printk(KERN_INFO "Serial console is HP APCI 1\n");
-
- port.uartclk = HPAPCI_BAUD_BASE * 16;
- port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
- port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
- port.regshift = 2;
- add_preferred_console("ttyS", port.line, "9600n8");
-#else
- printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
- return 0;
-#endif
- } else {
-#ifdef CONFIG_HPDCA
- unsigned long pa = dio_scodetophysaddr(scode);
- if (!pa)
- return 0;
-
- printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
-
- port.uartclk = HPDCA_BAUD_BASE * 16;
- port.mapbase = (pa + UART_OFFSET);
- port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
- port.regshift = 1;
- port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
-
- /* Enable board-interrupts */
- out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
-
- if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
- add_preferred_console("ttyS", port.line, "9600n8");
-#else
- printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
- return 0;
-#endif
- }
-
- if (early_serial_setup(&port) < 0)
- printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
- return 0;
-}
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
-#ifdef CONFIG_HPDCA
-static int __devinit hpdca_init_one(struct dio_dev *d,
- const struct dio_device_id *ent)
-{
- struct uart_port port;
- int line;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (hp300_uart_scode == d->scode) {
- /* Already got it. */
- return 0;
- }
-#endif
- memset(&port, 0, sizeof(struct uart_port));
-
- /* Memory mapped I/O */
- port.iotype = UPIO_MEM;
- port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
- port.irq = d->ipl;
- port.uartclk = HPDCA_BAUD_BASE * 16;
- port.mapbase = (d->resource.start + UART_OFFSET);
- port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
- port.regshift = 1;
- port.dev = &d->dev;
- line = serial8250_register_port(&port);
-
- if (line < 0) {
- printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
- " irq %d failed\n", d->scode, port.irq);
- return -ENOMEM;
- }
-
- /* Enable board-interrupts */
- out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
- dio_set_drvdata(d, (void *)line);
-
- /* Reset the DCA */
- out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
- udelay(100);
-
- num_ports++;
-
- return 0;
-}
-#endif
-
-static int __init hp300_8250_init(void)
-{
- static int called;
-#ifdef CONFIG_HPAPCI
- int line;
- unsigned long base;
- struct uart_port uport;
- struct hp300_port *port;
- int i;
-#endif
- if (called)
- return -ENODEV;
- called = 1;
-
- if (!MACH_IS_HP300)
- return -ENODEV;
-
-#ifdef CONFIG_HPDCA
- dio_register_driver(&hpdca_driver);
-#endif
-#ifdef CONFIG_HPAPCI
- if (hp300_model < HP_400) {
- if (!num_ports)
- return -ENODEV;
- return 0;
- }
- /* These models have the Frodo chip.
- * Port 0 is reserved for the Apollo Domain keyboard.
- * Port 1 is either the console or the DCA.
- */
- for (i = 1; i < 4; i++) {
- /* Port 1 is the console on a 425e, on other machines it's
- * mapped to DCA.
- */
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (i == 1)
- continue;
-#endif
-
- /* Create new serial device */
- port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- memset(&uport, 0, sizeof(struct uart_port));
-
- base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
-
- /* Memory mapped I/O */
- uport.iotype = UPIO_MEM;
- uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
- | UPF_BOOT_AUTOCONF;
- /* XXX - no interrupt support yet */
- uport.irq = 0;
- uport.uartclk = HPAPCI_BAUD_BASE * 16;
- uport.mapbase = base;
- uport.membase = (char *)(base + DIO_VIRADDRBASE);
- uport.regshift = 2;
-
- line = serial8250_register_port(&uport);
-
- if (line < 0) {
- printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
- " %d irq %d failed\n", i, uport.irq);
- kfree(port);
- continue;
- }
-
- port->line = line;
- port->next = hp300_ports;
- hp300_ports = port;
-
- num_ports++;
- }
-#endif
-
- /* Any boards found? */
- if (!num_ports)
- return -ENODEV;
-
- return 0;
-}
-
-#ifdef CONFIG_HPDCA
-static void __devexit hpdca_remove_one(struct dio_dev *d)
-{
- int line;
-
- line = (int) dio_get_drvdata(d);
- if (d->resource.start) {
- /* Disable board-interrupts */
- out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
- }
- serial8250_unregister_port(line);
-}
-#endif
-
-static void __exit hp300_8250_exit(void)
-{
-#ifdef CONFIG_HPAPCI
- struct hp300_port *port, *to_free;
-
- for (port = hp300_ports; port; ) {
- serial8250_unregister_port(port->line);
- to_free = port;
- port = port->next;
- kfree(to_free);
- }
-
- hp300_ports = NULL;
-#endif
-#ifdef CONFIG_HPDCA
- dio_unregister_driver(&hpdca_driver);
-#endif
-}
-
-module_init(hp300_8250_init);
-module_exit(hp300_8250_exit);
-MODULE_DESCRIPTION("HP DCA/APCI serial driver");
-MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define HUB6(card,port) \
- { \
- .iobase = 0x302, \
- .irq = 3, \
- .uartclk = 1843200, \
- .iotype = UPIO_HUB6, \
- .flags = UPF_BOOT_AUTOCONF, \
- .hub6 = (card) << 6 | (port) << 3 | 1, \
- }
-
-static struct plat_serial8250_port hub6_data[] = {
- HUB6(0, 0),
- HUB6(0, 1),
- HUB6(0, 2),
- HUB6(0, 3),
- HUB6(0, 4),
- HUB6(0, 5),
- HUB6(1, 0),
- HUB6(1, 1),
- HUB6(1, 2),
- HUB6(1, 3),
- HUB6(1, 4),
- HUB6(1, 5),
- { },
-};
-
-static struct platform_device hub6_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_HUB6,
- .dev = {
- .platform_data = hub6_data,
- },
-};
-
-static int __init hub6_init(void)
-{
- return platform_device_register(&hub6_device);
-}
-
-module_init(hub6_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Hub6 cards");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mca.h>
-#include <linux/serial_8250.h>
-
-/*
- * FIXME: Should we be doing AUTO_IRQ here?
- */
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ
-#else
-#define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
-#endif
-
-#define PORT(_base,_irq) \
- { \
- .iobase = _base, \
- .irq = _irq, \
- .uartclk = 1843200, \
- .iotype = UPIO_PORT, \
- .flags = MCA_FLAGS, \
- }
-
-static struct plat_serial8250_port mca_data[] = {
- PORT(0x3220, 3),
- PORT(0x3228, 3),
- PORT(0x4220, 3),
- PORT(0x4228, 3),
- PORT(0x5220, 3),
- PORT(0x5228, 3),
- { },
-};
-
-static struct platform_device mca_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_MCA,
- .dev = {
- .platform_data = mca_data,
- },
-};
-
-static int __init mca_init(void)
-{
- if (!MCA_bus)
- return -ENODEV;
- return platform_device_register(&mca_device);
-}
-
-module_init(mca_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for MCA ports");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * Probe module for 8250/16550-type PCI serial ports.
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/8250_pci.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-#undef SERIAL_DEBUG_PCI
-
-/*
- * init function returns:
- * > 0 - number of ports
- * = 0 - use board->num_ports
- * < 0 - error
- */
-struct pci_serial_quirk {
- u32 vendor;
- u32 device;
- u32 subvendor;
- u32 subdevice;
- int (*probe)(struct pci_dev *dev);
- int (*init)(struct pci_dev *dev);
- int (*setup)(struct serial_private *,
- const struct pciserial_board *,
- struct uart_port *, int);
- void (*exit)(struct pci_dev *dev);
-};
-
-#define PCI_NUM_BAR_RESOURCES 6
-
-struct serial_private {
- struct pci_dev *dev;
- unsigned int nr;
- void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES];
- struct pci_serial_quirk *quirk;
- int line[0];
-};
-
-static int pci_default_setup(struct serial_private*,
- const struct pciserial_board*, struct uart_port*, int);
-
-static void moan_device(const char *str, struct pci_dev *dev)
-{
- printk(KERN_WARNING
- "%s: %s\n"
- "Please send the output of lspci -vv, this\n"
- "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
- "manufacturer and name of serial board or\n"
- "modem board to rmk+serial@arm.linux.org.uk.\n",
- pci_name(dev), str, dev->vendor, dev->device,
- dev->subsystem_vendor, dev->subsystem_device);
-}
-
-static int
-setup_port(struct serial_private *priv, struct uart_port *port,
- int bar, int offset, int regshift)
-{
- struct pci_dev *dev = priv->dev;
- unsigned long base, len;
-
- if (bar >= PCI_NUM_BAR_RESOURCES)
- return -EINVAL;
-
- base = pci_resource_start(dev, bar);
-
- if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
- len = pci_resource_len(dev, bar);
-
- if (!priv->remapped_bar[bar])
- priv->remapped_bar[bar] = ioremap_nocache(base, len);
- if (!priv->remapped_bar[bar])
- return -ENOMEM;
-
- port->iotype = UPIO_MEM;
- port->iobase = 0;
- port->mapbase = base + offset;
- port->membase = priv->remapped_bar[bar] + offset;
- port->regshift = regshift;
- } else {
- port->iotype = UPIO_PORT;
- port->iobase = base + offset;
- port->mapbase = 0;
- port->membase = NULL;
- port->regshift = 0;
- }
- return 0;
-}
-
-/*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
-static int addidata_apci7800_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar = 0, offset = board->first_offset;
- bar = FL_GET_BASE(board->flags);
-
- if (idx < 2) {
- offset += idx * board->uart_offset;
- } else if ((idx >= 2) && (idx < 4)) {
- bar += 1;
- offset += ((idx - 2) * board->uart_offset);
- } else if ((idx >= 4) && (idx < 6)) {
- bar += 2;
- offset += ((idx - 4) * board->uart_offset);
- } else if (idx >= 6) {
- bar += 3;
- offset += ((idx - 6) * board->uart_offset);
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * AFAVLAB uses a different mixture of BARs and offsets
- * Not that ugly ;) -- HW
- */
-static int
-afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset;
-
- bar = FL_GET_BASE(board->flags);
- if (idx < 4)
- bar += idx;
- else {
- bar = 4;
- offset += (idx - 4) * board->uart_offset;
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * HP's Remote Management Console. The Diva chip came in several
- * different versions. N-class, L2000 and A500 have two Diva chips, each
- * with 3 UARTs (the third UART on the second chip is unused). Superdome
- * and Keystone have one Diva chip with 3 UARTs. Some later machines have
- * one Diva chip, but it has been expanded to 5 UARTs.
- */
-static int pci_hp_diva_init(struct pci_dev *dev)
-{
- int rc = 0;
-
- switch (dev->subsystem_device) {
- case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
- case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
- case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
- case PCI_DEVICE_ID_HP_DIVA_EVEREST:
- rc = 3;
- break;
- case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
- rc = 2;
- break;
- case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
- rc = 4;
- break;
- case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
- case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
- rc = 1;
- break;
- }
-
- return rc;
-}
-
-/*
- * HP's Diva chip puts the 4th/5th serial port further out, and
- * some serial ports are supposed to be hidden on certain models.
- */
-static int
-pci_hp_diva_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int offset = board->first_offset;
- unsigned int bar = FL_GET_BASE(board->flags);
-
- switch (priv->dev->subsystem_device) {
- case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
- if (idx == 3)
- idx++;
- break;
- case PCI_DEVICE_ID_HP_DIVA_EVEREST:
- if (idx > 0)
- idx++;
- if (idx > 2)
- idx++;
- break;
- }
- if (idx > 2)
- offset = 0x18;
-
- offset += idx * board->uart_offset;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * Added for EKF Intel i960 serial boards
- */
-static int pci_inteli960ni_init(struct pci_dev *dev)
-{
- unsigned long oldval;
-
- if (!(dev->subsystem_device & 0x1000))
- return -ENODEV;
-
- /* is firmware started? */
- pci_read_config_dword(dev, 0x44, (void *)&oldval);
- if (oldval == 0x00001000L) { /* RESET value */
- printk(KERN_DEBUG "Local i960 firmware missing");
- return -ENODEV;
- }
- return 0;
-}
-
-/*
- * Some PCI serial cards using the PLX 9050 PCI interface chip require
- * that the card interrupt be explicitly enabled or disabled. This
- * seems to be mainly needed on card using the PLX which also use I/O
- * mapped memory.
- */
-static int pci_plx9050_init(struct pci_dev *dev)
-{
- u8 irq_config;
- void __iomem *p;
-
- if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar 0", dev);
- return 0;
- }
-
- irq_config = 0x41;
- if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
- dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
- irq_config = 0x43;
-
- if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
- (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
- /*
- * As the megawolf cards have the int pins active
- * high, and have 2 UART chips, both ints must be
- * enabled on the 9050. Also, the UARTS are set in
- * 16450 mode by default, so we have to enable the
- * 16C950 'enhanced' mode so that we can use the
- * deep FIFOs
- */
- irq_config = 0x5b;
- /*
- * enable/disable interrupts
- */
- p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
- if (p == NULL)
- return -ENOMEM;
- writel(irq_config, p + 0x4c);
-
- /*
- * Read the register back to ensure that it took effect.
- */
- readl(p + 0x4c);
- iounmap(p);
-
- return 0;
-}
-
-static void __devexit pci_plx9050_exit(struct pci_dev *dev)
-{
- u8 __iomem *p;
-
- if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
- return;
-
- /*
- * disable interrupts
- */
- p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
- if (p != NULL) {
- writel(0, p + 0x4c);
-
- /*
- * Read the register back to ensure that it took effect.
- */
- readl(p + 0x4c);
- iounmap(p);
- }
-}
-
-#define NI8420_INT_ENABLE_REG 0x38
-#define NI8420_INT_ENABLE_BIT 0x2000
-
-static void __devexit pci_ni8420_exit(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return;
-
- /* Disable the CPU Interrupt */
- writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT),
- p + NI8420_INT_ENABLE_REG);
- iounmap(p);
-}
-
-
-/* MITE registers */
-#define MITE_IOWBSR1 0xc4
-#define MITE_IOWCR1 0xf4
-#define MITE_LCIMR1 0x08
-#define MITE_LCIMR2 0x10
-
-#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
-
-static void __devexit pci_ni8430_exit(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return;
-
- /* Disable the CPU Interrupt */
- writel(MITE_LCIMR2_CLR_CPU_IE, p + MITE_LCIMR2);
- iounmap(p);
-}
-
-/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
-static int
-sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset;
-
- bar = 0;
-
- if (idx < 4) {
- /* first four channels map to 0, 0x100, 0x200, 0x300 */
- offset += idx * board->uart_offset;
- } else if (idx < 8) {
- /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
- offset += idx * board->uart_offset + 0xC00;
- } else /* we have only 8 ports on PMC-OCTALPRO */
- return 1;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
-* This does initialization for PMC OCTALPRO cards:
-* maps the device memory, resets the UARTs (needed, bc
-* if the module is removed and inserted again, the card
-* is in the sleep mode) and enables global interrupt.
-*/
-
-/* global control register offset for SBS PMC-OctalPro */
-#define OCT_REG_CR_OFF 0x500
-
-static int sbs_init(struct pci_dev *dev)
-{
- u8 __iomem *p;
-
- p = pci_ioremap_bar(dev, 0);
-
- if (p == NULL)
- return -ENOMEM;
- /* Set bit-4 Control Register (UART RESET) in to reset the uarts */
- writeb(0x10, p + OCT_REG_CR_OFF);
- udelay(50);
- writeb(0x0, p + OCT_REG_CR_OFF);
-
- /* Set bit-2 (INTENABLE) of Control Register */
- writeb(0x4, p + OCT_REG_CR_OFF);
- iounmap(p);
-
- return 0;
-}
-
-/*
- * Disables the global interrupt of PMC-OctalPro
- */
-
-static void __devexit sbs_exit(struct pci_dev *dev)
-{
- u8 __iomem *p;
-
- p = pci_ioremap_bar(dev, 0);
- /* FIXME: What if resource_len < OCT_REG_CR_OFF */
- if (p != NULL)
- writeb(0, p + OCT_REG_CR_OFF);
- iounmap(p);
-}
-
-/*
- * SIIG serial cards have an PCI interface chip which also controls
- * the UART clocking frequency. Each UART can be clocked independently
- * (except cards equipped with 4 UARTs) and initial clocking settings
- * are stored in the EEPROM chip. It can cause problems because this
- * version of serial driver doesn't support differently clocked UART's
- * on single PCI card. To prevent this, initialization functions set
- * high frequency clocking for all UART's on given card. It is safe (I
- * hope) because it doesn't touch EEPROM settings to prevent conflicts
- * with other OSes (like M$ DOS).
- *
- * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
- *
- * There is two family of SIIG serial cards with different PCI
- * interface chip and different configuration methods:
- * - 10x cards have control registers in IO and/or memory space;
- * - 20x cards have control registers in standard PCI configuration space.
- *
- * Note: all 10x cards have PCI device ids 0x10..
- * all 20x cards have PCI device ids 0x20..
- *
- * There are also Quartet Serial cards which use Oxford Semiconductor
- * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
- *
- * Note: some SIIG cards are probed by the parport_serial object.
- */
-
-#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
-#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
-
-static int pci_siig10x_init(struct pci_dev *dev)
-{
- u16 data;
- void __iomem *p;
-
- switch (dev->device & 0xfff8) {
- case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
- data = 0xffdf;
- break;
- case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
- data = 0xf7ff;
- break;
- default: /* 1S1P, 4S */
- data = 0xfffb;
- break;
- }
-
- p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
- if (p == NULL)
- return -ENOMEM;
-
- writew(readw(p + 0x28) & data, p + 0x28);
- readw(p + 0x28);
- iounmap(p);
- return 0;
-}
-
-#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
-#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
-
-static int pci_siig20x_init(struct pci_dev *dev)
-{
- u8 data;
-
- /* Change clock frequency for the first UART. */
- pci_read_config_byte(dev, 0x6f, &data);
- pci_write_config_byte(dev, 0x6f, data & 0xef);
-
- /* If this card has 2 UART, we have to do the same with second UART. */
- if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
- ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
- pci_read_config_byte(dev, 0x73, &data);
- pci_write_config_byte(dev, 0x73, data & 0xef);
- }
- return 0;
-}
-
-static int pci_siig_init(struct pci_dev *dev)
-{
- unsigned int type = dev->device & 0xff00;
-
- if (type == 0x1000)
- return pci_siig10x_init(dev);
- else if (type == 0x2000)
- return pci_siig20x_init(dev);
-
- moan_device("Unknown SIIG card", dev);
- return -ENODEV;
-}
-
-static int pci_siig_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
-
- if (idx > 3) {
- bar = 4;
- offset = (idx - 4) * 8;
- }
-
- return setup_port(priv, port, bar, offset, 0);
-}
-
-/*
- * Timedia has an explosion of boards, and to avoid the PCI table from
- * growing *huge*, we use this function to collapse some 70 entries
- * in the PCI table into one, for sanity's and compactness's sake.
- */
-static const unsigned short timedia_single_port[] = {
- 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
-};
-
-static const unsigned short timedia_dual_port[] = {
- 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
- 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
- 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
- 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
- 0xD079, 0
-};
-
-static const unsigned short timedia_quad_port[] = {
- 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
- 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
- 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
- 0xB157, 0
-};
-
-static const unsigned short timedia_eight_port[] = {
- 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
- 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
-};
-
-static const struct timedia_struct {
- int num;
- const unsigned short *ids;
-} timedia_data[] = {
- { 1, timedia_single_port },
- { 2, timedia_dual_port },
- { 4, timedia_quad_port },
- { 8, timedia_eight_port }
-};
-
-/*
- * There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of
- * listing them individually, this driver merely grabs them all with
- * PCI_ANY_ID. Some of these devices, however, also feature a parallel port,
- * and should be left free to be claimed by parport_serial instead.
- */
-static int pci_timedia_probe(struct pci_dev *dev)
-{
- /*
- * Check the third digit of the subdevice ID
- * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
- */
- if ((dev->subsystem_device & 0x00f0) >= 0x70) {
- dev_info(&dev->dev,
- "ignoring Timedia subdevice %04x for parport_serial\n",
- dev->subsystem_device);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int pci_timedia_init(struct pci_dev *dev)
-{
- const unsigned short *ids;
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
- ids = timedia_data[i].ids;
- for (j = 0; ids[j]; j++)
- if (dev->subsystem_device == ids[j])
- return timedia_data[i].num;
- }
- return 0;
-}
-
-/*
- * Timedia/SUNIX uses a mixture of BARs and offsets
- * Ugh, this is ugly as all hell --- TYT
- */
-static int
-pci_timedia_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar = 0, offset = board->first_offset;
-
- switch (idx) {
- case 0:
- bar = 0;
- break;
- case 1:
- offset = board->uart_offset;
- bar = 0;
- break;
- case 2:
- bar = 1;
- break;
- case 3:
- offset = board->uart_offset;
- /* FALLTHROUGH */
- case 4: /* BAR 2 */
- case 5: /* BAR 3 */
- case 6: /* BAR 4 */
- case 7: /* BAR 5 */
- bar = idx - 2;
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * Some Titan cards are also a little weird
- */
-static int
-titan_400l_800l_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset;
-
- switch (idx) {
- case 0:
- bar = 1;
- break;
- case 1:
- bar = 2;
- break;
- default:
- bar = 4;
- offset = (idx - 2) * board->uart_offset;
- }
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int pci_xircom_init(struct pci_dev *dev)
-{
- msleep(100);
- return 0;
-}
-
-static int pci_ni8420_init(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return 0;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return -ENOMEM;
-
- /* Enable CPU Interrupt */
- writel(readl(p + NI8420_INT_ENABLE_REG) | NI8420_INT_ENABLE_BIT,
- p + NI8420_INT_ENABLE_REG);
-
- iounmap(p);
- return 0;
-}
-
-#define MITE_IOWBSR1_WSIZE 0xa
-#define MITE_IOWBSR1_WIN_OFFSET 0x800
-#define MITE_IOWBSR1_WENAB (1 << 7)
-#define MITE_LCIMR1_IO_IE_0 (1 << 24)
-#define MITE_LCIMR2_SET_CPU_IE (1 << 31)
-#define MITE_IOWCR1_RAMSEL_MASK 0xfffffffe
-
-static int pci_ni8430_init(struct pci_dev *dev)
-{
- void __iomem *p;
- unsigned long base, len;
- u32 device_window;
- unsigned int bar = 0;
-
- if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
- moan_device("no memory in bar", dev);
- return 0;
- }
-
- base = pci_resource_start(dev, bar);
- len = pci_resource_len(dev, bar);
- p = ioremap_nocache(base, len);
- if (p == NULL)
- return -ENOMEM;
-
- /* Set device window address and size in BAR0 */
- device_window = ((base + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00)
- | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE;
- writel(device_window, p + MITE_IOWBSR1);
-
- /* Set window access to go to RAMSEL IO address space */
- writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
- p + MITE_IOWCR1);
-
- /* Enable IO Bus Interrupt 0 */
- writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
-
- /* Enable CPU Interrupt */
- writel(MITE_LCIMR2_SET_CPU_IE, p + MITE_LCIMR2);
-
- iounmap(p);
- return 0;
-}
-
-/* UART Port Control Register */
-#define NI8430_PORTCON 0x0f
-#define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
-
-static int
-pci_ni8430_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- void __iomem *p;
- unsigned long base, len;
- unsigned int bar, offset = board->first_offset;
-
- if (idx >= board->num_ports)
- return 1;
-
- bar = FL_GET_BASE(board->flags);
- offset += idx * board->uart_offset;
-
- base = pci_resource_start(priv->dev, bar);
- len = pci_resource_len(priv->dev, bar);
- p = ioremap_nocache(base, len);
-
- /* enable the transceiver */
- writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
- p + offset + NI8430_PORTCON);
-
- iounmap(p);
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int pci_netmos_9900_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar;
-
- if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
- /* netmos apparently orders BARs by datasheet layout, so serial
- * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
- */
- bar = 3 * idx;
-
- return setup_port(priv, port, bar, 0, board->reg_shift);
- } else {
- return pci_default_setup(priv, board, port, idx);
- }
-}
-
-/* the 99xx series comes with a range of device IDs and a variety
- * of capabilities:
- *
- * 9900 has varying capabilities and can cascade to sub-controllers
- * (cascading should be purely internal)
- * 9904 is hardwired with 4 serial ports
- * 9912 and 9922 are hardwired with 2 serial ports
- */
-static int pci_netmos_9900_numports(struct pci_dev *dev)
-{
- unsigned int c = dev->class;
- unsigned int pi;
- unsigned short sub_serports;
-
- pi = (c & 0xff);
-
- if (pi == 2) {
- return 1;
- } else if ((pi == 0) &&
- (dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
- /* two possibilities: 0x30ps encodes number of parallel and
- * serial ports, or 0x1000 indicates *something*. This is not
- * immediately obvious, since the 2s1p+4s configuration seems
- * to offer all functionality on functions 0..2, while still
- * advertising the same function 3 as the 4s+2s1p config.
- */
- sub_serports = dev->subsystem_device & 0xf;
- if (sub_serports > 0) {
- return sub_serports;
- } else {
- printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
- return 0;
- }
- }
-
- moan_device("unknown NetMos/Mostech program interface", dev);
- return 0;
-}
-
-static int pci_netmos_init(struct pci_dev *dev)
-{
- /* subdevice 0x00PS means <P> parallel, <S> serial */
- unsigned int num_serial = dev->subsystem_device & 0xf;
-
- if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
- (dev->device == PCI_DEVICE_ID_NETMOS_9865))
- return 0;
-
- if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
- dev->subsystem_device == 0x0299)
- return 0;
-
- switch (dev->device) { /* FALLTHROUGH on all */
- case PCI_DEVICE_ID_NETMOS_9904:
- case PCI_DEVICE_ID_NETMOS_9912:
- case PCI_DEVICE_ID_NETMOS_9922:
- case PCI_DEVICE_ID_NETMOS_9900:
- num_serial = pci_netmos_9900_numports(dev);
- break;
-
- default:
- if (num_serial == 0 ) {
- moan_device("unknown NetMos/Mostech device", dev);
- }
- }
-
- if (num_serial == 0)
- return -ENODEV;
-
- return num_serial;
-}
-
-/*
- * These chips are available with optionally one parallel port and up to
- * two serial ports. Unfortunately they all have the same product id.
- *
- * Basic configuration is done over a region of 32 I/O ports. The base
- * ioport is called INTA or INTC, depending on docs/other drivers.
- *
- * The region of the 32 I/O ports is configured in POSIO0R...
- */
-
-/* registers */
-#define ITE_887x_MISCR 0x9c
-#define ITE_887x_INTCBAR 0x78
-#define ITE_887x_UARTBAR 0x7c
-#define ITE_887x_PS0BAR 0x10
-#define ITE_887x_POSIO0 0x60
-
-/* I/O space size */
-#define ITE_887x_IOSIZE 32
-/* I/O space size (bits 26-24; 8 bytes = 011b) */
-#define ITE_887x_POSIO_IOSIZE_8 (3 << 24)
-/* I/O space size (bits 26-24; 32 bytes = 101b) */
-#define ITE_887x_POSIO_IOSIZE_32 (5 << 24)
-/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */
-#define ITE_887x_POSIO_SPEED (3 << 29)
-/* enable IO_Space bit */
-#define ITE_887x_POSIO_ENABLE (1 << 31)
-
-static int pci_ite887x_init(struct pci_dev *dev)
-{
- /* inta_addr are the configuration addresses of the ITE */
- static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
- 0x200, 0x280, 0 };
- int ret, i, type;
- struct resource *iobase = NULL;
- u32 miscr, uartbar, ioport;
-
- /* search for the base-ioport */
- i = 0;
- while (inta_addr[i] && iobase == NULL) {
- iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
- "ite887x");
- if (iobase != NULL) {
- /* write POSIO0R - speed | size | ioport */
- pci_write_config_dword(dev, ITE_887x_POSIO0,
- ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
- ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]);
- /* write INTCBAR - ioport */
- pci_write_config_dword(dev, ITE_887x_INTCBAR,
- inta_addr[i]);
- ret = inb(inta_addr[i]);
- if (ret != 0xff) {
- /* ioport connected */
- break;
- }
- release_region(iobase->start, ITE_887x_IOSIZE);
- iobase = NULL;
- }
- i++;
- }
-
- if (!inta_addr[i]) {
- printk(KERN_ERR "ite887x: could not find iobase\n");
- return -ENODEV;
- }
-
- /* start of undocumented type checking (see parport_pc.c) */
- type = inb(iobase->start + 0x18) & 0x0f;
-
- switch (type) {
- case 0x2: /* ITE8871 (1P) */
- case 0xa: /* ITE8875 (1P) */
- ret = 0;
- break;
- case 0xe: /* ITE8872 (2S1P) */
- ret = 2;
- break;
- case 0x6: /* ITE8873 (1S) */
- ret = 1;
- break;
- case 0x8: /* ITE8874 (2S) */
- ret = 2;
- break;
- default:
- moan_device("Unknown ITE887x", dev);
- ret = -ENODEV;
- }
-
- /* configure all serial ports */
- for (i = 0; i < ret; i++) {
- /* read the I/O port from the device */
- pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),
- &ioport);
- ioport &= 0x0000FF00; /* the actual base address */
- pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),
- ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
- ITE_887x_POSIO_IOSIZE_8 | ioport);
-
- /* write the ioport to the UARTBAR */
- pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);
- uartbar &= ~(0xffff << (16 * i)); /* clear half the reg */
- uartbar |= (ioport << (16 * i)); /* set the ioport */
- pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);
-
- /* get current config */
- pci_read_config_dword(dev, ITE_887x_MISCR, &miscr);
- /* disable interrupts (UARTx_Routing[3:0]) */
- miscr &= ~(0xf << (12 - 4 * i));
- /* activate the UART (UARTx_En) */
- miscr |= 1 << (23 - i);
- /* write new config with activated UART */
- pci_write_config_dword(dev, ITE_887x_MISCR, miscr);
- }
-
- if (ret <= 0) {
- /* the device has no UARTs if we get here */
- release_region(iobase->start, ITE_887x_IOSIZE);
- }
-
- return ret;
-}
-
-static void __devexit pci_ite887x_exit(struct pci_dev *dev)
-{
- u32 ioport;
- /* the ioport is bit 0-15 in POSIO0R */
- pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
- ioport &= 0xffff;
- release_region(ioport, ITE_887x_IOSIZE);
-}
-
-/*
- * Oxford Semiconductor Inc.
- * Check that device is part of the Tornado range of devices, then determine
- * the number of ports available on the device.
- */
-static int pci_oxsemi_tornado_init(struct pci_dev *dev)
-{
- u8 __iomem *p;
- unsigned long deviceID;
- unsigned int number_uarts = 0;
-
- /* OxSemi Tornado devices are all 0xCxxx */
- if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
- (dev->device & 0xF000) != 0xC000)
- return 0;
-
- p = pci_iomap(dev, 0, 5);
- if (p == NULL)
- return -ENOMEM;
-
- deviceID = ioread32(p);
- /* Tornado device */
- if (deviceID == 0x07000200) {
- number_uarts = ioread8(p + 4);
- printk(KERN_DEBUG
- "%d ports detected on Oxford PCI Express device\n",
- number_uarts);
- }
- pci_iounmap(dev, p);
- return number_uarts;
-}
-
-static int
-pci_default_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset, maxnr;
-
- bar = FL_GET_BASE(board->flags);
- if (board->flags & FL_BASE_BARS)
- bar += idx;
- else
- offset += idx * board->uart_offset;
-
- maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
- (board->reg_shift + 3);
-
- if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
- return 1;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int
-ce4100_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- int ret;
-
- ret = setup_port(priv, port, 0, 0, board->reg_shift);
- port->iotype = UPIO_MEM32;
- port->type = PORT_XSCALE;
- port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
- port->regshift = 2;
-
- return ret;
-}
-
-static int
-pci_omegapci_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- return setup_port(priv, port, 2, idx * 8, 0);
-}
-
-static int skip_tx_en_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- port->flags |= UPF_NO_TXEN_TEST;
- printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
- "[%04x:%04x] subsystem [%04x:%04x]\n",
- priv->dev->vendor,
- priv->dev->device,
- priv->dev->subsystem_vendor,
- priv->dev->subsystem_device);
-
- return pci_default_setup(priv, board, port, idx);
-}
-
-static int kt_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- port->flags |= UPF_IIR_ONCE;
- return skip_tx_en_setup(priv, board, port, idx);
-}
-
-static int pci_eg20t_init(struct pci_dev *dev)
-{
-#if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE)
- return -ENODEV;
-#else
- return 0;
-#endif
-}
-
-static int
-pci_xr17c154_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
-{
- port->flags |= UPF_EXAR_EFR;
- return pci_default_setup(priv, board, port, idx);
-}
-
-static int try_enable_msi(struct pci_dev *dev)
-{
- /* use msi if available, but fallback to legacy otherwise */
- pci_enable_msi(dev);
- return 0;
-}
-
-static void disable_msi(struct pci_dev *dev)
-{
- pci_disable_msi(dev);
-}
-
-#define PCI_VENDOR_ID_SBSMODULARIO 0x124B
-#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
-#define PCI_DEVICE_ID_OCTPRO 0x0001
-#define PCI_SUBDEVICE_ID_OCTPRO232 0x0108
-#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208
-#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
-#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
-#define PCI_VENDOR_ID_ADVANTECH 0x13fe
-#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
-#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
-#define PCI_DEVICE_ID_TITAN_200I 0x8028
-#define PCI_DEVICE_ID_TITAN_400I 0x8048
-#define PCI_DEVICE_ID_TITAN_800I 0x8088
-#define PCI_DEVICE_ID_TITAN_800EH 0xA007
-#define PCI_DEVICE_ID_TITAN_800EHB 0xA008
-#define PCI_DEVICE_ID_TITAN_400EH 0xA009
-#define PCI_DEVICE_ID_TITAN_100E 0xA010
-#define PCI_DEVICE_ID_TITAN_200E 0xA012
-#define PCI_DEVICE_ID_TITAN_400E 0xA013
-#define PCI_DEVICE_ID_TITAN_800E 0xA014
-#define PCI_DEVICE_ID_TITAN_200EI 0xA016
-#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
-#define PCI_DEVICE_ID_TITAN_400V3 0xA310
-#define PCI_DEVICE_ID_TITAN_410V3 0xA312
-#define PCI_DEVICE_ID_TITAN_800V3 0xA314
-#define PCI_DEVICE_ID_TITAN_800V3B 0xA315
-#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
-#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
-#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
-#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
-
-/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
-#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
-
-/*
- * Master list of serial port init/setup/exit quirks.
- * This does not describe the general nature of the port.
- * (ie, baud base, number and location of ports, etc)
- *
- * This list is ordered alphabetically by vendor then device.
- * Specific entries must come before more generic entries.
- */
-static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
- /*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
- {
- .vendor = PCI_VENDOR_ID_ADDIDATA_OLD,
- .device = PCI_DEVICE_ID_ADDIDATA_APCI7800,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = addidata_apci7800_setup,
- },
- /*
- * AFAVLAB cards - these may be called via parport_serial
- * It is not clear whether this applies to all products.
- */
- {
- .vendor = PCI_VENDOR_ID_AFAVLAB,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = afavlab_setup,
- },
- /*
- * HP Diva
- */
- {
- .vendor = PCI_VENDOR_ID_HP,
- .device = PCI_DEVICE_ID_HP_DIVA,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_hp_diva_init,
- .setup = pci_hp_diva_setup,
- },
- /*
- * Intel
- */
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_80960_RP,
- .subvendor = 0xe4bf,
- .subdevice = PCI_ANY_ID,
- .init = pci_inteli960ni_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_8257X_SOL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = skip_tx_en_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82573L_SOL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = skip_tx_en_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82573E_SOL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = skip_tx_en_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_CE4100_UART,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = ce4100_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = try_enable_msi,
- .setup = kt_serial_setup,
- .exit = disable_msi,
- },
- /*
- * ITE
- */
- {
- .vendor = PCI_VENDOR_ID_ITE,
- .device = PCI_DEVICE_ID_ITE_8872,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ite887x_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ite887x_exit),
- },
- /*
- * National Instruments
- */
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI23216,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2328,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2324,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2322,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2324I,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PCI2322I,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_23216,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_2328,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_2324,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8420_2322,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8422_2324,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_DEVICE_ID_NI_PXI8422_2322,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8420_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_NI,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_ni8430_init,
- .setup = pci_ni8430_setup,
- .exit = __devexit_p(pci_ni8430_exit),
- },
- /*
- * Panacom
- */
- {
- .vendor = PCI_VENDOR_ID_PANACOM,
- .device = PCI_DEVICE_ID_PANACOM_QUADMODEM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PANACOM,
- .device = PCI_DEVICE_ID_PANACOM_DUALMODEM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- /*
- * PLX
- */
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9030,
- .subvendor = PCI_SUBVENDOR_ID_PERLE,
- .subdevice = PCI_ANY_ID,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_SUBVENDOR_ID_EXSYS,
- .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_SUBVENDOR_ID_KEYSPAN,
- .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_VENDOR_ID_PLX,
- .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_ROMULUS,
- .subvendor = PCI_VENDOR_ID_PLX,
- .subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
- .init = pci_plx9050_init,
- .setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
- },
- /*
- * SBS Technologies, Inc., PMC-OCTALPRO 232
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SBS Technologies, Inc., PMC-OCTALPRO 422
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SBS Technologies, Inc., P-Octal 232
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_POCTAL232,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SBS Technologies, Inc., P-Octal 422
- */
- {
- .vendor = PCI_VENDOR_ID_SBSMODULARIO,
- .device = PCI_DEVICE_ID_OCTPRO,
- .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
- .subdevice = PCI_SUBDEVICE_ID_POCTAL422,
- .init = sbs_init,
- .setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
- },
- /*
- * SIIG cards - these may be called via parport_serial
- */
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig_init,
- .setup = pci_siig_setup,
- },
- /*
- * Titan cards
- */
- {
- .vendor = PCI_VENDOR_ID_TITAN,
- .device = PCI_DEVICE_ID_TITAN_400L,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = titan_400l_800l_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_TITAN,
- .device = PCI_DEVICE_ID_TITAN_800L,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = titan_400l_800l_setup,
- },
- /*
- * Timedia cards
- */
- {
- .vendor = PCI_VENDOR_ID_TIMEDIA,
- .device = PCI_DEVICE_ID_TIMEDIA_1889,
- .subvendor = PCI_VENDOR_ID_TIMEDIA,
- .subdevice = PCI_ANY_ID,
- .probe = pci_timedia_probe,
- .init = pci_timedia_init,
- .setup = pci_timedia_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_TIMEDIA,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_timedia_setup,
- },
- /*
- * Exar cards
- */
- {
- .vendor = PCI_VENDOR_ID_EXAR,
- .device = PCI_DEVICE_ID_EXAR_XR17C152,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_xr17c154_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_EXAR,
- .device = PCI_DEVICE_ID_EXAR_XR17C154,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_xr17c154_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_EXAR,
- .device = PCI_DEVICE_ID_EXAR_XR17C158,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_xr17c154_setup,
- },
- /*
- * Xircom cards
- */
- {
- .vendor = PCI_VENDOR_ID_XIRCOM,
- .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_xircom_init,
- .setup = pci_default_setup,
- },
- /*
- * Netmos cards - these may be called via parport_serial
- */
- {
- .vendor = PCI_VENDOR_ID_NETMOS,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_netmos_init,
- .setup = pci_netmos_9900_setup,
- },
- /*
- * For Oxford Semiconductor Tornado based devices
- */
- {
- .vendor = PCI_VENDOR_ID_OXSEMI,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_MAINPINE,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_DIGI,
- .device = PCIE_DEVICE_ID_NEO_2_OX_IBM,
- .subvendor = PCI_SUBVENDOR_ID_IBM,
- .subdevice = PCI_ANY_ID,
- .init = pci_oxsemi_tornado_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8811,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8812,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8813,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = 0x8814,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = 0x10DB,
- .device = 0x8027,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = 0x10DB,
- .device = 0x8028,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = 0x10DB,
- .device = 0x8029,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = 0x10DB,
- .device = 0x800C,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = 0x10DB,
- .device = 0x800D,
- .init = pci_eg20t_init,
- .setup = pci_default_setup,
- },
- /*
- * Cronyx Omega PCI (PLX-chip based)
- */
- {
- .vendor = PCI_VENDOR_ID_PLX,
- .device = PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_omegapci_setup,
- },
- /*
- * Default "match everything" terminator entry
- */
- {
- .vendor = PCI_ANY_ID,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_default_setup,
- }
-};
-
-static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
-{
- return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
-}
-
-static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
-{
- struct pci_serial_quirk *quirk;
-
- for (quirk = pci_serial_quirks; ; quirk++)
- if (quirk_id_matches(quirk->vendor, dev->vendor) &&
- quirk_id_matches(quirk->device, dev->device) &&
- quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
- quirk_id_matches(quirk->subdevice, dev->subsystem_device))
- break;
- return quirk;
-}
-
-static inline int get_pci_irq(struct pci_dev *dev,
- const struct pciserial_board *board)
-{
- if (board->flags & FL_NOIRQ)
- return 0;
- else
- return dev->irq;
-}
-
-/*
- * This is the configuration table for all of the PCI serial boards
- * which we support. It is directly indexed by the pci_board_num_t enum
- * value, which is encoded in the pci_device_id PCI probe table's
- * driver_data member.
- *
- * The makeup of these names are:
- * pbn_bn{_bt}_n_baud{_offsetinhex}
- *
- * bn = PCI BAR number
- * bt = Index using PCI BARs
- * n = number of serial ports
- * baud = baud rate
- * offsetinhex = offset for each sequential port (in hex)
- *
- * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
- *
- * Please note: in theory if n = 1, _bt infix should make no difference.
- * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
- */
-enum pci_board_num_t {
- pbn_default = 0,
-
- pbn_b0_1_115200,
- pbn_b0_2_115200,
- pbn_b0_4_115200,
- pbn_b0_5_115200,
- pbn_b0_8_115200,
-
- pbn_b0_1_921600,
- pbn_b0_2_921600,
- pbn_b0_4_921600,
-
- pbn_b0_2_1130000,
-
- pbn_b0_4_1152000,
-
- pbn_b0_2_1843200,
- pbn_b0_4_1843200,
-
- pbn_b0_2_1843200_200,
- pbn_b0_4_1843200_200,
- pbn_b0_8_1843200_200,
-
- pbn_b0_1_4000000,
-
- pbn_b0_bt_1_115200,
- pbn_b0_bt_2_115200,
- pbn_b0_bt_4_115200,
- pbn_b0_bt_8_115200,
-
- pbn_b0_bt_1_460800,
- pbn_b0_bt_2_460800,
- pbn_b0_bt_4_460800,
-
- pbn_b0_bt_1_921600,
- pbn_b0_bt_2_921600,
- pbn_b0_bt_4_921600,
- pbn_b0_bt_8_921600,
-
- pbn_b1_1_115200,
- pbn_b1_2_115200,
- pbn_b1_4_115200,
- pbn_b1_8_115200,
- pbn_b1_16_115200,
-
- pbn_b1_1_921600,
- pbn_b1_2_921600,
- pbn_b1_4_921600,
- pbn_b1_8_921600,
-
- pbn_b1_2_1250000,
-
- pbn_b1_bt_1_115200,
- pbn_b1_bt_2_115200,
- pbn_b1_bt_4_115200,
-
- pbn_b1_bt_2_921600,
-
- pbn_b1_1_1382400,
- pbn_b1_2_1382400,
- pbn_b1_4_1382400,
- pbn_b1_8_1382400,
-
- pbn_b2_1_115200,
- pbn_b2_2_115200,
- pbn_b2_4_115200,
- pbn_b2_8_115200,
-
- pbn_b2_1_460800,
- pbn_b2_4_460800,
- pbn_b2_8_460800,
- pbn_b2_16_460800,
-
- pbn_b2_1_921600,
- pbn_b2_4_921600,
- pbn_b2_8_921600,
-
- pbn_b2_8_1152000,
-
- pbn_b2_bt_1_115200,
- pbn_b2_bt_2_115200,
- pbn_b2_bt_4_115200,
-
- pbn_b2_bt_2_921600,
- pbn_b2_bt_4_921600,
-
- pbn_b3_2_115200,
- pbn_b3_4_115200,
- pbn_b3_8_115200,
-
- pbn_b4_bt_2_921600,
- pbn_b4_bt_4_921600,
- pbn_b4_bt_8_921600,
-
- /*
- * Board-specific versions.
- */
- pbn_panacom,
- pbn_panacom2,
- pbn_panacom4,
- pbn_exsys_4055,
- pbn_plx_romulus,
- pbn_oxsemi,
- pbn_oxsemi_1_4000000,
- pbn_oxsemi_2_4000000,
- pbn_oxsemi_4_4000000,
- pbn_oxsemi_8_4000000,
- pbn_intel_i960,
- pbn_sgi_ioc3,
- pbn_computone_4,
- pbn_computone_6,
- pbn_computone_8,
- pbn_sbsxrsio,
- pbn_exar_XR17C152,
- pbn_exar_XR17C154,
- pbn_exar_XR17C158,
- pbn_exar_ibm_saturn,
- pbn_pasemi_1682M,
- pbn_ni8430_2,
- pbn_ni8430_4,
- pbn_ni8430_8,
- pbn_ni8430_16,
- pbn_ADDIDATA_PCIe_1_3906250,
- pbn_ADDIDATA_PCIe_2_3906250,
- pbn_ADDIDATA_PCIe_4_3906250,
- pbn_ADDIDATA_PCIe_8_3906250,
- pbn_ce4100_1_115200,
- pbn_omegapci,
- pbn_NETMOS9900_2s_115200,
-};
-
-/*
- * uart_offset - the space between channels
- * reg_shift - describes how the UART registers are mapped
- * to PCI memory by the card.
- * For example IER register on SBS, Inc. PMC-OctPro is located at
- * offset 0x10 from the UART base, while UART_IER is defined as 1
- * in include/linux/serial_reg.h,
- * see first lines of serial_in() and serial_out() in 8250.c
-*/
-
-static struct pciserial_board pci_boards[] __devinitdata = {
- [pbn_default] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_1_115200] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_2_115200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_4_115200] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_5_115200] = {
- .flags = FL_BASE0,
- .num_ports = 5,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_8_115200] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_1_921600] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_2_921600] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_4_921600] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b0_2_1130000] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1130000,
- .uart_offset = 8,
- },
-
- [pbn_b0_4_1152000] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 1152000,
- .uart_offset = 8,
- },
-
- [pbn_b0_2_1843200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1843200,
- .uart_offset = 8,
- },
- [pbn_b0_4_1843200] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 1843200,
- .uart_offset = 8,
- },
-
- [pbn_b0_2_1843200_200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 1843200,
- .uart_offset = 0x200,
- },
- [pbn_b0_4_1843200_200] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 1843200,
- .uart_offset = 0x200,
- },
- [pbn_b0_8_1843200_200] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 1843200,
- .uart_offset = 0x200,
- },
- [pbn_b0_1_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 4000000,
- .uart_offset = 8,
- },
-
- [pbn_b0_bt_1_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_bt_2_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_bt_4_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b0_bt_8_115200] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b0_bt_1_460800] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b0_bt_2_460800] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b0_bt_4_460800] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 460800,
- .uart_offset = 8,
- },
-
- [pbn_b0_bt_1_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_bt_2_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_bt_4_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b0_bt_8_921600] = {
- .flags = FL_BASE0|FL_BASE_BARS,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b1_1_115200] = {
- .flags = FL_BASE1,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_2_115200] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_4_115200] = {
- .flags = FL_BASE1,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_8_115200] = {
- .flags = FL_BASE1,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_16_115200] = {
- .flags = FL_BASE1,
- .num_ports = 16,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b1_1_921600] = {
- .flags = FL_BASE1,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_2_921600] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_4_921600] = {
- .flags = FL_BASE1,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_8_921600] = {
- .flags = FL_BASE1,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b1_2_1250000] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 1250000,
- .uart_offset = 8,
- },
-
- [pbn_b1_bt_1_115200] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_bt_2_115200] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b1_bt_4_115200] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b1_bt_2_921600] = {
- .flags = FL_BASE1|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b1_1_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 1,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
- [pbn_b1_2_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 2,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
- [pbn_b1_4_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 4,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
- [pbn_b1_8_1382400] = {
- .flags = FL_BASE1,
- .num_ports = 8,
- .base_baud = 1382400,
- .uart_offset = 8,
- },
-
- [pbn_b2_1_115200] = {
- .flags = FL_BASE2,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_2_115200] = {
- .flags = FL_BASE2,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_4_115200] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_8_115200] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b2_1_460800] = {
- .flags = FL_BASE2,
- .num_ports = 1,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b2_4_460800] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b2_8_460800] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 460800,
- .uart_offset = 8,
- },
- [pbn_b2_16_460800] = {
- .flags = FL_BASE2,
- .num_ports = 16,
- .base_baud = 460800,
- .uart_offset = 8,
- },
-
- [pbn_b2_1_921600] = {
- .flags = FL_BASE2,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b2_4_921600] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b2_8_921600] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b2_8_1152000] = {
- .flags = FL_BASE2,
- .num_ports = 8,
- .base_baud = 1152000,
- .uart_offset = 8,
- },
-
- [pbn_b2_bt_1_115200] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 1,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_bt_2_115200] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b2_bt_4_115200] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b2_bt_2_921600] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b2_bt_4_921600] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- [pbn_b3_2_115200] = {
- .flags = FL_BASE3,
- .num_ports = 2,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b3_4_115200] = {
- .flags = FL_BASE3,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_b3_8_115200] = {
- .flags = FL_BASE3,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- [pbn_b4_bt_2_921600] = {
- .flags = FL_BASE4,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b4_bt_4_921600] = {
- .flags = FL_BASE4,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8,
- },
- [pbn_b4_bt_8_921600] = {
- .flags = FL_BASE4,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 8,
- },
-
- /*
- * Entries following this are board-specific.
- */
-
- /*
- * Panacom - IOMEM
- */
- [pbn_panacom] = {
- .flags = FL_BASE2,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x400,
- .reg_shift = 7,
- },
- [pbn_panacom2] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x400,
- .reg_shift = 7,
- },
- [pbn_panacom4] = {
- .flags = FL_BASE2|FL_BASE_BARS,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x400,
- .reg_shift = 7,
- },
-
- [pbn_exsys_4055] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
- /* I think this entry is broken - the first_offset looks wrong --rmk */
- [pbn_plx_romulus] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 8 << 2,
- .reg_shift = 2,
- .first_offset = 0x03,
- },
-
- /*
- * This board uses the size of PCI Base region 0 to
- * signal now many ports are available
- */
- [pbn_oxsemi] = {
- .flags = FL_BASE0|FL_REGION_SZ_CAP,
- .num_ports = 32,
- .base_baud = 115200,
- .uart_offset = 8,
- },
- [pbn_oxsemi_1_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_oxsemi_2_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_oxsemi_4_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_oxsemi_8_4000000] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 4000000,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
-
-
- /*
- * EKF addition for i960 Boards form EKF with serial port.
- * Max 256 ports.
- */
- [pbn_intel_i960] = {
- .flags = FL_BASE0,
- .num_ports = 32,
- .base_baud = 921600,
- .uart_offset = 8 << 2,
- .reg_shift = 2,
- .first_offset = 0x10000,
- },
- [pbn_sgi_ioc3] = {
- .flags = FL_BASE0|FL_NOIRQ,
- .num_ports = 1,
- .base_baud = 458333,
- .uart_offset = 8,
- .reg_shift = 0,
- .first_offset = 0x20178,
- },
-
- /*
- * Computone - uses IOMEM.
- */
- [pbn_computone_4] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x40,
- .reg_shift = 2,
- .first_offset = 0x200,
- },
- [pbn_computone_6] = {
- .flags = FL_BASE0,
- .num_ports = 6,
- .base_baud = 921600,
- .uart_offset = 0x40,
- .reg_shift = 2,
- .first_offset = 0x200,
- },
- [pbn_computone_8] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 0x40,
- .reg_shift = 2,
- .first_offset = 0x200,
- },
- [pbn_sbsxrsio] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 460800,
- .uart_offset = 256,
- .reg_shift = 4,
- },
- /*
- * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
- * Only basic 16550A support.
- * XR17C15[24] are not tested, but they should work.
- */
- [pbn_exar_XR17C152] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
- [pbn_exar_XR17C154] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
- [pbn_exar_XR17C158] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
- [pbn_exar_ibm_saturn] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 0x200,
- },
-
- /*
- * PA Semi PWRficient PA6T-1682M on-chip UART
- */
- [pbn_pasemi_1682M] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 8333333,
- },
- /*
- * National Instruments 843x
- */
- [pbn_ni8430_16] = {
- .flags = FL_BASE0,
- .num_ports = 16,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- [pbn_ni8430_8] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- [pbn_ni8430_4] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- [pbn_ni8430_2] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 3686400,
- .uart_offset = 0x10,
- .first_offset = 0x800,
- },
- /*
- * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
- */
- [pbn_ADDIDATA_PCIe_1_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ADDIDATA_PCIe_2_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ADDIDATA_PCIe_4_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ADDIDATA_PCIe_8_3906250] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 3906250,
- .uart_offset = 0x200,
- .first_offset = 0x1000,
- },
- [pbn_ce4100_1_115200] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .reg_shift = 2,
- },
- [pbn_omegapci] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 115200,
- .uart_offset = 0x200,
- },
- [pbn_NETMOS9900_2s_115200] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 115200,
- },
-};
-
-static const struct pci_device_id softmodem_blacklist[] = {
- { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
- { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
- { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
-};
-
-/*
- * Given a complete unknown PCI device, try to use some heuristics to
- * guess what the configuration might be, based on the pitiful PCI
- * serial specs. Returns 0 on success, 1 on failure.
- */
-static int __devinit
-serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
-{
- const struct pci_device_id *blacklist;
- int num_iomem, num_port, first_port = -1, i;
-
- /*
- * If it is not a communications device or the programming
- * interface is greater than 6, give up.
- *
- * (Should we try to make guesses for multiport serial devices
- * later?)
- */
- if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
- ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
- (dev->class & 0xff) > 6)
- return -ENODEV;
-
- /*
- * Do not access blacklisted devices that are known not to
- * feature serial ports.
- */
- for (blacklist = softmodem_blacklist;
- blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
- blacklist++) {
- if (dev->vendor == blacklist->vendor &&
- dev->device == blacklist->device)
- return -ENODEV;
- }
-
- num_iomem = num_port = 0;
- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
- if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
- num_port++;
- if (first_port == -1)
- first_port = i;
- }
- if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
- num_iomem++;
- }
-
- /*
- * If there is 1 or 0 iomem regions, and exactly one port,
- * use it. We guess the number of ports based on the IO
- * region size.
- */
- if (num_iomem <= 1 && num_port == 1) {
- board->flags = first_port;
- board->num_ports = pci_resource_len(dev, first_port) / 8;
- return 0;
- }
-
- /*
- * Now guess if we've got a board which indexes by BARs.
- * Each IO BAR should be 8 bytes, and they should follow
- * consecutively.
- */
- first_port = -1;
- num_port = 0;
- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
- if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
- pci_resource_len(dev, i) == 8 &&
- (first_port == -1 || (first_port + num_port) == i)) {
- num_port++;
- if (first_port == -1)
- first_port = i;
- }
- }
-
- if (num_port > 1) {
- board->flags = first_port | FL_BASE_BARS;
- board->num_ports = num_port;
- return 0;
- }
-
- return -ENODEV;
-}
-
-static inline int
-serial_pci_matches(const struct pciserial_board *board,
- const struct pciserial_board *guessed)
-{
- return
- board->num_ports == guessed->num_ports &&
- board->base_baud == guessed->base_baud &&
- board->uart_offset == guessed->uart_offset &&
- board->reg_shift == guessed->reg_shift &&
- board->first_offset == guessed->first_offset;
-}
-
-struct serial_private *
-pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
-{
- struct uart_port serial_port;
- struct serial_private *priv;
- struct pci_serial_quirk *quirk;
- int rc, nr_ports, i;
-
- nr_ports = board->num_ports;
-
- /*
- * Find an init and setup quirks.
- */
- quirk = find_quirk(dev);
-
- /*
- * Run the new-style initialization function.
- * The initialization function returns:
- * <0 - error
- * 0 - use board->num_ports
- * >0 - number of ports
- */
- if (quirk->init) {
- rc = quirk->init(dev);
- if (rc < 0) {
- priv = ERR_PTR(rc);
- goto err_out;
- }
- if (rc)
- nr_ports = rc;
- }
-
- priv = kzalloc(sizeof(struct serial_private) +
- sizeof(unsigned int) * nr_ports,
- GFP_KERNEL);
- if (!priv) {
- priv = ERR_PTR(-ENOMEM);
- goto err_deinit;
- }
-
- priv->dev = dev;
- priv->quirk = quirk;
-
- memset(&serial_port, 0, sizeof(struct uart_port));
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board);
- serial_port.dev = &dev->dev;
-
- for (i = 0; i < nr_ports; i++) {
- if (quirk->setup(priv, board, &serial_port, i))
- break;
-
-#ifdef SERIAL_DEBUG_PCI
- printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
- serial_port.iobase, serial_port.irq, serial_port.iotype);
-#endif
-
- priv->line[i] = serial8250_register_port(&serial_port);
- if (priv->line[i] < 0) {
- printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
- break;
- }
- }
- priv->nr = i;
- return priv;
-
-err_deinit:
- if (quirk->exit)
- quirk->exit(dev);
-err_out:
- return priv;
-}
-EXPORT_SYMBOL_GPL(pciserial_init_ports);
-
-void pciserial_remove_ports(struct serial_private *priv)
-{
- struct pci_serial_quirk *quirk;
- int i;
-
- for (i = 0; i < priv->nr; i++)
- serial8250_unregister_port(priv->line[i]);
-
- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
- if (priv->remapped_bar[i])
- iounmap(priv->remapped_bar[i]);
- priv->remapped_bar[i] = NULL;
- }
-
- /*
- * Find the exit quirks.
- */
- quirk = find_quirk(priv->dev);
- if (quirk->exit)
- quirk->exit(priv->dev);
-
- kfree(priv);
-}
-EXPORT_SYMBOL_GPL(pciserial_remove_ports);
-
-void pciserial_suspend_ports(struct serial_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->nr; i++)
- if (priv->line[i] >= 0)
- serial8250_suspend_port(priv->line[i]);
-}
-EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
-
-void pciserial_resume_ports(struct serial_private *priv)
-{
- int i;
-
- /*
- * Ensure that the board is correctly configured.
- */
- if (priv->quirk->init)
- priv->quirk->init(priv->dev);
-
- for (i = 0; i < priv->nr; i++)
- if (priv->line[i] >= 0)
- serial8250_resume_port(priv->line[i]);
-}
-EXPORT_SYMBOL_GPL(pciserial_resume_ports);
-
-/*
- * Probe one serial board. Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
-{
- struct pci_serial_quirk *quirk;
- struct serial_private *priv;
- const struct pciserial_board *board;
- struct pciserial_board tmp;
- int rc;
-
- quirk = find_quirk(dev);
- if (quirk->probe) {
- rc = quirk->probe(dev);
- if (rc)
- return rc;
- }
-
- if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
- printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
- ent->driver_data);
- return -EINVAL;
- }
-
- board = &pci_boards[ent->driver_data];
-
- rc = pci_enable_device(dev);
- pci_save_state(dev);
- if (rc)
- return rc;
-
- if (ent->driver_data == pbn_default) {
- /*
- * Use a copy of the pci_board entry for this;
- * avoid changing entries in the table.
- */
- memcpy(&tmp, board, sizeof(struct pciserial_board));
- board = &tmp;
-
- /*
- * We matched one of our class entries. Try to
- * determine the parameters of this board.
- */
- rc = serial_pci_guess_board(dev, &tmp);
- if (rc)
- goto disable;
- } else {
- /*
- * We matched an explicit entry. If we are able to
- * detect this boards settings with our heuristic,
- * then we no longer need this entry.
- */
- memcpy(&tmp, &pci_boards[pbn_default],
- sizeof(struct pciserial_board));
- rc = serial_pci_guess_board(dev, &tmp);
- if (rc == 0 && serial_pci_matches(board, &tmp))
- moan_device("Redundant entry in serial pci_table.",
- dev);
- }
-
- priv = pciserial_init_ports(dev, board);
- if (!IS_ERR(priv)) {
- pci_set_drvdata(dev, priv);
- return 0;
- }
-
- rc = PTR_ERR(priv);
-
- disable:
- pci_disable_device(dev);
- return rc;
-}
-
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
-{
- struct serial_private *priv = pci_get_drvdata(dev);
-
- pci_set_drvdata(dev, NULL);
-
- pciserial_remove_ports(priv);
-
- pci_disable_device(dev);
-}
-
-#ifdef CONFIG_PM
-static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
-{
- struct serial_private *priv = pci_get_drvdata(dev);
-
- if (priv)
- pciserial_suspend_ports(priv);
-
- pci_save_state(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
- return 0;
-}
-
-static int pciserial_resume_one(struct pci_dev *dev)
-{
- int err;
- struct serial_private *priv = pci_get_drvdata(dev);
-
- pci_set_power_state(dev, PCI_D0);
- pci_restore_state(dev);
-
- if (priv) {
- /*
- * The device may have been disabled. Re-enable it.
- */
- err = pci_enable_device(dev);
- /* FIXME: We cannot simply error out here */
- if (err)
- printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
- pciserial_resume_ports(priv);
- }
- return 0;
-}
-#endif
-
-static struct pci_device_id serial_pci_tbl[] = {
- /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
- { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
- PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
- pbn_b2_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
- pbn_b1_8_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
- pbn_b1_4_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
- pbn_b1_2_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
- pbn_b1_8_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
- pbn_b1_4_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
- pbn_b1_2_1382400 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
- pbn_b1_4_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
- pbn_b1_4_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
- pbn_b1_2_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
- pbn_b1_8_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
- pbn_b1_4_921600 },
- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
- pbn_b1_2_1250000 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
- pbn_b0_2_1843200 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
- pbn_b0_4_1843200 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_VENDOR_ID_AFAVLAB,
- PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
- pbn_b0_4_1152000 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
- pbn_b0_2_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
- pbn_b0_4_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_SUBVENDOR_ID_CONNECT_TECH,
- PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
- pbn_b0_8_1843200_200 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
- 0, 0, pbn_exar_ibm_saturn },
-
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_1_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_115200 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_460800 },
- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_115200 },
-
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- /*
- * VScom SPCOM800, from sl@s.pl
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_8_921600 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_4_921600 },
- /* Unknown card - subdevice 0x1584 */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_VENDOR_ID_PLX,
- PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
- pbn_b0_4_115200 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_KEYSPAN,
- PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
- pbn_panacom },
- { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_panacom4 },
- { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_panacom2 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
- PCI_VENDOR_ID_ESDGMBH,
- PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0,
- pbn_b2_4_115200 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
- pbn_b2_4_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
- pbn_b2_8_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
- pbn_b2_16_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIFAST,
- PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
- pbn_b2_16_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIRAS,
- PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
- pbn_b2_4_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_CHASE_PCIRAS,
- PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
- pbn_b2_8_460800 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
- PCI_SUBVENDOR_ID_EXSYS,
- PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
- pbn_exsys_4055 },
- /*
- * Megawolf Romulus PCI Serial Card, from Mike Hudson
- * (Exoray@isys.ca)
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
- 0x10b5, 0x106a, 0, 0,
- pbn_plx_romulus },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_4_115200 },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_2_115200 },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
- 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL,
- 0, 0,
- pbn_b0_4_1152000 },
- { PCI_VENDOR_ID_OXSEMI, 0x9505,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
-
- /*
- * The below card is a little controversial since it is the
- * subject of a PCI vendor/device ID clash. (See
- * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html).
- * For now just used the hex ID 0x950a.
- */
- { PCI_VENDOR_ID_OXSEMI, 0x950a,
- PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
- pbn_b0_2_115200 },
- { PCI_VENDOR_ID_OXSEMI, 0x950a,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_2_1130000 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950,
- PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_115200 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
- PCI_ANY_ID , PCI_ANY_ID, 0, 0,
- pbn_b2_8_1152000 },
-
- /*
- * Oxford Semiconductor Inc. Tornado PCI express device range.
- */
- { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- /*
- * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
- */
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
- PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
- pbn_oxsemi_8_4000000 },
-
- /*
- * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
- */
- { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
- PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
-
- /*
- * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
- * from skokodyn@yahoo.com
- */
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0,
- pbn_sbsxrsio },
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0,
- pbn_sbsxrsio },
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0,
- pbn_sbsxrsio },
- { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
- PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0,
- pbn_sbsxrsio },
-
- /*
- * Digitan DS560-558, from jimd@esoft.com
- */
- { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_115200 },
-
- /*
- * Titan Electronic cards
- * The 400L and 800L have a custom setup quirk.
- */
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_2_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b4_bt_2_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b4_bt_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b4_bt_8_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_410V3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_4_921600 },
-
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_460800 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_460800 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_460800 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_921600 },
-
- /*
- * Computone devices submitted by Doug McNash dmcnash@computone.com
- */
- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
- 0, 0, pbn_computone_4 },
- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
- 0, 0, pbn_computone_8 },
- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
- 0, 0, pbn_computone_6 },
-
- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi },
- { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
- PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_1_921600 },
-
- /*
- * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
- */
- { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_115200 },
- { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_8_115200 },
-
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_4_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_2_460800 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_1_115200 },
- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_bt_1_460800 },
-
- /*
- * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
- * Cards are identified by their subsystem vendor IDs, which
- * (in hex) match the model number.
- *
- * Note that JC140x are RS422/485 cards which require ox950
- * ACR = 0x10, and as such are not currently fully supported.
- */
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1204, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
-/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1402, 0x0002, 0, 0,
- pbn_b0_2_921600 }, */
-/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
- 0x1404, 0x0004, 0, 0,
- pbn_b0_4_921600 }, */
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
-
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
- 0x1204, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
- 0x1208, 0x0004, 0, 0,
- pbn_b0_4_921600 },
- /*
- * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
- */
- { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_1382400 },
-
- /*
- * Dell Remote Access Card III - Tim_T_Murphy@Dell.com
- */
- { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_1_1382400 },
-
- /*
- * RAStel 2 port modem, gerg@moreton.com.au
- */
- { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_bt_2_115200 },
-
- /*
- * EKF addition for i960 Boards form EKF with serial port
- */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
- 0xE4BF, PCI_ANY_ID, 0, 0,
- pbn_intel_i960 },
-
- /*
- * Xircom Cardbus/Ethernet combos
- */
- { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_115200 },
- /*
- * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
- */
- { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_115200 },
-
- /*
- * Untested PCI modems, sent in from various folks...
- */
-
- /*
- * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
- */
- { PCI_VENDOR_ID_ROCKWELL, 0x1004,
- 0x1048, 0x1500, 0, 0,
- pbn_b1_1_115200 },
-
- { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
- 0xFF00, 0, 0, 0,
- pbn_sgi_ioc3 },
-
- /*
- * HP Diva card
- */
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
- PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0,
- pbn_b1_1_115200 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_5_115200 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b2_1_115200 },
-
- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b3_2_115200 },
- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b3_4_115200 },
- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b3_8_115200 },
-
- /*
- * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
- */
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_exar_XR17C152 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_exar_XR17C154 },
- { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_exar_XR17C158 },
-
- /*
- * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
- */
- { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_115200 },
- /*
- * ITE
- */
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
- PCI_ANY_ID, PCI_ANY_ID,
- 0, 0,
- pbn_b1_bt_1_115200 },
-
- /*
- * IntaShield IS-200
- */
- { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */
- pbn_b2_2_115200 },
- /*
- * IntaShield IS-400
- */
- { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
- pbn_b2_4_115200 },
- /*
- * Perle PCI-RAS cards
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
- PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
- 0, 0, pbn_b2_4_921600 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
- PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
- 0, 0, pbn_b2_8_921600 },
-
- /*
- * Mainpine series cards: Fairly standard layout but fools
- * parts of the autodetect in some cases and uses otherwise
- * unmatched communications subclasses in the PCI Express case
- */
-
- { /* RockForceDUO */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0200,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceQUATRO */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0300,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceDUO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0400,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceQUATRO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0500,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForce+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0600,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForce+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0700,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceOCTO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0800,
- 0, 0, pbn_b0_8_115200 },
- { /* RockForceDUO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0C00,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceQUARTRO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x0D00,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceOCTO+ */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x1D00,
- 0, 0, pbn_b0_8_115200 },
- { /* RockForceD1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2000,
- 0, 0, pbn_b0_1_115200 },
- { /* RockForceF1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2100,
- 0, 0, pbn_b0_1_115200 },
- { /* RockForceD2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2200,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceF2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2300,
- 0, 0, pbn_b0_2_115200 },
- { /* RockForceD4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2400,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceF4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2500,
- 0, 0, pbn_b0_4_115200 },
- { /* RockForceD8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2600,
- 0, 0, pbn_b0_8_115200 },
- { /* RockForceF8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x2700,
- 0, 0, pbn_b0_8_115200 },
- { /* IQ Express D1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3000,
- 0, 0, pbn_b0_1_115200 },
- { /* IQ Express F1 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3100,
- 0, 0, pbn_b0_1_115200 },
- { /* IQ Express D2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3200,
- 0, 0, pbn_b0_2_115200 },
- { /* IQ Express F2 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3300,
- 0, 0, pbn_b0_2_115200 },
- { /* IQ Express D4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3400,
- 0, 0, pbn_b0_4_115200 },
- { /* IQ Express F4 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3500,
- 0, 0, pbn_b0_4_115200 },
- { /* IQ Express D8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3C00,
- 0, 0, pbn_b0_8_115200 },
- { /* IQ Express F8 */
- PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
- PCI_VENDOR_ID_MAINPINE, 0x3D00,
- 0, 0, pbn_b0_8_115200 },
-
-
- /*
- * PA Semi PA6T-1682M on-chip UART
- */
- { PCI_VENDOR_ID_PASEMI, 0xa004,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pasemi_1682M },
-
- /*
- * National Instruments
- */
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_16_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322I,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_16_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_8_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_4_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b1_bt_2_115200 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_8 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2328,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_8 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_16 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_23216,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_16 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_2 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
- { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ni8430_4 },
-
- /*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7500,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_4_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7420,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_2_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7300,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA_OLD,
- PCI_DEVICE_ID_ADDIDATA_APCI7800,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b1_8_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7500_2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_4_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7420_2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_2_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7300_2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7500_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_4_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7420_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_2_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7300_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCI7800_3,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_b0_8_115200 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7500,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_4_3906250 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7420,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_2_3906250 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7300,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_1_3906250 },
-
- { PCI_VENDOR_ID_ADDIDATA,
- PCI_DEVICE_ID_ADDIDATA_APCIe7800,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- pbn_ADDIDATA_PCIe_8_3906250 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
- PCI_VENDOR_ID_IBM, 0x0299,
- 0, 0, pbn_b0_bt_2_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- /* the 9901 is a rebranded 9912 */
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
- 0xA000, 0x3002,
- 0, 0, pbn_NETMOS9900_2s_115200 },
-
- /*
- * Best Connectivity and Rosewill PCI Multi I/O cards
- */
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
- 0xA000, 0x1000,
- 0, 0, pbn_b0_1_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
- 0xA000, 0x3002,
- 0, 0, pbn_b0_bt_2_115200 },
-
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
- 0xA000, 0x3004,
- 0, 0, pbn_b0_bt_4_115200 },
- /* Intel CE4100 */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_ce4100_1_115200 },
-
- /*
- * Cronyx Omega PCI
- */
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_omegapci },
-
- /*
- * These entries match devices with class COMMUNICATION_SERIAL,
- * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
- */
- { PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8,
- 0xffff00, pbn_default },
- { PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_MODEM << 8,
- 0xffff00, pbn_default },
- { PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_MULTISERIAL << 8,
- 0xffff00, pbn_default },
- { 0, }
-};
-
-static pci_ers_result_t serial8250_io_error_detected(struct pci_dev *dev,
- pci_channel_state_t state)
-{
- struct serial_private *priv = pci_get_drvdata(dev);
-
- if (state == pci_channel_io_perm_failure)
- return PCI_ERS_RESULT_DISCONNECT;
-
- if (priv)
- pciserial_suspend_ports(priv);
-
- pci_disable_device(dev);
-
- return PCI_ERS_RESULT_NEED_RESET;
-}
-
-static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
-{
- int rc;
-
- rc = pci_enable_device(dev);
-
- if (rc)
- return PCI_ERS_RESULT_DISCONNECT;
-
- pci_restore_state(dev);
- pci_save_state(dev);
-
- return PCI_ERS_RESULT_RECOVERED;
-}
-
-static void serial8250_io_resume(struct pci_dev *dev)
-{
- struct serial_private *priv = pci_get_drvdata(dev);
-
- if (priv)
- pciserial_resume_ports(priv);
-}
-
-static struct pci_error_handlers serial8250_err_handler = {
- .error_detected = serial8250_io_error_detected,
- .slot_reset = serial8250_io_slot_reset,
- .resume = serial8250_io_resume,
-};
-
-static struct pci_driver serial_pci_driver = {
- .name = "serial",
- .probe = pciserial_init_one,
- .remove = __devexit_p(pciserial_remove_one),
-#ifdef CONFIG_PM
- .suspend = pciserial_suspend_one,
- .resume = pciserial_resume_one,
-#endif
- .id_table = serial_pci_tbl,
- .err_handler = &serial8250_err_handler,
-};
-
-static int __init serial8250_pci_init(void)
-{
- return pci_register_driver(&serial_pci_driver);
-}
-
-static void __exit serial8250_pci_exit(void)
-{
- pci_unregister_driver(&serial_pci_driver);
-}
-
-module_init(serial8250_pci_init);
-module_exit(serial8250_pci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
+++ /dev/null
-/*
- * Probe module for 8250/16550-type ISAPNP serial ports.
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- * Ported to the Linux PnP Layer - (C) Adam Belay.
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pnp.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/serial_core.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-
-#include "8250.h"
-
-#define UNKNOWN_DEV 0x3000
-
-
-static const struct pnp_device_id pnp_dev_table[] = {
- /* Archtek America Corp. */
- /* Archtek SmartLink Modem 3334BT Plug & Play */
- { "AAC000F", 0 },
- /* Anchor Datacomm BV */
- /* SXPro 144 External Data Fax Modem Plug & Play */
- { "ADC0001", 0 },
- /* SXPro 288 External Data Fax Modem Plug & Play */
- { "ADC0002", 0 },
- /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
- { "AEI0250", 0 },
- /* Actiontec ISA PNP 56K X2 Fax Modem */
- { "AEI1240", 0 },
- /* Rockwell 56K ACF II Fax+Data+Voice Modem */
- { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
- /* AZT3005 PnP SOUND DEVICE */
- { "AZT4001", 0 },
- /* Best Data Products Inc. Smart One 336F PnP Modem */
- { "BDP3336", 0 },
- /* Boca Research */
- /* Boca Complete Ofc Communicator 14.4 Data-FAX */
- { "BRI0A49", 0 },
- /* Boca Research 33,600 ACF Modem */
- { "BRI1400", 0 },
- /* Boca 33.6 Kbps Internal FD34FSVD */
- { "BRI3400", 0 },
- /* Boca 33.6 Kbps Internal FD34FSVD */
- { "BRI0A49", 0 },
- /* Best Data Products Inc. Smart One 336F PnP Modem */
- { "BDP3336", 0 },
- /* Computer Peripherals Inc */
- /* EuroViVa CommCenter-33.6 SP PnP */
- { "CPI4050", 0 },
- /* Creative Labs */
- /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
- { "CTL3001", 0 },
- /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
- { "CTL3011", 0 },
- /* Davicom ISA 33.6K Modem */
- { "DAV0336", 0 },
- /* Creative */
- /* Creative Modem Blaster Flash56 DI5601-1 */
- { "DMB1032", 0 },
- /* Creative Modem Blaster V.90 DI5660 */
- { "DMB2001", 0 },
- /* E-Tech */
- /* E-Tech CyberBULLET PC56RVP */
- { "ETT0002", 0 },
- /* FUJITSU */
- /* Fujitsu 33600 PnP-I2 R Plug & Play */
- { "FUJ0202", 0 },
- /* Fujitsu FMV-FX431 Plug & Play */
- { "FUJ0205", 0 },
- /* Fujitsu 33600 PnP-I4 R Plug & Play */
- { "FUJ0206", 0 },
- /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
- { "FUJ0209", 0 },
- /* Archtek America Corp. */
- /* Archtek SmartLink Modem 3334BT Plug & Play */
- { "GVC000F", 0 },
- /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
- { "GVC0303", 0 },
- /* Hayes */
- /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
- { "HAY0001", 0 },
- /* Hayes Optima 336 V.34 + FAX + Voice PnP */
- { "HAY000C", 0 },
- /* Hayes Optima 336B V.34 + FAX + Voice PnP */
- { "HAY000D", 0 },
- /* Hayes Accura 56K Ext Fax Modem PnP */
- { "HAY5670", 0 },
- /* Hayes Accura 56K Ext Fax Modem PnP */
- { "HAY5674", 0 },
- /* Hayes Accura 56K Fax Modem PnP */
- { "HAY5675", 0 },
- /* Hayes 288, V.34 + FAX */
- { "HAYF000", 0 },
- /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
- { "HAYF001", 0 },
- /* IBM */
- /* IBM Thinkpad 701 Internal Modem Voice */
- { "IBM0033", 0 },
- /* Intermec */
- /* Intermec CV60 touchscreen port */
- { "PNP4972", 0 },
- /* Intertex */
- /* Intertex 28k8 33k6 Voice EXT PnP */
- { "IXDC801", 0 },
- /* Intertex 33k6 56k Voice EXT PnP */
- { "IXDC901", 0 },
- /* Intertex 28k8 33k6 Voice SP EXT PnP */
- { "IXDD801", 0 },
- /* Intertex 33k6 56k Voice SP EXT PnP */
- { "IXDD901", 0 },
- /* Intertex 28k8 33k6 Voice SP INT PnP */
- { "IXDF401", 0 },
- /* Intertex 28k8 33k6 Voice SP EXT PnP */
- { "IXDF801", 0 },
- /* Intertex 33k6 56k Voice SP EXT PnP */
- { "IXDF901", 0 },
- /* Kortex International */
- /* KORTEX 28800 Externe PnP */
- { "KOR4522", 0 },
- /* KXPro 33.6 Vocal ASVD PnP */
- { "KORF661", 0 },
- /* Lasat */
- /* LASAT Internet 33600 PnP */
- { "LAS4040", 0 },
- /* Lasat Safire 560 PnP */
- { "LAS4540", 0 },
- /* Lasat Safire 336 PnP */
- { "LAS5440", 0 },
- /* Microcom, Inc. */
- /* Microcom TravelPorte FAST V.34 Plug & Play */
- { "MNP0281", 0 },
- /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
- { "MNP0336", 0 },
- /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
- { "MNP0339", 0 },
- /* Microcom DeskPorte 28.8P Plug & Play */
- { "MNP0342", 0 },
- /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
- { "MNP0500", 0 },
- /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
- { "MNP0501", 0 },
- /* Microcom DeskPorte 28.8S Internal Plug & Play */
- { "MNP0502", 0 },
- /* Motorola */
- /* Motorola BitSURFR Plug & Play */
- { "MOT1105", 0 },
- /* Motorola TA210 Plug & Play */
- { "MOT1111", 0 },
- /* Motorola HMTA 200 (ISDN) Plug & Play */
- { "MOT1114", 0 },
- /* Motorola BitSURFR Plug & Play */
- { "MOT1115", 0 },
- /* Motorola Lifestyle 28.8 Internal */
- { "MOT1190", 0 },
- /* Motorola V.3400 Plug & Play */
- { "MOT1501", 0 },
- /* Motorola Lifestyle 28.8 V.34 Plug & Play */
- { "MOT1502", 0 },
- /* Motorola Power 28.8 V.34 Plug & Play */
- { "MOT1505", 0 },
- /* Motorola ModemSURFR External 28.8 Plug & Play */
- { "MOT1509", 0 },
- /* Motorola Premier 33.6 Desktop Plug & Play */
- { "MOT150A", 0 },
- /* Motorola VoiceSURFR 56K External PnP */
- { "MOT150F", 0 },
- /* Motorola ModemSURFR 56K External PnP */
- { "MOT1510", 0 },
- /* Motorola ModemSURFR 56K Internal PnP */
- { "MOT1550", 0 },
- /* Motorola ModemSURFR Internal 28.8 Plug & Play */
- { "MOT1560", 0 },
- /* Motorola Premier 33.6 Internal Plug & Play */
- { "MOT1580", 0 },
- /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
- { "MOT15B0", 0 },
- /* Motorola VoiceSURFR 56K Internal PnP */
- { "MOT15F0", 0 },
- /* Com 1 */
- /* Deskline K56 Phone System PnP */
- { "MVX00A1", 0 },
- /* PC Rider K56 Phone System PnP */
- { "MVX00F2", 0 },
- /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
- { "nEC8241", 0 },
- /* Pace 56 Voice Internal Plug & Play Modem */
- { "PMC2430", 0 },
- /* Generic */
- /* Generic standard PC COM port */
- { "PNP0500", 0 },
- /* Generic 16550A-compatible COM port */
- { "PNP0501", 0 },
- /* Compaq 14400 Modem */
- { "PNPC000", 0 },
- /* Compaq 2400/9600 Modem */
- { "PNPC001", 0 },
- /* Dial-Up Networking Serial Cable between 2 PCs */
- { "PNPC031", 0 },
- /* Dial-Up Networking Parallel Cable between 2 PCs */
- { "PNPC032", 0 },
- /* Standard 9600 bps Modem */
- { "PNPC100", 0 },
- /* Standard 14400 bps Modem */
- { "PNPC101", 0 },
- /* Standard 28800 bps Modem*/
- { "PNPC102", 0 },
- /* Standard Modem*/
- { "PNPC103", 0 },
- /* Standard 9600 bps Modem*/
- { "PNPC104", 0 },
- /* Standard 14400 bps Modem*/
- { "PNPC105", 0 },
- /* Standard 28800 bps Modem*/
- { "PNPC106", 0 },
- /* Standard Modem */
- { "PNPC107", 0 },
- /* Standard 9600 bps Modem */
- { "PNPC108", 0 },
- /* Standard 14400 bps Modem */
- { "PNPC109", 0 },
- /* Standard 28800 bps Modem */
- { "PNPC10A", 0 },
- /* Standard Modem */
- { "PNPC10B", 0 },
- /* Standard 9600 bps Modem */
- { "PNPC10C", 0 },
- /* Standard 14400 bps Modem */
- { "PNPC10D", 0 },
- /* Standard 28800 bps Modem */
- { "PNPC10E", 0 },
- /* Standard Modem */
- { "PNPC10F", 0 },
- /* Standard PCMCIA Card Modem */
- { "PNP2000", 0 },
- /* Rockwell */
- /* Modular Technology */
- /* Rockwell 33.6 DPF Internal PnP */
- /* Modular Technology 33.6 Internal PnP */
- { "ROK0030", 0 },
- /* Kortex International */
- /* KORTEX 14400 Externe PnP */
- { "ROK0100", 0 },
- /* Rockwell 28.8 */
- { "ROK4120", 0 },
- /* Viking Components, Inc */
- /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
- { "ROK4920", 0 },
- /* Rockwell */
- /* British Telecom */
- /* Modular Technology */
- /* Rockwell 33.6 DPF External PnP */
- /* BT Prologue 33.6 External PnP */
- /* Modular Technology 33.6 External PnP */
- { "RSS00A0", 0 },
- /* Viking 56K FAX INT */
- { "RSS0262", 0 },
- /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
- { "RSS0250", 0 },
- /* SupraExpress 28.8 Data/Fax PnP modem */
- { "SUP1310", 0 },
- /* SupraExpress 336i PnP Voice Modem */
- { "SUP1381", 0 },
- /* SupraExpress 33.6 Data/Fax PnP modem */
- { "SUP1421", 0 },
- /* SupraExpress 33.6 Data/Fax PnP modem */
- { "SUP1590", 0 },
- /* SupraExpress 336i Sp ASVD */
- { "SUP1620", 0 },
- /* SupraExpress 33.6 Data/Fax PnP modem */
- { "SUP1760", 0 },
- /* SupraExpress 56i Sp Intl */
- { "SUP2171", 0 },
- /* Phoebe Micro */
- /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
- { "TEX0011", 0 },
- /* Archtek America Corp. */
- /* Archtek SmartLink Modem 3334BT Plug & Play */
- { "UAC000F", 0 },
- /* 3Com Corp. */
- /* Gateway Telepath IIvi 33.6 */
- { "USR0000", 0 },
- /* U.S. Robotics Sporster 33.6K Fax INT PnP */
- { "USR0002", 0 },
- /* Sportster Vi 14.4 PnP FAX Voicemail */
- { "USR0004", 0 },
- /* U.S. Robotics 33.6K Voice INT PnP */
- { "USR0006", 0 },
- /* U.S. Robotics 33.6K Voice EXT PnP */
- { "USR0007", 0 },
- /* U.S. Robotics Courier V.Everything INT PnP */
- { "USR0009", 0 },
- /* U.S. Robotics 33.6K Voice INT PnP */
- { "USR2002", 0 },
- /* U.S. Robotics 56K Voice INT PnP */
- { "USR2070", 0 },
- /* U.S. Robotics 56K Voice EXT PnP */
- { "USR2080", 0 },
- /* U.S. Robotics 56K FAX INT */
- { "USR3031", 0 },
- /* U.S. Robotics 56K FAX INT */
- { "USR3050", 0 },
- /* U.S. Robotics 56K Voice INT PnP */
- { "USR3070", 0 },
- /* U.S. Robotics 56K Voice EXT PnP */
- { "USR3080", 0 },
- /* U.S. Robotics 56K Voice INT PnP */
- { "USR3090", 0 },
- /* U.S. Robotics 56K Message */
- { "USR9100", 0 },
- /* U.S. Robotics 56K FAX EXT PnP*/
- { "USR9160", 0 },
- /* U.S. Robotics 56K FAX INT PnP*/
- { "USR9170", 0 },
- /* U.S. Robotics 56K Voice EXT PnP*/
- { "USR9180", 0 },
- /* U.S. Robotics 56K Voice INT PnP*/
- { "USR9190", 0 },
- /* Wacom tablets */
- { "WACFXXX", 0 },
- /* Compaq touchscreen */
- { "FPI2002", 0 },
- /* Fujitsu Stylistic touchscreens */
- { "FUJ02B2", 0 },
- { "FUJ02B3", 0 },
- /* Fujitsu Stylistic LT touchscreens */
- { "FUJ02B4", 0 },
- /* Passive Fujitsu Stylistic touchscreens */
- { "FUJ02B6", 0 },
- { "FUJ02B7", 0 },
- { "FUJ02B8", 0 },
- { "FUJ02B9", 0 },
- { "FUJ02BC", 0 },
- /* Fujitsu Wacom Tablet PC device */
- { "FUJ02E5", 0 },
- /* Fujitsu P-series tablet PC device */
- { "FUJ02E6", 0 },
- /* Fujitsu Wacom 2FGT Tablet PC device */
- { "FUJ02E7", 0 },
- /* Fujitsu Wacom 1FGT Tablet PC device */
- { "FUJ02E9", 0 },
- /*
- * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
- * disguise)
- */
- { "LTS0001", 0 },
- /* Rockwell's (PORALiNK) 33600 INT PNP */
- { "WCI0003", 0 },
- /* Unknown PnP modems */
- { "PNPCXXX", UNKNOWN_DEV },
- /* More unknown PnP modems */
- { "PNPDXXX", UNKNOWN_DEV },
- { "", 0 }
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static char *modem_names[] __devinitdata = {
- "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
- "56K", "56k", "K56", "33.6", "28.8", "14.4",
- "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
- "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
-};
-
-static int __devinit check_name(char *name)
-{
- char **tmp;
-
- for (tmp = modem_names; *tmp; tmp++)
- if (strstr(name, *tmp))
- return 1;
-
- return 0;
-}
-
-static int __devinit check_resources(struct pnp_dev *dev)
-{
- resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
- int i;
-
- for (i = 0; i < ARRAY_SIZE(base); i++) {
- if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Given a complete unknown PnP device, try to use some heuristics to
- * detect modems. Currently use such heuristic set:
- * - dev->name or dev->bus->name must contain "modem" substring;
- * - device must have only one IO region (8 byte long) with base address
- * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
- *
- * Such detection looks very ugly, but can detect at least some of numerous
- * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
- * table.
- */
-static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
-{
- if (!(check_name(pnp_dev_name(dev)) ||
- (dev->card && check_name(dev->card->name))))
- return -ENODEV;
-
- if (check_resources(dev))
- return 0;
-
- return -ENODEV;
-}
-
-static int __devinit
-serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
- struct uart_port port;
- int ret, line, flags = dev_id->driver_data;
-
- if (flags & UNKNOWN_DEV) {
- ret = serial_pnp_guess_board(dev, &flags);
- if (ret < 0)
- return ret;
- }
-
- memset(&port, 0, sizeof(struct uart_port));
- if (pnp_irq_valid(dev, 0))
- port.irq = pnp_irq(dev, 0);
- if (pnp_port_valid(dev, 0)) {
- port.iobase = pnp_port_start(dev, 0);
- port.iotype = UPIO_PORT;
- } else if (pnp_mem_valid(dev, 0)) {
- port.mapbase = pnp_mem_start(dev, 0);
- port.iotype = UPIO_MEM;
- port.flags = UPF_IOREMAP;
- } else
- return -ENODEV;
-
-#ifdef SERIAL_DEBUG_PNP
- printk(KERN_DEBUG
- "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
- port.iobase, port.mapbase, port.irq, port.iotype);
-#endif
-
- port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
- if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
- port.flags |= UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &dev->dev;
-
- line = serial8250_register_port(&port);
- if (line < 0)
- return -ENODEV;
-
- pnp_set_drvdata(dev, (void *)((long)line + 1));
- return 0;
-}
-
-static void __devexit serial_pnp_remove(struct pnp_dev *dev)
-{
- long line = (long)pnp_get_drvdata(dev);
- if (line)
- serial8250_unregister_port(line - 1);
-}
-
-#ifdef CONFIG_PM
-static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
-{
- long line = (long)pnp_get_drvdata(dev);
-
- if (!line)
- return -ENODEV;
- serial8250_suspend_port(line - 1);
- return 0;
-}
-
-static int serial_pnp_resume(struct pnp_dev *dev)
-{
- long line = (long)pnp_get_drvdata(dev);
-
- if (!line)
- return -ENODEV;
- serial8250_resume_port(line - 1);
- return 0;
-}
-#else
-#define serial_pnp_suspend NULL
-#define serial_pnp_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pnp_driver serial_pnp_driver = {
- .name = "serial",
- .probe = serial_pnp_probe,
- .remove = __devexit_p(serial_pnp_remove),
- .suspend = serial_pnp_suspend,
- .resume = serial_pnp_resume,
- .id_table = pnp_dev_table,
-};
-
-static int __init serial8250_pnp_init(void)
-{
- return pnp_register_driver(&serial_pnp_driver);
-}
-
-static void __exit serial8250_pnp_exit(void)
-{
- pnp_unregister_driver(&serial_pnp_driver);
-}
-
-module_init(serial8250_pnp_init);
-module_exit(serial8250_pnp_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
menu "Serial drivers"
depends on HAS_IOMEM
-#
-# The new 8250/16550 serial drivers
-config SERIAL_8250
- tristate "8250/16550 and compatible serial support"
- select SERIAL_CORE
- ---help---
- This selects whether you want to include the driver for the standard
- serial ports. The standard answer is Y. People who might say N
- here are those that are setting up dedicated Ethernet WWW/FTP
- servers, or users that have one of the various bus mice instead of a
- serial mouse and don't intend to use their machine's standard serial
- port for anything. (Note that the Cyclades and Stallion multi
- serial port drivers do not need this driver built in for them to
- work.)
-
- To compile this driver as a module, choose M here: the
- module will be called 8250.
- [WARNING: Do not compile this driver as a module if you are using
- non-standard serial ports, since the configuration information will
- be lost when the driver is unloaded. This limitation may be lifted
- in the future.]
-
- BTW1: If you have a mouseman serial mouse which is not recognized by
- the X window system, try running gpm first.
-
- BTW2: If you intend to use a software modem (also called Winmodem)
- under Linux, forget it. These modems are crippled and require
- proprietary drivers which are only available under Windows.
-
- Most people will say Y or M here, so that they can use serial mice,
- modems and similar devices connecting to the standard serial ports.
-
-config SERIAL_8250_CONSOLE
- bool "Console on 8250/16550 and compatible serial port"
- depends on SERIAL_8250=y
- select SERIAL_CORE_CONSOLE
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode). This could be useful if some terminal or printer is connected
- to that serial port.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyS1". (Try "man bootparam" or see the documentation of
- your boot loader (grub or lilo or loadlin) about how to pass options
- to the kernel at boot time.)
-
- If you don't have a VGA card installed and you say Y here, the
- kernel will automatically use the first serial line, /dev/ttyS0, as
- system console.
-
- You can set that using a kernel command line option such as
- "console=uart8250,io,0x3f8,9600n8"
- "console=uart8250,mmio,0xff5e0000,115200n8".
- and it will switch to normal serial console when the corresponding
- port is ready.
- "earlycon=uart8250,io,0x3f8,9600n8"
- "earlycon=uart8250,mmio,0xff5e0000,115200n8".
- it will not only setup early console.
-
- If unsure, say N.
-
-config FIX_EARLYCON_MEM
- bool
- depends on X86
- default y
-
-config SERIAL_8250_GSC
- tristate
- depends on SERIAL_8250 && GSC
- default SERIAL_8250
-
-config SERIAL_8250_PCI
- tristate "8250/16550 PCI device support" if EXPERT
- depends on SERIAL_8250 && PCI
- default SERIAL_8250
- help
- This builds standard PCI serial support. You may be able to
- disable this feature if you only need legacy serial support.
- Saves about 9K.
-
-config SERIAL_8250_PNP
- tristate "8250/16550 PNP device support" if EXPERT
- depends on SERIAL_8250 && PNP
- default SERIAL_8250
- help
- This builds standard PNP serial support. You may be able to
- disable this feature if you only need legacy serial support.
-
-config SERIAL_8250_FSL
- bool
- depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
- default PPC
-
-config SERIAL_8250_HP300
- tristate
- depends on SERIAL_8250 && HP300
- default SERIAL_8250
-
-config SERIAL_8250_CS
- tristate "8250/16550 PCMCIA device support"
- depends on PCMCIA && SERIAL_8250
- ---help---
- Say Y here to enable support for 16-bit PCMCIA serial devices,
- including serial port cards, modems, and the modem functions of
- multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
- credit-card size devices often used with laptops.)
-
- To compile this driver as a module, choose M here: the
- module will be called serial_cs.
-
- If unsure, say N.
-
-config SERIAL_8250_NR_UARTS
- int "Maximum number of 8250/16550 serial ports"
- depends on SERIAL_8250
- default "4"
- help
- Set this to the number of serial ports you want the driver
- to support. This includes any ports discovered via ACPI or
- PCI enumeration and any ports that may be added at run-time
- via hot-plug, or any ISA multi-port serial cards.
-
-config SERIAL_8250_RUNTIME_UARTS
- int "Number of 8250/16550 serial ports to register at runtime"
- depends on SERIAL_8250
- range 0 SERIAL_8250_NR_UARTS
- default "4"
- help
- Set this to the maximum number of serial ports you want
- the kernel to register at boot time. This can be overridden
- with the module parameter "nr_uarts", or boot-time parameter
- 8250.nr_uarts
-
-config SERIAL_8250_EXTENDED
- bool "Extended 8250/16550 serial driver options"
- depends on SERIAL_8250
- help
- If you wish to use any non-standard features of the standard "dumb"
- driver, say Y here. This includes HUB6 support, shared serial
- interrupts, special multiport support, support for more than the
- four COM 1/2/3/4 boards, etc.
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about serial driver options. If unsure, say N.
-
-config SERIAL_8250_MANY_PORTS
- bool "Support more than 4 legacy serial ports"
- depends on SERIAL_8250_EXTENDED && !IA64
- help
- Say Y here if you have dumb serial boards other than the four
- standard COM 1/2/3/4 ports. This may happen if you have an AST
- FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
- from <http://www.tldp.org/docs.html#howto>), or other custom
- serial port hardware which acts similar to standard serial port
- hardware. If you only use the standard COM 1/2/3/4 ports, you can
- say N here to save some memory. You can also say Y if you have an
- "intelligent" multiport card such as Cyclades, Digiboards, etc.
-
-#
-# Multi-port serial cards
-#
-
-config SERIAL_8250_FOURPORT
- tristate "Support Fourport cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have an AST FourPort serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_fourport.
-
-config SERIAL_8250_ACCENT
- tristate "Support Accent cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have an Accent Async serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_accent.
-
-config SERIAL_8250_BOCA
- tristate "Support Boca cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have a Boca serial board. Please read the Boca
- mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_boca.
-
-config SERIAL_8250_EXAR_ST16C554
- tristate "Support Exar ST16C554/554D Quad UART"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
- tinkering with your Envoy TU301, or have a machine with this UART,
- say Y here.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_exar_st16c554.
-
-config SERIAL_8250_HUB6
- tristate "Support Hub6 cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have a HUB6 serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_hub6.
-
-config SERIAL_8250_SHARE_IRQ
- bool "Support for sharing serial interrupts"
- depends on SERIAL_8250_EXTENDED
- help
- Some serial boards have hardware support which allows multiple dumb
- serial ports on the same board to share a single IRQ. To enable
- support for this in the serial driver, say Y here.
-
-config SERIAL_8250_DETECT_IRQ
- bool "Autodetect IRQ on standard ports (unsafe)"
- depends on SERIAL_8250_EXTENDED
- help
- Say Y here if you want the kernel to try to guess which IRQ
- to use for your serial port.
-
- This is considered unsafe; it is far better to configure the IRQ in
- a boot script using the setserial command.
-
- If unsure, say N.
-
-config SERIAL_8250_RSA
- bool "Support RSA serial ports"
- depends on SERIAL_8250_EXTENDED
- help
- ::: To be written :::
-
-config SERIAL_8250_MCA
- tristate "Support 8250-type ports on MCA buses"
- depends on SERIAL_8250 != n && MCA
- help
- Say Y here if you have a MCA serial ports.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_mca.
-
-config SERIAL_8250_ACORN
- tristate "Acorn expansion card serial port support"
- depends on ARCH_ACORN && SERIAL_8250
- help
- If you have an Atomwide Serial card or Serial Port card for an Acorn
- system, say Y to this option. The driver can handle 1, 2, or 3 port
- cards. If unsure, say N.
-
-config SERIAL_8250_RM9K
- bool "Support for MIPS RM9xxx integrated serial port"
- depends on SERIAL_8250 != n && SERIAL_RM9000
- select SERIAL_8250_SHARE_IRQ
- help
- Selecting this option will add support for the integrated serial
- port hardware found on MIPS RM9122 and similar processors.
- If unsure, say N.
-
-config SERIAL_8250_DW
- tristate "Support for Synopsys DesignWare 8250 quirks"
- depends on SERIAL_8250 && OF
- help
- Selecting this option will enable handling of the extra features
- present in the Synopsys DesignWare APB UART.
+source "drivers/tty/serial/8250/Kconfig"
comment "Non-8250 serial port support"
help
MAX3107 chip support
-config SERIAL_MAX3107_AAVA
- tristate "MAX3107 AAVA platform support"
- depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB
- select SERIAL_CORE
- help
- Support for the MAX3107 chip configuration found on the AAVA
- platform. Includes the extra initialisation and GPIO support
- neded for this device.
-
config SERIAL_DZ
bool "DECstation DZ serial driver"
depends on MACH_DECSTATION && 32BIT
obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
-obj-$(CONFIG_SERIAL_8250) += 8250.o
-obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
-obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
-obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
-obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
-obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
-obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
-obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
-obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
-obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
-obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
-obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
-obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
-obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
-obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
-obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
+# Now bring in any enabled 8250/16450/16550 type drivers.
+obj-$(CONFIG_SERIAL_8250) += 8250/
+
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
-obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
unsigned int fifosize; /* vendor-specific */
unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */
+ unsigned int old_cr; /* state during shutdown */
bool autorts;
char type[12];
bool interrupt_may_hang; /* vendor-specific */
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
barrier();
- cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
+ /* restore RTS and DTR */
+ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
+ cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
/* Clear pending error interrupts */
static void pl011_shutdown(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
+ unsigned int cr;
/*
* disable all interrupts
/*
* disable the port
+ * disable the port. It should not disable RTS and DTR.
+ * Also RTS and DTR state should be preserved to restore
+ * it during startup().
*/
uap->autorts = false;
- writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);
+ cr = readw(uap->port.membase + UART011_CR);
+ uap->old_cr = cr;
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
+ cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
+ writew(cr, uap->port.membase + UART011_CR);
/*
* disable break condition and fifos
{
struct uart_amba_port *uap = amba_ports[co->index];
unsigned int status, old_cr, new_cr;
+ unsigned long flags;
+ int locked = 1;
clk_enable(uap->clk);
+ local_irq_save(flags);
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&uap->port.lock);
+ else
+ spin_lock(&uap->port.lock);
+
/*
* First save the CR then disable the interrupts
*/
} while (status & UART01x_FR_BUSY);
writew(old_cr, uap->port.membase + UART011_CR);
+ if (locked)
+ spin_unlock(&uap->port.lock);
+ local_irq_restore(flags);
+
clk_disable(uap->clk);
}
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
+ uap->old_cr = 0;
uap->fifosize = vendor->fifosize;
uap->interrupt_may_hang = vendor->interrupt_may_hang;
uap->port.dev = &dev->dev;
struct jsm_board *brd = pci_get_drvdata(pdev);
pci_restore_state(pdev);
+ pci_save_state(pdev);
jsm_uart_port_init(brd);
}
+++ /dev/null
-/*
- * m32r_sio.c
- *
- * Driver for M32R serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- * Based on drivers/serial/8250.c.
- *
- * Copyright (C) 2001 Russell King.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
- *
- * 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.
- */
-
-/*
- * A note about mapbase / membase
- *
- * mapbase is the physical address of the IO port. Currently, we don't
- * support this very well, and it may well be dropped from this driver
- * in future. As such, mapbase should be NULL.
- *
- * membase is an 'ioremapped' cookie. This is compatible with the old
- * serial.c driver, and is currently the preferred form.
- */
-
-#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/delay.h>
-
-#include <asm/m32r.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define PORT_M32R_BASE PORT_M32R_SIO
-#define PORT_INDEX(x) (x - PORT_M32R_BASE + 1)
-#define BAUD_RATE 115200
-
-#include <linux/serial_core.h>
-#include "m32r_sio.h"
-#include "m32r_sio_reg.h"
-
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
-#define PASS_LIMIT 256
-
-/*
- * We default to IRQ0 for the "no irq" hack. Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-#define BASE_BAUD 115200
-
-/* Standard COM flags */
-#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
-
-/*
- * SERIAL_PORT_DFNS tells us about built-in ports that have no
- * standard enumeration mechanism. Platforms that can find all
- * serial ports via mechanisms like ACPI or PCI need not supply it.
- */
-#if defined(CONFIG_PLAT_USRV)
-
-#define SERIAL_PORT_DFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */
-
-#else /* !CONFIG_PLAT_USRV */
-
-#if defined(CONFIG_SERIAL_M32R_PLDSIO)
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, \
- STD_COM_FLAGS }, /* ttyS0 */
-#else
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, \
- STD_COM_FLAGS }, /* ttyS0 */
-#endif
-
-#endif /* !CONFIG_PLAT_USRV */
-
-static struct old_serial_port old_serial_port[] = {
- SERIAL_PORT_DFNS
-};
-
-#define UART_NR ARRAY_SIZE(old_serial_port)
-
-struct uart_sio_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short rev;
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char lsr_break_flag;
-
- /*
- * We provide a per-port pm hook.
- */
- void (*pm)(struct uart_port *port,
- unsigned int state, unsigned int old);
-};
-
-struct irq_info {
- spinlock_t lock;
- struct list_head *head;
-};
-
-static struct irq_info irq_lists[NR_IRQS];
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[] = {
- [PORT_UNKNOWN] = {
- .name = "unknown",
- .dfl_xmit_fifo_size = 1,
- .flags = 0,
- },
- [PORT_INDEX(PORT_M32R_SIO)] = {
- .name = "M32RSIO",
- .dfl_xmit_fifo_size = 1,
- .flags = 0,
- },
-};
-
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
-
-#define __sio_in(x) inw((unsigned long)(x))
-#define __sio_out(v,x) outw((v),(unsigned long)(x))
-
-static inline void sio_set_baud_rate(unsigned long baud)
-{
- unsigned short sbaud;
- sbaud = (boot_cpu_data.bus_clock / (baud * 4))-1;
- __sio_out(sbaud, PLD_ESIO0BAUR);
-}
-
-static void sio_reset(void)
-{
- unsigned short tmp;
-
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0CR);
- sio_set_baud_rate(BAUD_RATE);
- __sio_out(0x0300, PLD_ESIO0CR);
- __sio_out(0x0003, PLD_ESIO0CR);
-}
-
-static void sio_init(void)
-{
- unsigned short tmp;
-
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0RXB);
- tmp = __sio_in(PLD_ESIO0CR);
- __sio_out(0x0300, PLD_ESIO0CR);
- __sio_out(0x0003, PLD_ESIO0CR);
-}
-
-static void sio_error(int *status)
-{
- printk("SIO0 error[%04x]\n", *status);
- do {
- sio_init();
- } while ((*status = __sio_in(PLD_ESIO0CR)) != 3);
-}
-
-#else /* not CONFIG_SERIAL_M32R_PLDSIO */
-
-#define __sio_in(x) inl(x)
-#define __sio_out(v,x) outl((v),(x))
-
-static inline void sio_set_baud_rate(unsigned long baud)
-{
- unsigned long i, j;
-
- i = boot_cpu_data.bus_clock / (baud * 16);
- j = (boot_cpu_data.bus_clock - (i * baud * 16)) / baud;
- i -= 1;
- j = (j + 1) >> 1;
-
- __sio_out(i, M32R_SIO0_BAUR_PORTL);
- __sio_out(j, M32R_SIO0_RBAUR_PORTL);
-}
-
-static void sio_reset(void)
-{
- __sio_out(0x00000300, M32R_SIO0_CR_PORTL); /* init status */
- __sio_out(0x00000800, M32R_SIO0_MOD1_PORTL); /* 8bit */
- __sio_out(0x00000080, M32R_SIO0_MOD0_PORTL); /* 1stop non */
- sio_set_baud_rate(BAUD_RATE);
- __sio_out(0x00000000, M32R_SIO0_TRCR_PORTL);
- __sio_out(0x00000003, M32R_SIO0_CR_PORTL); /* RXCEN */
-}
-
-static void sio_init(void)
-{
- unsigned int tmp;
-
- tmp = __sio_in(M32R_SIO0_RXB_PORTL);
- tmp = __sio_in(M32R_SIO0_RXB_PORTL);
- tmp = __sio_in(M32R_SIO0_STS_PORTL);
- __sio_out(0x00000003, M32R_SIO0_CR_PORTL);
-}
-
-static void sio_error(int *status)
-{
- printk("SIO0 error[%04x]\n", *status);
- do {
- sio_init();
- } while ((*status = __sio_in(M32R_SIO0_CR_PORTL)) != 3);
-}
-
-#endif /* CONFIG_SERIAL_M32R_PLDSIO */
-
-static unsigned int sio_in(struct uart_sio_port *up, int offset)
-{
- return __sio_in(up->port.iobase + offset);
-}
-
-static void sio_out(struct uart_sio_port *up, int offset, int value)
-{
- __sio_out(value, up->port.iobase + offset);
-}
-
-static unsigned int serial_in(struct uart_sio_port *up, int offset)
-{
- if (!offset)
- return 0;
-
- return __sio_in(offset);
-}
-
-static void serial_out(struct uart_sio_port *up, int offset, int value)
-{
- if (!offset)
- return;
-
- __sio_out(value, offset);
-}
-
-static void m32r_sio_stop_tx(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void m32r_sio_start_tx(struct uart_port *port)
-{
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- struct circ_buf *xmit = &up->port.state->xmit;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- }
- while((serial_in(up, UART_LSR) & UART_EMPTY) != UART_EMPTY);
-#else
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-#endif
-}
-
-static void m32r_sio_stop_rx(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void m32r_sio_enable_ms(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void receive_chars(struct uart_sio_port *up, int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch;
- unsigned char flag;
- int max_count = 256;
-
- do {
- ch = sio_in(up, SIORXB);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
- /*
- * For statistics only
- */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ingored.
- */
- *status &= up->port.read_status_mask;
-
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-
- if (*status & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
-
- if (*status & UART_LSR_OE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
- ignore_char:
- *status = serial_in(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && (max_count-- > 0));
- tty_flip_buffer_push(tty);
-}
-
-static void transmit_chars(struct uart_sio_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- int count;
-
- if (up->port.x_char) {
-#ifndef CONFIG_SERIAL_M32R_PLDSIO /* XXX */
- serial_out(up, UART_TX, up->port.x_char);
-#endif
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- m32r_sio_stop_tx(&up->port);
- return;
- }
-
- count = up->port.fifosize;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- while (!(serial_in(up, UART_LSR) & UART_LSR_THRE));
-
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- DEBUG_INTR("THRE...");
-
- if (uart_circ_empty(xmit))
- m32r_sio_stop_tx(&up->port);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline void m32r_sio_handle_port(struct uart_sio_port *up,
- unsigned int status)
-{
- DEBUG_INTR("status = %x...", status);
-
- if (status & 0x04)
- receive_chars(up, &status);
- if (status & 0x01)
- transmit_chars(up);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts. (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id)
-{
- struct irq_info *i = dev_id;
- struct list_head *l, *end = NULL;
- int pass_counter = 0;
-
- DEBUG_INTR("m32r_sio_interrupt(%d)...", irq);
-
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
-// if (irq == PLD_IRQ_SIO0_SND)
-// irq = PLD_IRQ_SIO0_RCV;
-#else
- if (irq == M32R_IRQ_SIO0_S)
- irq = M32R_IRQ_SIO0_R;
-#endif
-
- spin_lock(&i->lock);
-
- l = i->head;
- do {
- struct uart_sio_port *up;
- unsigned int sts;
-
- up = list_entry(l, struct uart_sio_port, list);
-
- sts = sio_in(up, SIOSTS);
- if (sts & 0x5) {
- spin_lock(&up->port.lock);
- m32r_sio_handle_port(up, sts);
- spin_unlock(&up->port.lock);
-
- end = NULL;
- } else if (end == NULL)
- end = l;
-
- l = l->next;
-
- if (l == i->head && pass_counter++ > PASS_LIMIT) {
- if (sts & 0xe0)
- sio_error(&sts);
- break;
- }
- } while (l != end);
-
- spin_unlock(&i->lock);
-
- DEBUG_INTR("end.\n");
-
- return IRQ_HANDLED;
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning. Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up)
-{
- spin_lock_irq(&i->lock);
-
- if (!list_empty(i->head)) {
- if (i->head == &up->list)
- i->head = i->head->next;
- list_del(&up->list);
- } else {
- BUG_ON(i->head != &up->list);
- i->head = NULL;
- }
-
- spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct uart_sio_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = 0;
-
- spin_lock_irq(&i->lock);
-
- if (i->head) {
- list_add(&up->list, i->head);
- spin_unlock_irq(&i->lock);
-
- ret = 0;
- } else {
- INIT_LIST_HEAD(&up->list);
- i->head = &up->list;
- spin_unlock_irq(&i->lock);
-
- ret = request_irq(up->port.irq, m32r_sio_interrupt,
- irq_flags, "SIO0-RX", i);
- ret |= request_irq(up->port.irq + 1, m32r_sio_interrupt,
- irq_flags, "SIO0-TX", i);
- if (ret < 0)
- serial_do_unlink(i, up);
- }
-
- return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_sio_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
-
- BUG_ON(i->head == NULL);
-
- if (list_empty(i->head)) {
- free_irq(up->port.irq, i);
- free_irq(up->port.irq + 1, i);
- }
-
- serial_do_unlink(i, up);
-}
-
-/*
- * This function is used to handle ports that do not have an interrupt.
- */
-static void m32r_sio_timeout(unsigned long data)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)data;
- unsigned int timeout;
- unsigned int sts;
-
- sts = sio_in(up, SIOSTS);
- if (sts & 0x5) {
- spin_lock(&up->port.lock);
- m32r_sio_handle_port(up, sts);
- spin_unlock(&up->port.lock);
- }
-
- timeout = up->port.timeout;
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
- mod_timer(&up->timer, jiffies + timeout);
-}
-
-static unsigned int m32r_sio_tx_empty(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int m32r_sio_get_mctrl(struct uart_port *port)
-{
- return 0;
-}
-
-static void m32r_sio_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-
-}
-
-static void m32r_sio_break_ctl(struct uart_port *port, int break_state)
-{
-
-}
-
-static int m32r_sio_startup(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- int retval;
-
- sio_init();
-
- /*
- * If the "interrupt" for this port doesn't correspond with any
- * hardware interrupt, we use a timer-based system. The original
- * driver used to do this with IRQ0.
- */
- if (!is_real_interrupt(up->port.irq)) {
- unsigned int timeout = up->port.timeout;
-
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies + timeout);
- } else {
- retval = serial_link_irq_chain(up);
- if (retval)
- return retval;
- }
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- * - M32R_SIO: 0x0c
- * - M32R_PLDSIO: 0x04
- */
- up->ier = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
- sio_out(up, SIOTRCR, up->ier);
-
- /*
- * And clear the interrupt registers again for luck.
- */
- sio_reset();
-
- return 0;
-}
-
-static void m32r_sio_shutdown(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- sio_out(up, SIOTRCR, 0);
-
- /*
- * Disable break condition and FIFOs
- */
-
- sio_init();
-
- if (!is_real_interrupt(up->port.irq))
- del_timer_sync(&up->timer);
- else
- serial_unlink_irq_chain(up);
-}
-
-static unsigned int m32r_sio_get_divisor(struct uart_port *port,
- unsigned int baud)
-{
- return uart_get_divisor(port, baud);
-}
-
-static void m32r_sio_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned char cval = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Ask the core to calculate the divisor for us.
- */
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
-#else
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-#endif
- quot = m32r_sio_get_divisor(port, baud);
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- sio_set_baud_rate(baud);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
-
- up->lcr = cval; /* Save LCR */
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void m32r_sio_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- if (up->pm)
- up->pm(port, state, oldstate);
-}
-
-/*
- * Resource handling. This is complicated by the fact that resources
- * depend on the port type. Maybe we should be claiming the standard
- * 8250 ports, and then trying to get other resources as necessary?
- */
-static int
-m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res)
-{
- unsigned int size = 8 << up->port.regshift;
-#ifndef CONFIG_SERIAL_M32R_PLDSIO
- unsigned long start;
-#endif
- int ret = 0;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- *res = request_mem_region(up->port.mapbase, size, "serial");
-#else
- start = up->port.mapbase;
- *res = request_mem_region(start, size, "serial");
-#endif
- if (!*res)
- ret = -EBUSY;
- }
- break;
-
- case UPIO_PORT:
- *res = request_region(up->port.iobase, size, "serial");
- if (!*res)
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-static void m32r_sio_release_port(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned long start, offset = 0, size = 0;
-
- size <<= up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
- /*
- * Unmap the area.
- */
- iounmap(up->port.membase);
- up->port.membase = NULL;
-
- start = up->port.mapbase;
-
- if (size)
- release_mem_region(start + offset, size);
- release_mem_region(start, 8 << up->port.regshift);
- }
- break;
-
- case UPIO_PORT:
- start = up->port.iobase;
-
- if (size)
- release_region(start + offset, size);
- release_region(start + offset, 8 << up->port.regshift);
- break;
-
- default:
- break;
- }
-}
-
-static int m32r_sio_request_port(struct uart_port *port)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- struct resource *res = NULL;
- int ret = 0;
-
- ret = m32r_sio_request_std_resource(up, &res);
-
- /*
- * If we have a mapbase, then request that as well.
- */
- if (ret == 0 && up->port.flags & UPF_IOREMAP) {
- int size = resource_size(res);
-
- up->port.membase = ioremap(up->port.mapbase, size);
- if (!up->port.membase)
- ret = -ENOMEM;
- }
-
- if (ret < 0) {
- if (res)
- release_resource(res);
- }
-
- return ret;
-}
-
-static void m32r_sio_config_port(struct uart_port *port, int unused)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
-
- up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
- up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int
-m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type >= ARRAY_SIZE(uart_config))
- return -EINVAL;
- return 0;
-}
-
-static const char *
-m32r_sio_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops m32r_sio_pops = {
- .tx_empty = m32r_sio_tx_empty,
- .set_mctrl = m32r_sio_set_mctrl,
- .get_mctrl = m32r_sio_get_mctrl,
- .stop_tx = m32r_sio_stop_tx,
- .start_tx = m32r_sio_start_tx,
- .stop_rx = m32r_sio_stop_rx,
- .enable_ms = m32r_sio_enable_ms,
- .break_ctl = m32r_sio_break_ctl,
- .startup = m32r_sio_startup,
- .shutdown = m32r_sio_shutdown,
- .set_termios = m32r_sio_set_termios,
- .pm = m32r_sio_pm,
- .type = m32r_sio_type,
- .release_port = m32r_sio_release_port,
- .request_port = m32r_sio_request_port,
- .config_port = m32r_sio_config_port,
- .verify_port = m32r_sio_verify_port,
-};
-
-static struct uart_sio_port m32r_sio_ports[UART_NR];
-
-static void __init m32r_sio_init_ports(void)
-{
- struct uart_sio_port *up;
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0, up = m32r_sio_ports; i < ARRAY_SIZE(old_serial_port);
- i++, up++) {
- up->port.iobase = old_serial_port[i].port;
- up->port.irq = irq_canonicalize(old_serial_port[i].irq);
- up->port.uartclk = old_serial_port[i].baud_base * 16;
- up->port.flags = old_serial_port[i].flags;
- up->port.membase = old_serial_port[i].iomem_base;
- up->port.iotype = old_serial_port[i].io_type;
- up->port.regshift = old_serial_port[i].iomem_reg_shift;
- up->port.ops = &m32r_sio_pops;
- }
-}
-
-static void __init m32r_sio_register_ports(struct uart_driver *drv)
-{
- int i;
-
- m32r_sio_init_ports();
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_sio_port *up = &m32r_sio_ports[i];
-
- up->port.line = i;
- up->port.ops = &m32r_sio_pops;
- init_timer(&up->timer);
- up->timer.function = m32r_sio_timeout;
-
- up->mcr_mask = ~0;
- up->mcr_force = 0;
-
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_M32R_SIO_CONSOLE
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_sio_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = sio_in(up, SIOSTS);
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & UART_EMPTY) != UART_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout)
- udelay(1);
- }
-}
-
-static void m32r_sio_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_sio_port *up = (struct uart_sio_port *)port;
-
- wait_for_xmitr(up);
- sio_out(up, SIOTXB, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void m32r_sio_console_write(struct console *co, const char *s,
- unsigned int count)
-{
- struct uart_sio_port *up = &m32r_sio_ports[co->index];
- unsigned int ier;
-
- /*
- * First save the UER then disable the interrupts
- */
- ier = sio_in(up, SIOTRCR);
- sio_out(up, SIOTRCR, 0);
-
- uart_console_write(&up->port, s, count, m32r_sio_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- sio_out(up, SIOTRCR, ier);
-}
-
-static int __init m32r_sio_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- port = &m32r_sio_ports[co->index].port;
-
- /*
- * Temporary fix.
- */
- spin_lock_init(&port->lock);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver m32r_sio_reg;
-static struct console m32r_sio_console = {
- .name = "ttyS",
- .write = m32r_sio_console_write,
- .device = uart_console_device,
- .setup = m32r_sio_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &m32r_sio_reg,
-};
-
-static int __init m32r_sio_console_init(void)
-{
- sio_reset();
- sio_init();
- m32r_sio_init_ports();
- register_console(&m32r_sio_console);
- return 0;
-}
-console_initcall(m32r_sio_console_init);
-
-#define M32R_SIO_CONSOLE &m32r_sio_console
-#else
-#define M32R_SIO_CONSOLE NULL
-#endif
-
-static struct uart_driver m32r_sio_reg = {
- .owner = THIS_MODULE,
- .driver_name = "sio",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = UART_NR,
- .cons = M32R_SIO_CONSOLE,
-};
-
-/**
- * m32r_sio_suspend_port - suspend one serial port
- * @line: serial line number
- *
- * Suspend one serial port.
- */
-void m32r_sio_suspend_port(int line)
-{
- uart_suspend_port(&m32r_sio_reg, &m32r_sio_ports[line].port);
-}
-
-/**
- * m32r_sio_resume_port - resume one serial port
- * @line: serial line number
- *
- * Resume one serial port.
- */
-void m32r_sio_resume_port(int line)
-{
- uart_resume_port(&m32r_sio_reg, &m32r_sio_ports[line].port);
-}
-
-static int __init m32r_sio_init(void)
-{
- int ret, i;
-
- printk(KERN_INFO "Serial: M32R SIO driver\n");
-
- for (i = 0; i < nr_irqs; i++)
- spin_lock_init(&irq_lists[i].lock);
-
- ret = uart_register_driver(&m32r_sio_reg);
- if (ret >= 0)
- m32r_sio_register_ports(&m32r_sio_reg);
-
- return ret;
-}
-
-static void __exit m32r_sio_exit(void)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++)
- uart_remove_one_port(&m32r_sio_reg, &m32r_sio_ports[i].port);
-
- uart_unregister_driver(&m32r_sio_reg);
-}
-
-module_init(m32r_sio_init);
-module_exit(m32r_sio_exit);
-
-EXPORT_SYMBOL(m32r_sio_suspend_port);
-EXPORT_SYMBOL(m32r_sio_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic M32R SIO serial driver");
+++ /dev/null
-/*
- * m32r_sio.h
- *
- * Driver for M32R serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- * Based on drivers/serial/8250.h.
- *
- * Copyright (C) 2001 Russell King.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
- *
- * 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.
- */
-
-
-struct m32r_sio_probe {
- struct module *owner;
- int (*pci_init_one)(struct pci_dev *dev);
- void (*pci_remove_one)(struct pci_dev *dev);
- void (*pnp_init)(void);
-};
-
-int m32r_sio_register_probe(struct m32r_sio_probe *probe);
-void m32r_sio_unregister_probe(struct m32r_sio_probe *probe);
-void m32r_sio_get_irq_map(unsigned int *map);
-void m32r_sio_suspend_port(int line);
-void m32r_sio_resume_port(int line);
-
-struct old_serial_port {
- unsigned int uart;
- unsigned int baud_base;
- unsigned int port;
- unsigned int irq;
- unsigned int flags;
- unsigned char io_type;
- unsigned char __iomem *iomem_base;
- unsigned short iomem_reg_shift;
-};
-
-#define _INLINE_ inline
-
-#define PROBE_RSA (1 << 0)
-#define PROBE_ANY (~0)
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+++ /dev/null
-/*
- * m32r_sio_reg.h
- *
- * Copyright (C) 1992, 1994 by Theodore Ts'o.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
- *
- * Redistribution of this file is permitted under the terms of the GNU
- * Public License (GPL)
- *
- * These are the UART port assignments, expressed as offsets from the base
- * register. These assignments should hold for any serial port based on
- * a 8250, 16450, or 16550(A).
- */
-
-#ifndef _M32R_SIO_REG_H
-#define _M32R_SIO_REG_H
-
-
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
-
-#define SIOCR 0x000
-#define SIOMOD0 0x002
-#define SIOMOD1 0x004
-#define SIOSTS 0x006
-#define SIOTRCR 0x008
-#define SIOBAUR 0x00a
-// #define SIORBAUR 0x018
-#define SIOTXB 0x00c
-#define SIORXB 0x00e
-
-#define UART_RX ((unsigned long) PLD_ESIO0RXB)
- /* In: Receive buffer (DLAB=0) */
-#define UART_TX ((unsigned long) PLD_ESIO0TXB)
- /* Out: Transmit buffer (DLAB=0) */
-#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
-#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
- * In: Fifo count
- * Out: Fifo custom trigger levels
- * XR16C85x only */
-
-#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
-#define UART_IER ((unsigned long) PLD_ESIO0INTCR)
- /* Out: Interrupt Enable Register */
-#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
- * XR16C85x only */
-
-#define UART_IIR 0 /* In: Interrupt ID Register */
-#define UART_FCR 0 /* Out: FIFO Control Register */
-#define UART_EFR 0 /* I/O: Extended Features Register */
- /* (DLAB=1, 16C660 only) */
-
-#define UART_LCR 0 /* Out: Line Control Register */
-#define UART_MCR 0 /* Out: Modem Control Register */
-#define UART_LSR ((unsigned long) PLD_ESIO0STS)
- /* In: Line Status Register */
-#define UART_MSR 0 /* In: Modem Status Register */
-#define UART_SCR 0 /* I/O: Scratch Register */
-#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
- * FCTR bit 6 selects SCR or EMSR
- * XR16c85x only */
-
-#else /* not CONFIG_SERIAL_M32R_PLDSIO */
-
-#define SIOCR 0x000
-#define SIOMOD0 0x004
-#define SIOMOD1 0x008
-#define SIOSTS 0x00c
-#define SIOTRCR 0x010
-#define SIOBAUR 0x014
-#define SIORBAUR 0x018
-#define SIOTXB 0x01c
-#define SIORXB 0x020
-
-#define UART_RX M32R_SIO0_RXB_PORTL /* In: Receive buffer (DLAB=0) */
-#define UART_TX M32R_SIO0_TXB_PORTL /* Out: Transmit buffer (DLAB=0) */
-#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
-#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
- * In: Fifo count
- * Out: Fifo custom trigger levels
- * XR16C85x only */
-
-#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
-#define UART_IER M32R_SIO0_TRCR_PORTL /* Out: Interrupt Enable Register */
-#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
- * XR16C85x only */
-
-#define UART_IIR 0 /* In: Interrupt ID Register */
-#define UART_FCR 0 /* Out: FIFO Control Register */
-#define UART_EFR 0 /* I/O: Extended Features Register */
- /* (DLAB=1, 16C660 only) */
-
-#define UART_LCR 0 /* Out: Line Control Register */
-#define UART_MCR 0 /* Out: Modem Control Register */
-#define UART_LSR M32R_SIO0_STS_PORTL /* In: Line Status Register */
-#define UART_MSR 0 /* In: Modem Status Register */
-#define UART_SCR 0 /* I/O: Scratch Register */
-#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
- * FCTR bit 6 selects SCR or EMSR
- * XR16c85x only */
-
-#endif /* CONFIG_SERIAL_M32R_PLDSIO */
-
-#define UART_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * These are the definitions for the Line Control Register
- *
- * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
- * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
- */
-#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
-#define UART_LCR_SBC 0x40 /* Set break control */
-#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
-#define UART_LCR_EPAR 0x10 /* Even parity select */
-#define UART_LCR_PARITY 0x08 /* Parity Enable */
-#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
-#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
-#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
-#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
-#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
-
-/*
- * These are the definitions for the Line Status Register
- */
-#define UART_LSR_TEMT 0x02 /* Transmitter empty */
-#define UART_LSR_THRE 0x01 /* Transmit-hold-register empty */
-#define UART_LSR_BI 0x00 /* Break interrupt indicator */
-#define UART_LSR_FE 0x80 /* Frame error indicator */
-#define UART_LSR_PE 0x40 /* Parity error indicator */
-#define UART_LSR_OE 0x20 /* Overrun error indicator */
-#define UART_LSR_DR 0x04 /* Receiver data ready */
-
-/*
- * These are the definitions for the Interrupt Identification Register
- */
-#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
-#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
-
-#define UART_IIR_MSI 0x00 /* Modem status interrupt */
-#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
-#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
-#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
-
-/*
- * These are the definitions for the Interrupt Enable Register
- */
-#define UART_IER_MSI 0x00 /* Enable Modem status interrupt */
-#define UART_IER_RLSI 0x08 /* Enable receiver line status interrupt */
-#define UART_IER_THRI 0x03 /* Enable Transmitter holding register int. */
-#define UART_IER_RDI 0x04 /* Enable receiver data interrupt */
-
-#endif /* _M32R_SIO_REG_H */
+++ /dev/null
-/*
- * max3107.c - spi uart protocol driver for Maxim 3107
- * Based on max3100.c
- * by Christian Pellegrin <chripell@evolware.org>
- * and max3110.c
- * by Feng Tang <feng.tang@intel.com>
- *
- * Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/sfi.h>
-#include <linux/module.h>
-#include <asm/mrst.h>
-#include "max3107.h"
-
-/* GPIO direction to input function */
-static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration register */
- buf[0] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to input */
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO direction to output function */
-static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration and data registers */
- buf[0] = MAX3107_GPIOCFG_REG;
- buf[1] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to output */
- buf[0] |= (0x0001 << offset);
- /* Set value */
- if (value)
- buf[1] |= (0x0001 << offset);
- else
- buf[1] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration and data register values */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO conf data w failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO value query function */
-static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO data register */
- buf[0] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Return value */
- return buf[0] & (0x0001 << offset);
-}
-
-/* GPIO value set function */
-static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return;
- }
-
- /* Read current GPIO configuration registers*/
- buf[0] = MAX3107_GPIODATA_REG;
- buf[1] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO data and config read failed\n");
- return;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- if (!(buf[1] & (0x0001 << offset))) {
- /* Configured as input, can't set value */
- dev_warn(&s->spi->dev,
- "Trying to set value for input GPIO\n");
- return;
- }
-
- /* Set value */
- if (value)
- buf[0] |= (0x0001 << offset);
- else
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO data register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
-}
-
-/* GPIO chip data */
-static struct gpio_chip max3107_gpio_chip = {
- .owner = THIS_MODULE,
- .direction_input = max3107_gpio_direction_in,
- .direction_output = max3107_gpio_direction_out,
- .get = max3107_gpio_get,
- .set = max3107_gpio_set,
- .can_sleep = 1,
- .base = MAX3107_GPIO_BASE,
- .ngpio = MAX3107_GPIO_COUNT,
-};
-
-/**
- * max3107_aava_reset - reset on AAVA systems
- * @spi: The SPI device we are probing
- *
- * Reset the device ready for probing.
- */
-
-static int max3107_aava_reset(struct spi_device *spi)
-{
- /* Reset the chip */
- if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
- pr_err("Requesting RESET GPIO failed\n");
- return -EIO;
- }
- if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
- pr_err("Setting RESET GPIO to 0 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- msleep(MAX3107_RESET_DELAY);
- if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
- pr_err("Setting RESET GPIO to 1 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- gpio_free(MAX3107_RESET_GPIO);
- msleep(MAX3107_WAKEUP_DELAY);
- return 0;
-}
-
-static int max3107_aava_configure(struct max3107_port *s)
-{
- int retval;
-
- /* Initialize GPIO chip data */
- s->chip = max3107_gpio_chip;
- s->chip.label = s->spi->modalias;
- s->chip.dev = &s->spi->dev;
-
- /* Add GPIO chip */
- retval = gpiochip_add(&s->chip);
- if (retval) {
- dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
- return retval;
- }
-
- /* Temporary fix for EV2 boot problems, set modem reset to 0 */
- max3107_gpio_direction_out(&s->chip, 3, 0);
- return 0;
-}
-
-#if 0
-/* This will get enabled once we have the board stuff merged for this
- specific case */
-
-static const struct baud_table brg13_ext[] = {
- { 300, MAX3107_BRG13_B300 },
- { 600, MAX3107_BRG13_B600 },
- { 1200, MAX3107_BRG13_B1200 },
- { 2400, MAX3107_BRG13_B2400 },
- { 4800, MAX3107_BRG13_B4800 },
- { 9600, MAX3107_BRG13_B9600 },
- { 19200, MAX3107_BRG13_B19200 },
- { 57600, MAX3107_BRG13_B57600 },
- { 115200, MAX3107_BRG13_B115200 },
- { 230400, MAX3107_BRG13_B230400 },
- { 460800, MAX3107_BRG13_B460800 },
- { 921600, MAX3107_BRG13_B921600 },
- { 0, 0 }
-};
-
-static void max3107_aava_init(struct max3107_port *s)
-{
- /*override for AAVA SC specific*/
- if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
- if (get_koski_build_id() <= KOSKI_EV2)
- if (s->ext_clk) {
- s->brg_cfg = MAX3107_BRG13_B9600;
- s->baud_tbl = (struct baud_table *)brg13_ext;
- }
- }
-}
-#endif
-
-static int __devexit max3107_aava_remove(struct spi_device *spi)
-{
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- /* Remove GPIO chip */
- if (gpiochip_remove(&s->chip))
- dev_warn(&spi->dev, "Removing GPIO chip failed\n");
-
- /* Then do the default remove */
- return max3107_remove(spi);
-}
-
-/* Platform data */
-static struct max3107_plat aava_plat_data = {
- .loopback = 0,
- .ext_clk = 1,
-/* .init = max3107_aava_init, */
- .configure = max3107_aava_configure,
- .hw_suspend = max3107_hw_susp,
- .polled_mode = 0,
- .poll_time = 0,
-};
-
-
-static int __devinit max3107_probe_aava(struct spi_device *spi)
-{
- int err = max3107_aava_reset(spi);
- if (err < 0)
- return err;
- return max3107_probe(spi, &aava_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
- .driver = {
- .name = "aava-max3107",
- .owner = THIS_MODULE,
- },
- .probe = max3107_probe_aava,
- .remove = __devexit_p(max3107_aava_remove),
- .suspend = max3107_suspend,
- .resume = max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
- return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
- spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("spi:aava-max3107");
-MODULE_LICENSE("GPL v2");
.cons = OMAP_CONSOLE,
};
-#ifdef CONFIG_SUSPEND
+#ifdef CONFIG_PM_SLEEP
static int serial_omap_suspend(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
}
}
+#ifdef CONFIG_PM_RUNTIME
static void serial_omap_restore_context(struct uart_omap_port *up)
{
if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
serial_out(up, UART_OMAP_MDR1, up->mdr1);
}
-#ifdef CONFIG_PM_RUNTIME
static int serial_omap_runtime_suspend(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
*/
tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
if (likely(!IS_ERR(tty_dev))) {
- device_init_wakeup(tty_dev, 1);
- device_set_wakeup_enable(tty_dev, 0);
- } else
+ device_set_wakeup_capable(tty_dev, 1);
+ } else {
printk(KERN_ERR "Cannot register tty device on line %d\n",
uport->line);
+ }
/*
* Ensure UPF_DEAD is not set.
+++ /dev/null
-/*======================================================================
-
- A driver for PCMCIA serial devices
-
- serial_cs.c 1.134 2002/05/04 05:48:53
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include "8250.h"
-
-
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-/* Enable the speaker? */
-static int do_sound = 1;
-/* Skip strict UART tests? */
-static int buggy_uart;
-
-module_param(do_sound, int, 0444);
-module_param(buggy_uart, int, 0444);
-
-/*====================================================================*/
-
-/* Table of multi-port card ID's */
-
-struct serial_quirk {
- unsigned int manfid;
- unsigned int prodid;
- int multi; /* 1 = multifunction, > 1 = # ports */
- void (*config)(struct pcmcia_device *);
- void (*setup)(struct pcmcia_device *, struct uart_port *);
- void (*wakeup)(struct pcmcia_device *);
- int (*post)(struct pcmcia_device *);
-};
-
-struct serial_info {
- struct pcmcia_device *p_dev;
- int ndev;
- int multi;
- int slave;
- int manfid;
- int prodid;
- int c950ctrl;
- int line[4];
- const struct serial_quirk *quirk;
-};
-
-struct serial_cfg_mem {
- tuple_t tuple;
- cisparse_t parse;
- u_char buf[256];
-};
-
-/*
- * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6"
- * manfid 0x0160, 0x0104
- * This card appears to have a 14.7456MHz clock.
- */
-/* Generic Modem: MD55x (GPRS/EDGE) have
- * Elan VPU16551 UART with 14.7456MHz oscillator
- * manfid 0x015D, 0x4C45
- */
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
-{
- port->uartclk = 14745600;
-}
-
-static int quirk_post_ibm(struct pcmcia_device *link)
-{
- u8 val;
- int ret;
-
- ret = pcmcia_read_config_byte(link, 0x800, &val);
- if (ret)
- goto failed;
-
- ret = pcmcia_write_config_byte(link, 0x800, val | 1);
- if (ret)
- goto failed;
- return 0;
-
- failed:
- return -ENODEV;
-}
-
-/*
- * Nokia cards are not really multiport cards. Shouldn't this
- * be handled by setting the quirk entry .multi = 0 | 1 ?
- */
-static void quirk_config_nokia(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- if (info->multi > 1)
- info->multi = 1;
-}
-
-static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- if (info->c950ctrl)
- outb(12, info->c950ctrl + 1);
-}
-
-/* request_region? oxsemi branch does no request_region too... */
-/*
- * This sequence is needed to properly initialize MC45 attached to OXCF950.
- * I tried decreasing these msleep()s, but it worked properly (survived
- * 1000 stop/start operations) with these timeouts (or bigger).
- */
-static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- unsigned int ctrl = info->c950ctrl;
-
- outb(0xA, ctrl + 1);
- msleep(100);
- outb(0xE, ctrl + 1);
- msleep(300);
- outb(0xC, ctrl + 1);
- msleep(100);
- outb(0xE, ctrl + 1);
- msleep(200);
- outb(0xF, ctrl + 1);
- msleep(100);
- outb(0xE, ctrl + 1);
- msleep(100);
- outb(0xC, ctrl + 1);
-}
-
-/*
- * Socket Dual IO: this enables irq's for second port
- */
-static void quirk_config_socket(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- if (info->multi)
- link->config_flags |= CONF_ENABLE_ESR;
-}
-
-static const struct serial_quirk quirks[] = {
- {
- .manfid = 0x0160,
- .prodid = 0x0104,
- .multi = -1,
- .setup = quirk_setup_brainboxes_0104,
- }, {
- .manfid = 0x015D,
- .prodid = 0x4C45,
- .multi = -1,
- .setup = quirk_setup_brainboxes_0104,
- }, {
- .manfid = MANFID_IBM,
- .prodid = ~0,
- .multi = -1,
- .post = quirk_post_ibm,
- }, {
- .manfid = MANFID_INTEL,
- .prodid = PRODID_INTEL_DUAL_RS232,
- .multi = 2,
- }, {
- .manfid = MANFID_NATINST,
- .prodid = PRODID_NATINST_QUAD_RS232,
- .multi = 4,
- }, {
- .manfid = MANFID_NOKIA,
- .prodid = ~0,
- .multi = -1,
- .config = quirk_config_nokia,
- }, {
- .manfid = MANFID_OMEGA,
- .prodid = PRODID_OMEGA_QSP_100,
- .multi = 4,
- }, {
- .manfid = MANFID_OXSEMI,
- .prodid = ~0,
- .multi = -1,
- .wakeup = quirk_wakeup_oxsemi,
- }, {
- .manfid = MANFID_POSSIO,
- .prodid = PRODID_POSSIO_GCC,
- .multi = -1,
- .wakeup = quirk_wakeup_possio_gcc,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_DUAL_RS232,
- .multi = 2,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_DUAL_RS232_D1,
- .multi = 2,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_DUAL_RS232_G,
- .multi = 2,
- }, {
- .manfid = MANFID_QUATECH,
- .prodid = PRODID_QUATECH_QUAD_RS232,
- .multi = 4,
- }, {
- .manfid = MANFID_SOCKET,
- .prodid = PRODID_SOCKET_DUAL_RS232,
- .multi = 2,
- .config = quirk_config_socket,
- }, {
- .manfid = MANFID_SOCKET,
- .prodid = ~0,
- .multi = -1,
- .config = quirk_config_socket,
- }
-};
-
-
-static int serial_config(struct pcmcia_device * link);
-
-
-static void serial_remove(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- dev_dbg(&link->dev, "serial_release\n");
-
- /*
- * Recheck to see if the device is still configured.
- */
- for (i = 0; i < info->ndev; i++)
- serial8250_unregister_port(info->line[i]);
-
- if (!info->slave)
- pcmcia_disable_device(link);
-}
-
-static int serial_suspend(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- for (i = 0; i < info->ndev; i++)
- serial8250_suspend_port(info->line[i]);
-
- return 0;
-}
-
-static int serial_resume(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- for (i = 0; i < info->ndev; i++)
- serial8250_resume_port(info->line[i]);
-
- if (info->quirk && info->quirk->wakeup)
- info->quirk->wakeup(link);
-
- return 0;
-}
-
-static int serial_probe(struct pcmcia_device *link)
-{
- struct serial_info *info;
-
- dev_dbg(&link->dev, "serial_attach()\n");
-
- /* Create new serial device */
- info = kzalloc(sizeof (*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
- info->p_dev = link;
- link->priv = info;
-
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
- if (do_sound)
- link->config_flags |= CONF_ENABLE_SPKR;
-
- return serial_config(link);
-}
-
-static void serial_detach(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
-
- dev_dbg(&link->dev, "serial_detach\n");
-
- /*
- * Ensure that the ports have been released.
- */
- serial_remove(link);
-
- /* free bits */
- kfree(info);
-}
-
-/*====================================================================*/
-
-static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
- unsigned int iobase, int irq)
-{
- struct uart_port port;
- int line;
-
- memset(&port, 0, sizeof (struct uart_port));
- port.iobase = iobase;
- port.irq = irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &handle->dev;
- if (buggy_uart)
- port.flags |= UPF_BUGGY_UART;
-
- if (info->quirk && info->quirk->setup)
- info->quirk->setup(handle, &port);
-
- line = serial8250_register_port(&port);
- if (line < 0) {
- printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
- "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
- return -EINVAL;
- }
-
- info->line[info->ndev] = line;
- info->ndev++;
-
- return 0;
-}
-
-/*====================================================================*/
-
-static int pfc_config(struct pcmcia_device *p_dev)
-{
- unsigned int port = 0;
- struct serial_info *info = p_dev->priv;
-
- if ((p_dev->resource[1]->end != 0) &&
- (resource_size(p_dev->resource[1]) == 8)) {
- port = p_dev->resource[1]->start;
- info->slave = 1;
- } else if ((info->manfid == MANFID_OSITECH) &&
- (resource_size(p_dev->resource[0]) == 0x40)) {
- port = p_dev->resource[0]->start + 0x28;
- info->slave = 1;
- }
- if (info->slave)
- return setup_serial(p_dev, info, port, p_dev->irq);
-
- dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
- return -ENODEV;
-}
-
-static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
- static const int size_table[2] = { 8, 16 };
- int *try = priv_data;
-
- if (p_dev->resource[0]->start == 0)
- return -ENODEV;
-
- if ((*try & 0x1) == 0)
- p_dev->io_lines = 16;
-
- if (p_dev->resource[0]->end != size_table[(*try >> 1)])
- return -ENODEV;
-
- p_dev->resource[0]->end = 8;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
- return pcmcia_request_io(p_dev);
-}
-
-static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- int j;
-
- if (p_dev->io_lines > 3)
- return -ENODEV;
-
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[0]->end = 8;
-
- for (j = 0; j < 5; j++) {
- p_dev->resource[0]->start = base[j];
- p_dev->io_lines = base[j] ? 16 : 3;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
- return -ENODEV;
-}
-
-static int simple_config(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i = -ENODEV, try;
-
- /* First pass: look for a config entry that looks normal.
- * Two tries: without IO aliases, then with aliases */
- link->config_flags |= CONF_AUTO_SET_VPP;
- for (try = 0; try < 4; try++)
- if (!pcmcia_loop_config(link, simple_config_check, &try))
- goto found_port;
-
- /* Second pass: try to find an entry that isn't picky about
- its base address, then try to grab any standard serial port
- address, and finally try to get any free port. */
- if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
- goto found_port;
-
- dev_warn(&link->dev, "no usable port range found, giving up\n");
- return -1;
-
-found_port:
- if (info->multi && (info->manfid == MANFID_3COM))
- link->config_index &= ~(0x08);
-
- /*
- * Apply any configuration quirks.
- */
- if (info->quirk && info->quirk->config)
- info->quirk->config(link);
-
- i = pcmcia_enable_device(link);
- if (i != 0)
- return -1;
- return setup_serial(link, info, link->resource[0]->start, link->irq);
-}
-
-static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
- int *multi = priv_data;
-
- if (p_dev->resource[1]->end)
- return -EINVAL;
-
- /* The quad port cards have bad CIS's, so just look for a
- window larger than 8 ports and assume it will be right */
- if (p_dev->resource[0]->end <= 8)
- return -EINVAL;
-
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[0]->end = *multi * 8;
-
- if (pcmcia_request_io(p_dev))
- return -ENODEV;
- return 0;
-}
-
-static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- int *base2 = priv_data;
-
- if (!p_dev->resource[0]->end || !p_dev->resource[1]->end ||
- p_dev->resource[0]->start + 8 != p_dev->resource[1]->start)
- return -ENODEV;
-
- p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
- if (pcmcia_request_io(p_dev))
- return -ENODEV;
-
- *base2 = p_dev->resource[0]->start + 8;
- return 0;
-}
-
-static int multi_config(struct pcmcia_device *link)
-{
- struct serial_info *info = link->priv;
- int i, base2 = 0;
-
- /* First, look for a generic full-sized window */
- if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
- base2 = link->resource[0]->start + 8;
- else {
- /* If that didn't work, look for two windows */
- info->multi = 2;
- if (pcmcia_loop_config(link, multi_config_check_notpicky,
- &base2)) {
- dev_warn(&link->dev, "no usable port range "
- "found, giving up\n");
- return -ENODEV;
- }
- }
-
- if (!link->irq)
- dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
-
- /*
- * Apply any configuration quirks.
- */
- if (info->quirk && info->quirk->config)
- info->quirk->config(link);
-
- i = pcmcia_enable_device(link);
- if (i != 0)
- return -ENODEV;
-
- /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
- * 8 registers are for the UART, the others are extra registers.
- * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
- */
- if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
- info->prodid == PRODID_POSSIO_GCC)) {
- int err;
-
- if (link->config_index == 1 ||
- link->config_index == 3) {
- err = setup_serial(link, info, base2,
- link->irq);
- base2 = link->resource[0]->start;
- } else {
- err = setup_serial(link, info, link->resource[0]->start,
- link->irq);
- }
- info->c950ctrl = base2;
-
- /*
- * FIXME: We really should wake up the port prior to
- * handing it over to the serial layer.
- */
- if (info->quirk && info->quirk->wakeup)
- info->quirk->wakeup(link);
-
- return 0;
- }
-
- setup_serial(link, info, link->resource[0]->start, link->irq);
- for (i = 0; i < info->multi - 1; i++)
- setup_serial(link, info, base2 + (8 * i),
- link->irq);
- return 0;
-}
-
-static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data)
-{
- struct serial_info *info = p_dev->priv;
-
- if (!p_dev->resource[0]->end)
- return -EINVAL;
-
- if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
- info->multi = p_dev->resource[0]->end >> 3;
-
- if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
- && (p_dev->resource[1]->end == 8))
- info->multi = 2;
-
- return 0; /* break */
-}
-
-
-static int serial_config(struct pcmcia_device * link)
-{
- struct serial_info *info = link->priv;
- int i;
-
- dev_dbg(&link->dev, "serial_config\n");
-
- /* Is this a compliant multifunction card? */
- info->multi = (link->socket->functions > 1);
-
- /* Is this a multiport card? */
- info->manfid = link->manf_id;
- info->prodid = link->card_id;
-
- for (i = 0; i < ARRAY_SIZE(quirks); i++)
- if ((quirks[i].manfid == ~0 ||
- quirks[i].manfid == info->manfid) &&
- (quirks[i].prodid == ~0 ||
- quirks[i].prodid == info->prodid)) {
- info->quirk = &quirks[i];
- break;
- }
-
- /* Another check for dual-serial cards: look for either serial or
- multifunction cards that ask for appropriate IO port ranges */
- if ((info->multi == 0) &&
- (link->has_func_id) &&
- (link->socket->pcmcia_pfc == 0) &&
- ((link->func_id == CISTPL_FUNCID_MULTI) ||
- (link->func_id == CISTPL_FUNCID_SERIAL)))
- pcmcia_loop_config(link, serial_check_for_multi, info);
-
- /*
- * Apply any multi-port quirk.
- */
- if (info->quirk && info->quirk->multi != -1)
- info->multi = info->quirk->multi;
-
- dev_info(&link->dev,
- "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
- link->manf_id, link->card_id,
- link->socket->pcmcia_pfc, info->multi, info->quirk);
- if (link->socket->pcmcia_pfc)
- i = pfc_config(link);
- else if (info->multi > 1)
- i = multi_config(link);
- else
- i = simple_config(link);
-
- if (i || info->ndev == 0)
- goto failed;
-
- /*
- * Apply any post-init quirk. FIXME: This should really happen
- * before we register the port, since it might already be in use.
- */
- if (info->quirk && info->quirk->post)
- if (info->quirk->post(link))
- goto failed;
-
- return 0;
-
-failed:
- dev_warn(&link->dev, "failed to initialize\n");
- serial_remove(link);
- return -ENODEV;
-}
-
-static const struct pcmcia_device_id serial_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
- PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
- PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
- PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0b05),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
- PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
- PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
- PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
- PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
- PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
- PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
- PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
- PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
- PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
- PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
- PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
- PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
- PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
- PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
- PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
- PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
- PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
- PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
- PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
- PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
- PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
- PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
- PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
- PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
- PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
- PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
- PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
- PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
- PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
- PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
- PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
- PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
- PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
- PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
- PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
- PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
- PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
- PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
- PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
- PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
- PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
- PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
- PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
- PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
- PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
- PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC860", 0xd85f6206, 0x698f93db, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC860 3G Network Adapter R1 */
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
- PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3),
- PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676),
- PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
- PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
- PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
- /* too generic */
- /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
- /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
- PCMCIA_DEVICE_FUNC_ID(2),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, serial_ids);
-
-MODULE_FIRMWARE("cis/PCMLM28.cis");
-MODULE_FIRMWARE("cis/DP83903.cis");
-MODULE_FIRMWARE("cis/3CCFEM556.cis");
-MODULE_FIRMWARE("cis/3CXEM556.cis");
-MODULE_FIRMWARE("cis/SW_8xx_SER.cis");
-MODULE_FIRMWARE("cis/SW_7xx_SER.cis");
-MODULE_FIRMWARE("cis/SW_555_SER.cis");
-MODULE_FIRMWARE("cis/MT5634ZLX.cis");
-MODULE_FIRMWARE("cis/COMpad2.cis");
-MODULE_FIRMWARE("cis/COMpad4.cis");
-MODULE_FIRMWARE("cis/RS-COM-2P.cis");
-
-static struct pcmcia_driver serial_cs_driver = {
- .owner = THIS_MODULE,
- .name = "serial_cs",
- .probe = serial_probe,
- .remove = serial_detach,
- .id_table = serial_ids,
- .suspend = serial_suspend,
- .resume = serial_resume,
-};
-
-static int __init init_serial_cs(void)
-{
- return pcmcia_register_driver(&serial_cs_driver);
-}
-
-static void __exit exit_serial_cs(void)
-{
- pcmcia_unregister_driver(&serial_cs_driver);
-}
-
-module_init(init_serial_cs);
-module_exit(exit_serial_cs);
-
-MODULE_LICENSE("GPL");
int do_clocal = 0, retval;
unsigned long flags;
DEFINE_WAIT(wait);
- int cd;
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
retval = -ERESTARTSYS;
break;
}
- /* Probe the carrier. For devices with no carrier detect this
- will always return true */
- cd = tty_port_carrier_raised(port);
+ /*
+ * Probe the carrier. For devices with no carrier detect
+ * tty_port_carrier_raised will always return true.
+ * Never ask drivers if CLOCAL is set, this causes troubles
+ * on some hardware.
+ */
if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || cd))
+ (do_clocal || tty_port_carrier_raised(port)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
#define WDM_MAX 16
+/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
+#define WDM_DEFAULT_BUFSIZE 256
static DEFINE_MUTEX(wdm_mutex);
int count;
dma_addr_t shandle;
dma_addr_t ihandle;
- struct mutex lock;
+ struct mutex wlock;
+ struct mutex rlock;
wait_queue_head_t wait;
struct work_struct rxwork;
int werr;
}
/* concurrent writes and disconnect */
- r = mutex_lock_interruptible(&desc->lock);
+ r = mutex_lock_interruptible(&desc->wlock);
rv = -ERESTARTSYS;
if (r) {
kfree(buf);
out:
usb_autopm_put_interface(desc->intf);
outnp:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
outnl:
return rv < 0 ? rv : count;
}
struct wdm_device *desc = file->private_data;
- rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
+ rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
if (rv < 0)
return -ERESTARTSYS;
for (i = 0; i < desc->length - cntr; i++)
desc->ubuf[i] = desc->ubuf[i + cntr];
+ spin_lock_irq(&desc->iuspin);
desc->length -= cntr;
+ spin_unlock_irq(&desc->iuspin);
/* in case we had outstanding data */
if (!desc->length)
clear_bit(WDM_READ, &desc->flags);
rv = cntr;
err:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->rlock);
return rv;
}
}
intf->needs_remote_wakeup = 1;
- mutex_lock(&desc->lock);
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
if (!desc->count++) {
desc->werr = 0;
desc->rerr = 0;
} else {
rv = 0;
}
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
usb_autopm_put_interface(desc->intf);
out:
mutex_unlock(&wdm_mutex);
struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex);
- mutex_lock(&desc->lock);
+
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
desc->count--;
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
struct usb_cdc_dmm_desc *dmhd;
u8 *buffer = intf->altsetting->extra;
int buflen = intf->altsetting->extralen;
- u16 maxcom = 0;
+ u16 maxcom = WDM_DEFAULT_BUFSIZE;
if (!buffer)
goto out;
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc)
goto out;
- mutex_init(&desc->lock);
+ mutex_init(&desc->rlock);
+ mutex_init(&desc->wlock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
goto err;
desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
- desc->bMaxPacketSize0,
+ desc->wMaxCommand,
GFP_KERNEL,
&desc->response->transfer_dma);
if (!desc->inbuf)
/* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags);
- mutex_lock(&desc->lock);
+ wake_up_all(&desc->wait);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
- mutex_unlock(&desc->lock);
- wake_up_all(&desc->wait);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
if (!desc->count)
cleanup(desc);
mutex_unlock(&wdm_mutex);
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
/* if this is an autosuspend the caller does the locking */
- if (!PMSG_IS_AUTO(message))
- mutex_lock(&desc->lock);
+ if (!PMSG_IS_AUTO(message)) {
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
+ }
spin_lock_irq(&desc->iuspin);
if (PMSG_IS_AUTO(message) &&
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
}
- if (!PMSG_IS_AUTO(message))
- mutex_unlock(&desc->lock);
+ if (!PMSG_IS_AUTO(message)) {
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
+ }
return rv;
}
{
struct wdm_device *desc = usb_get_intfdata(intf);
- mutex_lock(&desc->lock);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
/*
int rv;
rv = recover_from_urb_loss(desc);
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
return 0;
}
struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- u32 type;
int ret = 0;
req->request.actual = 0;
direction = !!(dep->flags & DWC3_EP0_DIR_IN);
- if (dwc->ep0state == EP0_STATUS_PHASE) {
- type = dwc->three_stage_setup
- ? DWC3_TRBCTL_CONTROL_STATUS3
- : DWC3_TRBCTL_CONTROL_STATUS2;
- } else if (dwc->ep0state == EP0_DATA_PHASE) {
- type = DWC3_TRBCTL_CONTROL_DATA;
- } else {
- /* should never happen */
- WARN_ON(1);
+ if (dwc->ep0state != EP0_DATA_PHASE) {
+ dev_WARN(dwc->dev, "Unexpected pending request\n");
return 0;
}
ret = dwc3_ep0_start_trans(dwc, direction,
- req->request.dma, req->request.length, type);
+ req->request.dma, req->request.length,
+ DWC3_TRBCTL_CONTROL_DATA);
dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
DWC3_EP0_DIR_IN);
} else if (dwc->delayed_status) {
if (req->request.num_mapped_sgs) {
req->request.dma = DMA_ADDR_INVALID;
dma_unmap_sg(dwc->dev, req->request.sg,
- req->request.num_sgs,
+ req->request.num_mapped_sgs,
req->direction ? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
_ep->comp_desc = comp_desc;
if (g->speed == USB_SPEED_SUPER) {
switch (usb_endpoint_type(_ep->desc)) {
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
- _ep->maxburst = comp_desc->bMaxBurst;
- break;
case USB_ENDPOINT_XFER_ISOC:
/* mult: bits 1:0 of bmAttributes */
_ep->mult = comp_desc->bmAttributes & 0x3;
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ _ep->maxburst = comp_desc->bMaxBurst;
break;
default:
/* Do nothing for control endpoints */
* descriptor and see if the EP matches it
*/
if (usb_endpoint_xfer_bulk(desc)) {
- if (ep_comp) {
+ if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
num_req_streams = ep_comp->bmAttributes & 0x1f;
if (num_req_streams > ep->max_streams)
return 0;
struct fsg_module_parameters {
char *file[FSG_MAX_LUNS];
- int ro[FSG_MAX_LUNS];
- int removable[FSG_MAX_LUNS];
- int cdrom[FSG_MAX_LUNS];
- int nofua[FSG_MAX_LUNS];
+ bool ro[FSG_MAX_LUNS];
+ bool removable[FSG_MAX_LUNS];
+ bool cdrom[FSG_MAX_LUNS];
+ bool nofua[FSG_MAX_LUNS];
unsigned int file_count, ro_count, removable_count, cdrom_count;
unsigned int nofua_count;
unsigned int luns; /* nluns */
- int stall; /* can_stall */
+ bool stall; /* can_stall */
};
#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \
int pipe = get_pipe_by_windex(wIndex);
struct fsl_ep *ep;
- if (wValue != 0 || wLength != 0 || pipe > udc->max_ep)
+ if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep)
break;
ep = get_ep_by_pipe(udc, pipe);
if (!bit_pos)
return;
- for (i = 0; i < udc->max_ep * 2; i++) {
+ for (i = 0; i < udc->max_ep; i++) {
ep_num = i >> 1;
direction = i % 2;
/* #undef DEBUG */
/* #undef VERBOSE_DEBUG */
-#if defined(CONFIG_USB_LANGWELL_OTG)
-#define OTG_TRANSCEIVER
-#endif
-
-
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
/* stop all USB activities */
-static void stop_activity(struct langwell_udc *dev,
- struct usb_gadget_driver *driver)
+static void stop_activity(struct langwell_udc *dev)
{
struct langwell_ep *ep;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
}
/* report disconnect; the driver is already quiesced */
- if (driver) {
+ if (dev->driver) {
spin_unlock(&dev->lock);
- driver->disconnect(&dev->gadget);
+ dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
/* stop all usb activities */
dev->gadget.speed = USB_SPEED_UNKNOWN;
- stop_activity(dev, driver);
- spin_unlock_irqrestore(&dev->lock, flags);
-
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
+ stop_activity(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
device_remove_file(&dev->pdev->dev, &dev_attr_function);
if (!gadget_is_otg(&dev->gadget))
break;
- else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
+ else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
dev->gadget.b_hnp_enable = 1;
-#ifdef OTG_TRANSCEIVER
- if (!dev->lotg->otg.default_a)
- dev->lotg->hsm.b_hnp_enable = 1;
-#endif
- } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
+ else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
dev->gadget.a_hnp_support = 1;
else if (setup->bRequest ==
USB_DEVICE_A_ALT_HNP_SUPPORT)
dev->bus_reset = 1;
/* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
dev->usb_state = USB_STATE_DEFAULT;
} else {
dev_vdbg(&dev->pdev->dev, "device controller reset\n");
langwell_udc_reset(dev);
/* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
/* reset ep0 dQH and endptctrl */
ep0_reset(dev);
dev->usb_state = USB_STATE_ATTACHED;
}
-#ifdef OTG_TRANSCEIVER
- /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */
- if (!dev->lotg->otg.default_a)
- dev->lotg->hsm.b_hnp_enable = 0;
-#endif
-
dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
}
dev->resume_state = dev->usb_state;
dev->usb_state = USB_STATE_SUSPENDED;
-#ifdef OTG_TRANSCEIVER
- if (dev->lotg->otg.default_a) {
- if (dev->lotg->hsm.b_bus_suspend_vld == 1) {
- dev->lotg->hsm.b_bus_suspend = 1;
- /* notify transceiver the state changes */
- if (spin_trylock(&dev->lotg->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&dev->lotg->wq_lock);
- }
- }
- dev->lotg->hsm.b_bus_suspend_vld++;
- } else {
- if (!dev->lotg->hsm.a_bus_suspend) {
- dev->lotg->hsm.a_bus_suspend = 1;
- /* notify transceiver the state changes */
- if (spin_trylock(&dev->lotg->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&dev->lotg->wq_lock);
- }
- }
- }
-#endif
-
/* report suspend to the driver */
if (dev->driver) {
if (dev->driver->suspend) {
if (dev->pdev->device != 0x0829)
langwell_phy_low_power(dev, 0);
-#ifdef OTG_TRANSCEIVER
- if (dev->lotg->otg.default_a == 0)
- dev->lotg->hsm.a_bus_suspend = 0;
-#endif
-
/* report resume to the driver */
if (dev->driver) {
if (dev->driver->resume) {
dev->done = &done;
-#ifndef OTG_TRANSCEIVER
/* free dTD dma_pool and dQH */
if (dev->dtd_pool)
dma_pool_destroy(dev->dtd_pool);
/* release SRAM caching */
if (dev->has_sram && dev->got_sram)
sram_deinit(dev);
-#endif
if (dev->status_req) {
kfree(dev->status_req->req.buf);
if (dev->got_irq)
free_irq(pdev->irq, dev);
-#ifndef OTG_TRANSCEIVER
if (dev->cap_regs)
iounmap(dev->cap_regs);
if (dev->enabled)
pci_disable_device(pdev);
-#else
- if (dev->transceiver) {
- otg_put_transceiver(dev->transceiver);
- dev->transceiver = NULL;
- dev->lotg = NULL;
- }
-#endif
dev->cap_regs = NULL;
device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
-#ifndef OTG_TRANSCEIVER
pci_set_drvdata(pdev, NULL);
-#endif
/* free dev, wait for the release() finished */
wait_for_completion(&done);
const struct pci_device_id *id)
{
struct langwell_udc *dev;
-#ifndef OTG_TRANSCEIVER
unsigned long resource, len;
-#endif
void __iomem *base = NULL;
size_t size;
int retval;
dev->pdev = pdev;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-#ifdef OTG_TRANSCEIVER
- /* PCI device is already enabled by otg_transceiver driver */
- dev->enabled = 1;
-
- /* mem region and register base */
- dev->region = 1;
- dev->transceiver = otg_get_transceiver();
- dev->lotg = otg_to_langwell(dev->transceiver);
- base = dev->lotg->regs;
-#else
pci_set_drvdata(pdev, dev);
/* now all the pci goodies ... */
dev->region = 1;
base = ioremap_nocache(resource, len);
-#endif
if (base == NULL) {
dev_err(&dev->pdev->dev, "can't map memory\n");
retval = -EFAULT;
dev->got_sram = 0;
dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
-#ifndef OTG_TRANSCEIVER
/* enable SRAM caching if detected */
if (dev->has_sram && !dev->got_sram)
sram_init(dev);
goto error;
}
dev->got_irq = 1;
-#endif
/* set stopped bit */
dev->stopped = 1;
dev->remote_wakeup = 0;
dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
-#ifndef OTG_TRANSCEIVER
/* reset device controller */
langwell_udc_reset(dev);
-#endif
/* initialize gadget structure */
dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */
INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
-#ifdef OTG_TRANSCEIVER
- dev->gadget.is_otg = 1; /* support otg mode */
-#endif
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&dev->gadget.dev, "gadget");
/* controller endpoints reinit */
eps_reinit(dev);
-#ifndef OTG_TRANSCEIVER
/* reset ep0 dQH and endptctrl */
ep0_reset(dev);
-#endif
/* create dTD dma_pool resource */
dev->dtd_pool = dma_pool_create("langwell_dtd",
spin_lock_irq(&dev->lock);
/* stop all usb activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
spin_unlock_irq(&dev->lock);
/* free dTD dma_pool and dQH */
static int __init init(void)
{
-#ifdef OTG_TRANSCEIVER
- return langwell_register_peripheral(&langwell_pci_driver);
-#else
return pci_register_driver(&langwell_pci_driver);
-#endif
}
module_init(init);
static void __exit cleanup(void)
{
-#ifdef OTG_TRANSCEIVER
- return langwell_unregister_peripheral(&langwell_pci_driver);
-#else
pci_unregister_driver(&langwell_pci_driver);
-#endif
}
module_exit(cleanup);
*/
#include <linux/usb/langwell_udc.h>
-#include <linux/usb/langwell_otg.h>
/*-------------------------------------------------------------------------*/
| USB_5GBPS_OPERATION),
.bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT,
- .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT,
+ .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
};
static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
- .wTotalLength = USB_DT_BOS_SIZE
+ .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE
+ USB_DT_USB_EXT_CAP_SIZE
- + USB_DT_USB_SS_CAP_SIZE,
+ + USB_DT_USB_SS_CAP_SIZE),
.bNumDeviceCaps = 2,
};
*/
if (pdata->init && pdata->init(pdev)) {
retval = -ENODEV;
- goto err3;
+ goto err4;
}
/* Enable USB controller, 83xx or 8536 */
/* Serial Bus Release Number is at PCI 0x60 offset */
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+ if (pdev->vendor == PCI_VENDOR_ID_STMICRO
+ && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
+ ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
/* Keep this around for a while just in case some EHCI
* implementation uses legacy PCI PM support. This test
/* handle any USB 2.0 EHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
.driver_data = (unsigned long) &ehci_pci_hc_driver,
+ }, {
+ PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST),
+ .driver_data = (unsigned long) &ehci_pci_hc_driver,
},
{ /* end: all zeroes */ }
};
}
iclk = clk_get(&pdev->dev, "ohci_clk");
+ if (IS_ERR(iclk)) {
+ dev_err(&pdev->dev, "failed to get ohci_clk\n");
+ retval = PTR_ERR(iclk);
+ goto err3;
+ }
fclk = clk_get(&pdev->dev, "uhpck");
+ if (IS_ERR(fclk)) {
+ dev_err(&pdev->dev, "failed to get uhpck\n");
+ retval = PTR_ERR(fclk);
+ goto err4;
+ }
hclk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(hclk)) {
+ dev_err(&pdev->dev, "failed to get hclk\n");
+ retval = PTR_ERR(hclk);
+ goto err5;
+ }
at91_start_hc(pdev);
ohci_hcd_init(hcd_to_ohci(hcd));
at91_stop_hc(pdev);
clk_put(hclk);
+ err5:
clk_put(fclk);
+ err4:
clk_put(iclk);
+ err3:
iounmap(hcd->regs);
err2:
if (!gpio_is_valid(pdata->vbus_pin[port]))
return;
- gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
+ gpio_set_value(pdata->vbus_pin[port],
+ !pdata->vbus_pin_active_low[port] ^ enable);
}
static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
if (!gpio_is_valid(pdata->vbus_pin[port]))
return -EINVAL;
- return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
+ return gpio_get_value(pdata->vbus_pin[port]) ^
+ !pdata->vbus_pin_active_low[port];
}
/*
ohci_dbg(ohci,format, ## arg ); \
} while (0);
+/* Version for use where "next" is the address of a local variable */
+#define ohci_dbg_nosw(ohci, next, size, format, arg...) \
+ do { \
+ unsigned s_len; \
+ s_len = scnprintf(*next, *size, format, ## arg); \
+ *size -= s_len; *next += s_len; \
+ } while (0);
+
static void ohci_dump_intr_mask (
struct ohci_hcd *ohci,
/* dump driver info, then registers in spec order */
- ohci_dbg_sw (ohci, &next, &size,
+ ohci_dbg_nosw(ohci, &next, &size,
"bus %s, device %s\n"
"%s\n"
"%s\n",
/* hcca */
if (ohci->hcca)
- ohci_dbg_sw (ohci, &next, &size,
+ ohci_dbg_nosw(ohci, &next, &size,
"hcca frame 0x%04x\n", ohci_frame_no(ohci));
/* other registers mostly affect frame timings */
/* handle any USB OHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
.driver_data = (unsigned long) &ohci_pci_hc_driver,
+ }, {
+ /* The device in the ConneXT I/O hub has no class reg */
+ PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI),
+ .driver_data = (unsigned long) &ohci_pci_hc_driver,
}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, pci_ids);
*
* Returns a zero-based port number, which is suitable for indexing into each of
* the split roothubs' port arrays and bus state arrays.
+ * Add one to it in order to call xhci_find_slot_id_by_port.
*/
static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
struct xhci_hcd *xhci, u32 port_id)
xhci_set_link_state(xhci, port_array, faked_port_index,
XDEV_U0);
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
- faked_port_index);
+ faked_port_index + 1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n");
goto cleanup;
/* Check TD length */
if (running_total != td_len) {
xhci_err(xhci, "ISOC TD length unmatch\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto cleanup;
}
}
static int emi26_load_firmware (struct usb_device *dev);
static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi26_disconnect(struct usb_interface *intf);
-static int __init emi26_init (void);
-static void __exit emi26_exit (void);
-
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi26_writememory (struct usb_device *dev, int address,
static int emi62_load_firmware (struct usb_device *dev);
static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi62_disconnect(struct usb_interface *intf);
-static int __init emi62_init (void);
-static void __exit emi62_exit (void);
-
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi62_writememory(struct usb_device *dev, int address,
#define VENDOR_ID 0x0fc5
#define PRODUCT_ID 0x1227
-#define MAXLEN 6
+#define MAXLEN 8
/* table of devices that work with this driver */
static const struct usb_device_id id_table[] = {
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/gpio.h>
#include <mach/cputype.h>
#include <asm/mach-types.h>
unsigned long flags;
pm_runtime_get_sync(musb->controller);
+
+ musb_gadget_cleanup(musb);
+
spin_lock_irqsave(&musb->lock, flags);
musb_platform_disable(musb);
musb_generic_disable(musb);
sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
#endif
- musb_gadget_cleanup(musb);
-
if (musb->nIrq >= 0) {
if (musb->irq_wake)
disable_irq_wake(musb->nIrq);
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
-/* blocking notifier support */
static int musb_otg_notifications(struct notifier_block *nb,
unsigned long event, void *unused)
{
musb->xceiv_event = event;
schedule_work(&musb->otg_notifier_work);
- return 0;
+ return NOTIFY_OK;
}
static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
static int omap2430_musb_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
+ cancel_work_sync(&musb->otg_notifier_work);
omap2430_low_level_exit(musb);
otg_put_transceiver(musb->xceiv);
built-in with usb ip or which are autonomous and doesn't require any
phy programming such as ISP1x04 etc.
-config USB_LANGWELL_OTG
- tristate "Intel Langwell USB OTG dual-role support"
- depends on USB && PCI && INTEL_SCU_IPC
- select USB_OTG
- select USB_OTG_UTILS
- help
- Say Y here if you want to build Intel Langwell USB OTG
- transciever driver in kernel. This driver implements role
- switch between EHCI host driver and Langwell USB OTG
- client driver.
-
- To compile this driver as a module, choose M here: the
- module will be called langwell_otg.
-
config USB_MSM_OTG
tristate "OTG support for Qualcomm on-chip USB controller"
depends on (USB || USB_GADGET) && ARCH_MSM
config FSL_USB2_OTG
bool "Freescale USB OTG Transceiver Driver"
- depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2
+ depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
config USB_MV_OTG
tristate "Marvell USB OTG support"
- depends on USB_MV_UDC
+ depends on USB_MV_UDC && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o
-obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
obj-$(CONFIG_USB_ULPI) += ulpi.o
obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o
+++ /dev/null
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/* This driver helps to switch Langwell OTG controller function between host
- * and peripheral. It works with EHCI driver and Langwell client controller
- * driver together.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/hcd.h>
-#include <linux/notifier.h>
-#include <linux/delay.h>
-#include <asm/intel_scu_ipc.h>
-
-#include <linux/usb/langwell_otg.h>
-
-#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver"
-#define DRIVER_VERSION "July 10, 2010"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "langwell_otg";
-
-static int langwell_otg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
-static void langwell_otg_remove(struct pci_dev *pdev);
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
-static int langwell_otg_resume(struct pci_dev *pdev);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
- struct usb_bus *host);
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
- struct usb_gadget *gadget);
-static int langwell_otg_start_srp(struct otg_transceiver *otg);
-
-static const struct pci_device_id pci_ids[] = {{
- .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
- .class_mask = ~0,
- .vendor = 0x8086,
- .device = 0x0811,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-static struct pci_driver otg_pci_driver = {
- .name = (char *) driver_name,
- .id_table = pci_ids,
-
- .probe = langwell_otg_probe,
- .remove = langwell_otg_remove,
-
- .suspend = langwell_otg_suspend,
- .resume = langwell_otg_resume,
-};
-
-/* HSM timers */
-static inline struct langwell_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
- struct langwell_otg_timer *timer;
- timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
- if (timer == NULL)
- return timer;
-
- timer->function = function;
- timer->expires = expires;
- timer->data = data;
- return timer;
-}
-
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
- *b_se0_srp_tmr, *b_srp_init_tmr;
-
-static struct list_head active_timers;
-
-static struct langwell_otg *the_transceiver;
-
-/* host/client notify transceiver when event affects HNP state */
-void langwell_update_transceiver(void)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- dev_dbg(lnw->dev, "transceiver is updated\n");
-
- if (!lnw->qwork)
- return ;
-
- queue_work(lnw->qwork, &lnw->work);
-}
-EXPORT_SYMBOL(langwell_update_transceiver);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
- struct usb_bus *host)
-{
- otg->host = host;
-
- return 0;
-}
-
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
- struct usb_gadget *gadget)
-{
- otg->gadget = gadget;
-
- return 0;
-}
-
-static int langwell_otg_set_power(struct otg_transceiver *otg,
- unsigned mA)
-{
- return 0;
-}
-
-/* A-device drives vbus, controlled through IPC commands */
-static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
-{
- struct langwell_otg *lnw = the_transceiver;
- u8 sub_id;
-
- dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off");
-
- if (enabled)
- sub_id = 0x8; /* Turn on the VBus */
- else
- sub_id = 0x9; /* Turn off the VBus */
-
- if (intel_scu_ipc_simple_command(0xef, sub_id)) {
- dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n");
- return -EBUSY;
- }
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- return 0;
-}
-
-/* charge vbus or discharge vbus through a resistor to ground */
-static void langwell_otg_chrg_vbus(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- val = readl(lnw->iotg.base + CI_OTGSC);
-
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
- lnw->iotg.base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
- lnw->iotg.base + CI_OTGSC);
-}
-
-/* Start SRP */
-static int langwell_otg_start_srp(struct otg_transceiver *otg)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- val = readl(iotg->base + CI_OTGSC);
-
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
- iotg->base + CI_OTGSC);
-
- /* Check if the data plus is finished or not */
- msleep(8);
- val = readl(iotg->base + CI_OTGSC);
- if (val & (OTGSC_HADP | OTGSC_DP))
- dev_dbg(lnw->dev, "DataLine SRP Error\n");
-
- /* Disable interrupt - b_sess_vld */
- val = readl(iotg->base + CI_OTGSC);
- val &= (~(OTGSC_BSVIE | OTGSC_BSEIE));
- writel(val, iotg->base + CI_OTGSC);
-
- /* Start VBus SRP, drive vbus to generate VBus pulse */
- iotg->otg.set_vbus(&iotg->otg, true);
- msleep(15);
- iotg->otg.set_vbus(&iotg->otg, false);
-
- /* Enable interrupt - b_sess_vld*/
- val = readl(iotg->base + CI_OTGSC);
- dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val);
-
- val |= (OTGSC_BSVIE | OTGSC_BSEIE);
- writel(val, iotg->base + CI_OTGSC);
-
- /* If Vbus is valid, then update the hsm */
- if (val & OTGSC_BSV) {
- dev_dbg(lnw->dev, "no b_sess_vld interrupt\n");
-
- lnw->iotg.hsm.b_sess_vld = 1;
- langwell_update_transceiver();
- }
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
- return 0;
-}
-
-/* stop SOF via bus_suspend */
-static void langwell_otg_loc_sof(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct usb_hcd *hcd;
- int err;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume");
-
- hcd = bus_to_hcd(lnw->iotg.otg.host);
- if (on)
- err = hcd->driver->bus_resume(hcd);
- else
- err = hcd->driver->bus_suspend(hcd);
-
- if (err)
- dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_otgsc(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 otgsc, usbcfg;
-
- dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n");
-
- otgsc = readl(lnw->iotg.base + CI_OTGSC);
- usbcfg = readl(lnw->usbcfg);
-
- dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n",
- otgsc, usbcfg);
- dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV));
- dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n",
- !!(usbcfg & USBCFG_VBUSVAL));
- dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV));
- dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n",
- !!(usbcfg & USBCFG_AVALID));
- dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV));
- dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n",
- !!(usbcfg & USBCFG_BVALID));
- dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE));
- dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n",
- !!(usbcfg & USBCFG_SESEND));
-
- /* Check USBCFG VBusValid/AValid/BValid/SessEnd */
- if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) {
- dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) {
- dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) {
- dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) {
- dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n");
- goto err;
- }
-
- dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n");
-
- return 0;
-
-err:
- dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n");
- return -EPIPE;
-}
-
-
-static void langwell_otg_phy_low_power(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u8 val, phcd;
- int retval;
-
- dev_dbg(lnw->dev, "%s ---> %s mode\n",
- __func__, on ? "Low power" : "Normal");
-
- phcd = 0x40;
-
- val = readb(iotg->base + CI_HOSTPC1 + 2);
-
- if (on) {
- /* Due to hardware issue, after set PHCD, sync will failed
- * between USBCFG and OTGSC, so before set PHCD, check if
- * sync is in process now. If the answer is "yes", then do
- * not touch PHCD bit */
- retval = langwell_otg_check_otgsc();
- if (retval) {
- dev_dbg(lnw->dev, "Skip PHCD programming..\n");
- return ;
- }
-
- writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2);
- } else
- writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2);
-
- dev_dbg(lnw->dev, "%s <--- done\n", __func__);
-}
-
-/* After drv vbus, add 5 ms delay to set PHCD */
-static void langwell_otg_phy_low_power_wait(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n");
-
- mdelay(5);
- langwell_otg_phy_low_power(on);
-}
-
-/* Enable/Disable OTG interrupt */
-static void langwell_otg_intr(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
-
- /* OTGSC_INT_MASK doesn't contains 1msInt */
- if (on) {
- val = val | (OTGSC_INT_MASK);
- writel(val, iotg->base + CI_OTGSC);
- } else {
- val = val & ~(OTGSC_INT_MASK);
- writel(val, iotg->base + CI_OTGSC);
- }
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HAAR: Hardware Assist Auto-Reset */
-static void langwell_otg_HAAR(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
- iotg->base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
- iotg->base + CI_OTGSC);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HABA: Hardware Assist B-Disconnect to A-Connect */
-static void langwell_otg_HABA(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
- iotg->base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
- iotg->base + CI_OTGSC);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_se0_srp(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- int delay_time = TB_SE0_SRP * 10;
- u32 val;
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- do {
- udelay(100);
- if (!delay_time--)
- break;
- val = readl(lnw->iotg.base + CI_PORTSC1);
- val &= PORTSC_LS;
- } while (!val);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
- return val;
-}
-
-/* The timeout callback function to set time out bit */
-static void set_tmout(unsigned long indicator)
-{
- *(int *)indicator = 1;
-}
-
-void langwell_otg_nsf_msg(unsigned long indicator)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- switch (indicator) {
- case 2:
- case 4:
- case 6:
- case 7:
- dev_warn(lnw->dev,
- "OTG:NSF-%lu - deivce not responding\n", indicator);
- break;
- case 3:
- dev_warn(lnw->dev,
- "OTG:NSF-%lu - deivce not supported\n", indicator);
- break;
- default:
- dev_warn(lnw->dev, "Do not have this kind of NSF\n");
- break;
- }
-}
-
-/* Initialize timers */
-static int langwell_otg_init_timers(struct otg_hsm *hsm)
-{
- /* HSM used timers */
- a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
- (unsigned long)&hsm->a_wait_vrise_tmout);
- if (a_wait_vrise_tmr == NULL)
- return -ENOMEM;
- a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
- (unsigned long)&hsm->a_aidl_bdis_tmout);
- if (a_aidl_bdis_tmr == NULL)
- return -ENOMEM;
- b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
- (unsigned long)&hsm->b_se0_srp);
- if (b_se0_srp_tmr == NULL)
- return -ENOMEM;
- b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
- (unsigned long)&hsm->b_srp_init_tmout);
- if (b_srp_init_tmr == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-/* Free timers */
-static void langwell_otg_free_timers(void)
-{
- kfree(a_wait_vrise_tmr);
- kfree(a_aidl_bdis_tmr);
- kfree(b_se0_srp_tmr);
- kfree(b_srp_init_tmr);
-}
-
-/* The timeout callback function to set time out bit */
-static void langwell_otg_timer_fn(unsigned long indicator)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- *(int *)indicator = 1;
-
- dev_dbg(lnw->dev, "kernel timer - timeout\n");
-
- langwell_update_transceiver();
-}
-
-/* kernel timer used instead of HW based interrupt */
-static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- unsigned long j = jiffies;
- unsigned long data, time;
-
- switch (timers) {
- case TA_WAIT_VRISE_TMR:
- iotg->hsm.a_wait_vrise_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout;
- time = TA_WAIT_VRISE;
- break;
- case TA_WAIT_BCON_TMR:
- iotg->hsm.a_wait_bcon_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout;
- time = TA_WAIT_BCON;
- break;
- case TA_AIDL_BDIS_TMR:
- iotg->hsm.a_aidl_bdis_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout;
- time = TA_AIDL_BDIS;
- break;
- case TB_ASE0_BRST_TMR:
- iotg->hsm.b_ase0_brst_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout;
- time = TB_ASE0_BRST;
- break;
- case TB_SRP_INIT_TMR:
- iotg->hsm.b_srp_init_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_srp_init_tmout;
- time = TB_SRP_INIT;
- break;
- case TB_SRP_FAIL_TMR:
- iotg->hsm.b_srp_fail_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_srp_fail_tmout;
- time = TB_SRP_FAIL;
- break;
- case TB_BUS_SUSPEND_TMR:
- iotg->hsm.b_bus_suspend_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout;
- time = TB_BUS_SUSPEND;
- break;
- default:
- dev_dbg(lnw->dev, "unknown timer, cannot enable it\n");
- return;
- }
-
- lnw->hsm_timer.data = data;
- lnw->hsm_timer.function = langwell_otg_timer_fn;
- lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
-
- add_timer(&lnw->hsm_timer);
-
- dev_dbg(lnw->dev, "add timer successfully\n");
-}
-
-/* Add timer to timer list */
-static void langwell_otg_add_timer(void *gtimer)
-{
- struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
- struct langwell_otg_timer *tmp_timer;
- struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg;
- u32 val32;
-
- /* Check if the timer is already in the active list,
- * if so update timer count
- */
- list_for_each_entry(tmp_timer, &active_timers, list)
- if (tmp_timer == timer) {
- timer->count = timer->expires;
- return;
- }
- timer->count = timer->expires;
-
- if (list_empty(&active_timers)) {
- val32 = readl(iotg->base + CI_OTGSC);
- writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC);
- }
-
- list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-static void langwell_otg_del_timer(void *gtimer)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
- struct langwell_otg_timer *tmp_timer, *del_tmp;
- u32 val32;
-
- list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
- if (tmp_timer == timer)
- list_del(&timer->list);
-
- if (list_empty(&active_timers)) {
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC);
- }
-}
-
-/* Reduce timer count by 1, and find timeout conditions.*/
-static int langwell_otg_tick_timer(u32 *int_sts)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct langwell_otg_timer *tmp_timer, *del_tmp;
- int expired = 0;
-
- list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
- tmp_timer->count--;
- /* check if timer expires */
- if (!tmp_timer->count) {
- list_del(&tmp_timer->list);
- tmp_timer->function(tmp_timer->data);
- expired = 1;
- }
- }
-
- if (list_empty(&active_timers)) {
- dev_dbg(lnw->dev, "tick timer: disable 1ms int\n");
- *int_sts = *int_sts & ~OTGSC_1MSE;
- }
- return expired;
-}
-
-static void reset_otg(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- int delay_time = 1000;
- u32 val;
-
- dev_dbg(lnw->dev, "reseting OTG controller ...\n");
- val = readl(lnw->iotg.base + CI_USBCMD);
- writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD);
- do {
- udelay(100);
- if (!delay_time--)
- dev_dbg(lnw->dev, "reset timeout\n");
- val = readl(lnw->iotg.base + CI_USBCMD);
- val &= USBCMD_RST;
- } while (val != 0);
- dev_dbg(lnw->dev, "reset done.\n");
-}
-
-static void set_host_mode(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- reset_otg();
- val = readl(lnw->iotg.base + CI_USBMODE);
- val = (val & (~USBMODE_CM)) | USBMODE_HOST;
- writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void set_client_mode(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- reset_otg();
- val = readl(lnw->iotg.base + CI_USBMODE);
- val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
- writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void init_hsm(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val32;
-
- /* read OTGSC after reset */
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32);
-
- /* set init state */
- if (val32 & OTGSC_ID) {
- iotg->hsm.id = 1;
- iotg->otg.default_a = 0;
- set_client_mode();
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else {
- iotg->hsm.id = 0;
- iotg->otg.default_a = 1;
- set_host_mode();
- iotg->otg.state = OTG_STATE_A_IDLE;
- }
-
- /* set session indicator */
- if (val32 & OTGSC_BSE)
- iotg->hsm.b_sess_end = 1;
- if (val32 & OTGSC_BSV)
- iotg->hsm.b_sess_vld = 1;
- if (val32 & OTGSC_ASV)
- iotg->hsm.a_sess_vld = 1;
- if (val32 & OTGSC_AVV)
- iotg->hsm.a_vbus_vld = 1;
-
- /* defautly power the bus */
- iotg->hsm.a_bus_req = 1;
- iotg->hsm.a_bus_drop = 0;
- /* defautly don't request bus as B device */
- iotg->hsm.b_bus_req = 0;
- /* no system error */
- iotg->hsm.a_clr_err = 0;
-
- langwell_otg_phy_low_power_wait(1);
-}
-
-static void update_hsm(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val32;
-
- /* read OTGSC */
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32);
-
- iotg->hsm.id = !!(val32 & OTGSC_ID);
- iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE);
- iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV);
- iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV);
- iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV);
-}
-
-static irqreturn_t otg_dummy_irq(int irq, void *_dev)
-{
- struct langwell_otg *lnw = the_transceiver;
- void __iomem *reg_base = _dev;
- u32 val;
- u32 int_mask = 0;
-
- val = readl(reg_base + CI_USBMODE);
- if ((val & USBMODE_CM) != USBMODE_DEVICE)
- return IRQ_NONE;
-
- val = readl(reg_base + CI_USBSTS);
- int_mask = val & INTR_DUMMY_MASK;
-
- if (int_mask == 0)
- return IRQ_NONE;
-
- /* clear hsm.b_conn here since host driver can't detect it
- * otg_dummy_irq called means B-disconnect happened.
- */
- if (lnw->iotg.hsm.b_conn) {
- lnw->iotg.hsm.b_conn = 0;
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- }
-
- /* Clear interrupts */
- writel(int_mask, reg_base + CI_USBSTS);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t otg_irq(int irq, void *_dev)
-{
- struct langwell_otg *lnw = _dev;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 int_sts, int_en;
- u32 int_mask = 0;
- int flag = 0;
-
- int_sts = readl(lnw->iotg.base + CI_OTGSC);
- int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
- int_mask = int_sts & int_en;
- if (int_mask == 0)
- return IRQ_NONE;
-
- if (int_mask & OTGSC_IDIS) {
- dev_dbg(lnw->dev, "%s: id change int\n", __func__);
- iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
- dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id);
- flag = 1;
- }
- if (int_mask & OTGSC_DPIS) {
- dev_dbg(lnw->dev, "%s: data pulse int\n", __func__);
- iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
- dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det);
- flag = 1;
- }
- if (int_mask & OTGSC_BSEIS) {
- dev_dbg(lnw->dev, "%s: b session end int\n", __func__);
- iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
- dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end);
- flag = 1;
- }
- if (int_mask & OTGSC_BSVIS) {
- dev_dbg(lnw->dev, "%s: b session valid int\n", __func__);
- iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
- dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end);
- flag = 1;
- }
- if (int_mask & OTGSC_ASVIS) {
- dev_dbg(lnw->dev, "%s: a session valid int\n", __func__);
- iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
- dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld);
- flag = 1;
- }
- if (int_mask & OTGSC_AVVIS) {
- dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__);
- iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
- dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld);
- flag = 1;
- }
-
- if (int_mask & OTGSC_1MSS) {
- /* need to schedule otg_work if any timer is expired */
- if (langwell_otg_tick_timer(&int_sts))
- flag = 1;
- }
-
- writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
- lnw->iotg.base + CI_OTGSC);
- if (flag)
- langwell_update_transceiver();
-
- return IRQ_HANDLED;
-}
-
-static int langwell_otg_iotg_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = data;
- int flag = 0;
-
- if (iotg == NULL)
- return NOTIFY_BAD;
-
- if (lnw == NULL)
- return NOTIFY_BAD;
-
- switch (action) {
- case MID_OTG_NOTIFY_CONNECT:
- dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_conn = 1;
- else
- iotg->hsm.a_conn = 1;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_DISCONN:
- dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_conn = 0;
- else
- iotg->hsm.a_conn = 0;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HSUSPEND:
- dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.a_suspend_req = 1;
- else
- iotg->hsm.b_bus_req = 0;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HRESUME:
- dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_bus_resume = 1;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CSUSPEND:
- dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n");
- if (iotg->otg.default_a == 1) {
- if (iotg->hsm.b_bus_suspend_vld == 2) {
- iotg->hsm.b_bus_suspend = 1;
- iotg->hsm.b_bus_suspend_vld = 0;
- flag = 1;
- } else {
- iotg->hsm.b_bus_suspend_vld++;
- flag = 0;
- }
- } else {
- if (iotg->hsm.a_bus_suspend == 0) {
- iotg->hsm.a_bus_suspend = 1;
- flag = 1;
- }
- }
- break;
- case MID_OTG_NOTIFY_CRESUME:
- dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n");
- if (iotg->otg.default_a == 0)
- iotg->hsm.a_bus_suspend = 0;
- flag = 0;
- break;
- case MID_OTG_NOTIFY_HOSTADD:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HOSTREMOVE:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CLIENTADD:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CLIENTREMOVE:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n");
- flag = 1;
- break;
- default:
- dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n");
- return NOTIFY_DONE;
- }
-
- if (flag)
- langwell_update_transceiver();
-
- return NOTIFY_OK;
-}
-
-static void langwell_otg_work(struct work_struct *work)
-{
- struct langwell_otg *lnw;
- struct intel_mid_otg_xceiv *iotg;
- int retval;
- struct pci_dev *pdev;
-
- lnw = container_of(work, struct langwell_otg, work);
- iotg = &lnw->iotg;
- pdev = to_pci_dev(lnw->dev);
-
- dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
- otg_state_string(iotg->otg.state));
-
- switch (iotg->otg.state) {
- case OTG_STATE_UNDEFINED:
- case OTG_STATE_B_IDLE:
- if (!iotg->hsm.id) {
- langwell_otg_del_timer(b_srp_init_tmr);
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
- set_host_mode();
- langwell_otg_phy_low_power(1);
-
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.b_sess_vld) {
- langwell_otg_del_timer(b_srp_init_tmr);
- del_timer_sync(&lnw->hsm_timer);
- iotg->hsm.b_sess_end = 0;
- iotg->hsm.a_bus_suspend = 0;
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.start_peripheral) {
- lnw->iotg.start_peripheral(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- } else
- dev_dbg(lnw->dev, "client driver not loaded\n");
-
- } else if (iotg->hsm.b_srp_init_tmout) {
- iotg->hsm.b_srp_init_tmout = 0;
- dev_warn(lnw->dev, "SRP init timeout\n");
- } else if (iotg->hsm.b_srp_fail_tmout) {
- iotg->hsm.b_srp_fail_tmout = 0;
- iotg->hsm.b_bus_req = 0;
-
- /* No silence failure */
- langwell_otg_nsf_msg(6);
- } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
- del_timer_sync(&lnw->hsm_timer);
- /* workaround for b_se0_srp detection */
- retval = langwell_otg_check_se0_srp(0);
- if (retval) {
- iotg->hsm.b_bus_req = 0;
- dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
- } else {
- /* clear the PHCD before start srp */
- langwell_otg_phy_low_power(0);
-
- /* Start SRP */
- langwell_otg_add_timer(b_srp_init_tmr);
- iotg->otg.start_srp(&iotg->otg);
- langwell_otg_del_timer(b_srp_init_tmr);
- langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
-
- /* reset PHY low power mode here */
- langwell_otg_phy_low_power_wait(1);
- }
- }
- break;
- case OTG_STATE_B_SRP_INIT:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_chrg_vbus(0);
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.b_sess_vld) {
- langwell_otg_chrg_vbus(0);
- if (lnw->iotg.start_peripheral) {
- lnw->iotg.start_peripheral(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- } else
- dev_dbg(lnw->dev, "client driver not loaded\n");
- }
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- iotg->hsm.b_hnp_enable = 0;
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
- iotg->otg.gadget->b_hnp_enable &&
- iotg->hsm.a_bus_suspend) {
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- langwell_otg_HAAR(1);
- iotg->hsm.a_conn = 0;
-
- if (lnw->iotg.start_host) {
- lnw->iotg.start_host(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_WAIT_ACON;
- } else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
-
- iotg->hsm.a_bus_resume = 0;
- langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
- }
- break;
-
- case OTG_STATE_B_WAIT_ACON:
- if (!iotg->hsm.id) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- langwell_otg_HAAR(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->hsm.b_hnp_enable = 0;
- iotg->hsm.b_bus_req = 0;
-
- langwell_otg_chrg_vbus(0);
- langwell_otg_HAAR(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.a_conn) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
- iotg->otg.state = OTG_STATE_B_HOST;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_resume ||
- iotg->hsm.b_ase0_brst_tmout) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
- langwell_otg_nsf_msg(7);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.a_bus_suspend = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- }
- break;
-
- case OTG_STATE_B_HOST:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- iotg->hsm.b_hnp_enable = 0;
- iotg->hsm.b_bus_req = 0;
-
- langwell_otg_chrg_vbus(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if ((!iotg->hsm.b_bus_req) ||
- (!iotg->hsm.a_conn)) {
- iotg->hsm.b_bus_req = 0;
- langwell_otg_loc_sof(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.a_bus_suspend = 0;
-
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- }
- break;
-
- case OTG_STATE_A_IDLE:
- iotg->otg.default_a = 1;
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
- iotg->hsm.vbus_srp_up = 0;
-
- langwell_otg_chrg_vbus(0);
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_bus_drop &&
- (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
- langwell_otg_phy_low_power(0);
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
-
- iotg->hsm.vbus_srp_up = 0;
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
- iotg->hsm.vbus_srp_up = 1;
- } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
- msleep(10);
- langwell_otg_phy_low_power(0);
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
- iotg->hsm.a_srp_det = 1;
- iotg->hsm.vbus_srp_up = 0;
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_sess_vld &&
- !iotg->hsm.vbus_srp_up) {
- langwell_otg_phy_low_power(1);
- }
- break;
- case OTG_STATE_A_WAIT_VRISE:
- if (iotg->hsm.id) {
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.b_bus_req = 0;
- iotg->otg.default_a = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.a_vbus_vld) {
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.b_conn = 0;
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else {
- dev_dbg(lnw->dev, "host driver not loaded.\n");
- break;
- }
-
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else if (iotg->hsm.a_wait_vrise_tmout) {
- iotg->hsm.b_conn = 0;
- if (iotg->hsm.a_vbus_vld) {
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else {
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- break;
- }
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else {
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- }
- }
- break;
- case OTG_STATE_A_WAIT_BCON:
- if (iotg->hsm.id) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_vbus_vld) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->hsm.a_bus_drop ||
- (iotg->hsm.a_wait_bcon_tmout &&
- !iotg->hsm.a_bus_req)) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (iotg->hsm.b_conn) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->hsm.a_suspend_req = 0;
- iotg->otg.state = OTG_STATE_A_HOST;
- if (iotg->hsm.a_srp_det && iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable) {
- /* SRP capable peripheral-only device */
- iotg->hsm.a_bus_req = 1;
- iotg->hsm.a_srp_det = 0;
- } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
- iotg->otg.host->b_hnp_enable) {
- /* It is not safe enough to do a fast
- * transition from A_WAIT_BCON to
- * A_SUSPEND */
- msleep(10000);
- if (iotg->hsm.a_bus_req)
- break;
-
- if (request_irq(pdev->irq,
- otg_dummy_irq, IRQF_SHARED,
- driver_name, iotg->base) != 0) {
- dev_dbg(lnw->dev,
- "request interrupt %d fail\n",
- pdev->irq);
- }
-
- langwell_otg_HABA(1);
- iotg->hsm.b_bus_resume = 0;
- iotg->hsm.a_aidl_bdis_tmout = 0;
-
- langwell_otg_loc_sof(0);
- /* clear PHCD to enable HW timer */
- langwell_otg_phy_low_power(0);
- langwell_otg_add_timer(a_aidl_bdis_tmr);
- iotg->otg.state = OTG_STATE_A_SUSPEND;
- } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- }
- }
- break;
- case OTG_STATE_A_HOST:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_drop ||
- (iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable &&
- !iotg->hsm.a_bus_req)) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (!iotg->hsm.a_vbus_vld) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->otg.host &&
- iotg->otg.host->b_hnp_enable &&
- !iotg->hsm.a_bus_req) {
- /* Set HABA to enable hardware assistance to signal
- * A-connect after receiver B-disconnect. Hardware
- * will then set client mode and enable URE, SLE and
- * PCE after the assistance. otg_dummy_irq is used to
- * clean these ints when client driver is not resumed.
- */
- if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
- driver_name, iotg->base) != 0) {
- dev_dbg(lnw->dev,
- "request interrupt %d failed\n",
- pdev->irq);
- }
-
- /* set HABA */
- langwell_otg_HABA(1);
- iotg->hsm.b_bus_resume = 0;
- iotg->hsm.a_aidl_bdis_tmout = 0;
- langwell_otg_loc_sof(0);
- /* clear PHCD to enable HW timer */
- langwell_otg_phy_low_power(0);
- langwell_otg_add_timer(a_aidl_bdis_tmr);
- iotg->otg.state = OTG_STATE_A_SUSPEND;
- } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- }
- break;
- case OTG_STATE_A_SUSPEND:
- if (iotg->hsm.id) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_req ||
- iotg->hsm.b_bus_resume) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- iotg->hsm.a_suspend_req = 0;
- langwell_otg_loc_sof(1);
- iotg->otg.state = OTG_STATE_A_HOST;
- } else if (iotg->hsm.a_aidl_bdis_tmout ||
- iotg->hsm.a_bus_drop) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (!iotg->hsm.b_conn && iotg->otg.host &&
- iotg->otg.host->b_hnp_enable) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.b_bus_suspend = 0;
- iotg->hsm.b_bus_suspend_vld = 0;
-
- /* msleep(200); */
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
- iotg->otg.state = OTG_STATE_A_PERIPHERAL;
- break;
- } else if (!iotg->hsm.a_vbus_vld) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- }
- break;
- case OTG_STATE_A_PERIPHERAL:
- if (iotg->hsm.id) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_vbus_vld) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->hsm.a_bus_drop) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (iotg->hsm.b_bus_suspend) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else if (iotg->hsm.b_bus_suspend_tmout) {
- u32 val;
- val = readl(lnw->iotg.base + CI_PORTSC1);
- if (!(val & PORTSC_SUSP))
- break;
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- }
- break;
- case OTG_STATE_A_VBUS_ERR:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.a_clr_err = 0;
- iotg->hsm.a_srp_det = 0;
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_clr_err) {
- iotg->hsm.a_clr_err = 0;
- iotg->hsm.a_srp_det = 0;
- reset_otg();
- init_hsm();
- if (iotg->otg.state == OTG_STATE_A_IDLE)
- langwell_update_transceiver();
- } else {
- /* FW will clear PHCD bit when any VBus
- * event detected. Reset PHCD to 1 again */
- langwell_otg_phy_low_power(1);
- }
- break;
- case OTG_STATE_A_WAIT_VFALL:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_req) {
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- } else if (!iotg->hsm.a_sess_vld) {
- iotg->hsm.a_srp_det = 0;
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- }
- break;
- default:
- ;
- }
-
- dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
- otg_state_string(iotg->otg.state));
-}
-
-static ssize_t
-show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size,
- "\n"
- "USBCMD = 0x%08x\n"
- "USBSTS = 0x%08x\n"
- "USBINTR = 0x%08x\n"
- "ASYNCLISTADDR = 0x%08x\n"
- "PORTSC1 = 0x%08x\n"
- "HOSTPC1 = 0x%08x\n"
- "OTGSC = 0x%08x\n"
- "USBMODE = 0x%08x\n",
- readl(lnw->iotg.base + 0x30),
- readl(lnw->iotg.base + 0x34),
- readl(lnw->iotg.base + 0x38),
- readl(lnw->iotg.base + 0x48),
- readl(lnw->iotg.base + 0x74),
- readl(lnw->iotg.base + 0xb4),
- readl(lnw->iotg.base + 0xf4),
- readl(lnw->iotg.base + 0xf8)
- );
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- if (iotg->otg.host)
- iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable;
-
- if (iotg->otg.gadget)
- iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable;
-
- t = scnprintf(next, size,
- "\n"
- "current state = %s\n"
- "a_bus_resume = \t%d\n"
- "a_bus_suspend = \t%d\n"
- "a_conn = \t%d\n"
- "a_sess_vld = \t%d\n"
- "a_srp_det = \t%d\n"
- "a_vbus_vld = \t%d\n"
- "b_bus_resume = \t%d\n"
- "b_bus_suspend = \t%d\n"
- "b_conn = \t%d\n"
- "b_se0_srp = \t%d\n"
- "b_sess_end = \t%d\n"
- "b_sess_vld = \t%d\n"
- "id = \t%d\n"
- "a_set_b_hnp_en = \t%d\n"
- "b_srp_done = \t%d\n"
- "b_hnp_enable = \t%d\n"
- "a_wait_vrise_tmout = \t%d\n"
- "a_wait_bcon_tmout = \t%d\n"
- "a_aidl_bdis_tmout = \t%d\n"
- "b_ase0_brst_tmout = \t%d\n"
- "a_bus_drop = \t%d\n"
- "a_bus_req = \t%d\n"
- "a_clr_err = \t%d\n"
- "a_suspend_req = \t%d\n"
- "b_bus_req = \t%d\n"
- "b_bus_suspend_tmout = \t%d\n"
- "b_bus_suspend_vld = \t%d\n",
- otg_state_string(iotg->otg.state),
- iotg->hsm.a_bus_resume,
- iotg->hsm.a_bus_suspend,
- iotg->hsm.a_conn,
- iotg->hsm.a_sess_vld,
- iotg->hsm.a_srp_det,
- iotg->hsm.a_vbus_vld,
- iotg->hsm.b_bus_resume,
- iotg->hsm.b_bus_suspend,
- iotg->hsm.b_conn,
- iotg->hsm.b_se0_srp,
- iotg->hsm.b_sess_end,
- iotg->hsm.b_sess_vld,
- iotg->hsm.id,
- iotg->hsm.a_set_b_hnp_en,
- iotg->hsm.b_srp_done,
- iotg->hsm.b_hnp_enable,
- iotg->hsm.a_wait_vrise_tmout,
- iotg->hsm.a_wait_bcon_tmout,
- iotg->hsm.a_aidl_bdis_tmout,
- iotg->hsm.b_ase0_brst_tmout,
- iotg->hsm.a_bus_drop,
- iotg->hsm.a_bus_req,
- iotg->hsm.a_clr_err,
- iotg->hsm.a_suspend_req,
- iotg->hsm.b_bus_req,
- iotg->hsm.b_bus_suspend_tmout,
- iotg->hsm.b_bus_suspend_vld
- );
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.a_bus_req = 0;
- dev_dbg(lnw->dev, "User request: a_bus_req = 0\n");
- } else if (buf[0] == '1') {
- /* If a_bus_drop is TRUE, a_bus_req can't be set */
- if (iotg->hsm.a_bus_drop)
- return -1;
- iotg->hsm.a_bus_req = 1;
- dev_dbg(lnw->dev, "User request: a_bus_req = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.a_bus_drop = 0;
- dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n");
- } else if (buf[0] == '1') {
- iotg->hsm.a_bus_drop = 1;
- iotg->hsm.a_bus_req = 0;
- dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n");
- dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop);
-
-static ssize_t
-get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_b_bus_req(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (iotg->otg.default_a)
- return -1;
-
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.b_bus_req = 0;
- dev_dbg(lnw->dev, "User request: b_bus_req = 0\n");
- } else if (buf[0] == '1') {
- iotg->hsm.b_bus_req = 1;
- dev_dbg(lnw->dev, "User request: b_bus_req = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '1') {
- iotg->hsm.a_clr_err = 1;
- dev_dbg(lnw->dev, "User request: a_clr_err = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
-
-static struct attribute *inputs_attrs[] = {
- &dev_attr_a_bus_req.attr,
- &dev_attr_a_bus_drop.attr,
- &dev_attr_b_bus_req.attr,
- &dev_attr_a_clr_err.attr,
- NULL,
-};
-
-static struct attribute_group debug_dev_attr_group = {
- .name = "inputs",
- .attrs = inputs_attrs,
-};
-
-static int langwell_otg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- unsigned long resource, len;
- void __iomem *base = NULL;
- int retval;
- u32 val32;
- struct langwell_otg *lnw;
- char qname[] = "langwell_otg_queue";
-
- retval = 0;
- dev_dbg(&pdev->dev, "\notg controller is detected.\n");
- if (pci_enable_device(pdev) < 0) {
- retval = -ENODEV;
- goto done;
- }
-
- lnw = kzalloc(sizeof *lnw, GFP_KERNEL);
- if (lnw == NULL) {
- retval = -ENOMEM;
- goto done;
- }
- the_transceiver = lnw;
-
- /* control register: BAR 0 */
- resource = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
- if (!request_mem_region(resource, len, driver_name)) {
- retval = -EBUSY;
- goto err;
- }
- lnw->region = 1;
-
- base = ioremap_nocache(resource, len);
- if (base == NULL) {
- retval = -EFAULT;
- goto err;
- }
- lnw->iotg.base = base;
-
- if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) {
- retval = -EBUSY;
- goto err;
- }
- lnw->cfg_region = 1;
-
- /* For the SCCB.USBCFG register */
- base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN);
- if (base == NULL) {
- retval = -EFAULT;
- goto err;
- }
- lnw->usbcfg = base;
-
- if (!pdev->irq) {
- dev_dbg(&pdev->dev, "No IRQ.\n");
- retval = -ENODEV;
- goto err;
- }
-
- lnw->qwork = create_singlethread_workqueue(qname);
- if (!lnw->qwork) {
- dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname);
- retval = -ENOMEM;
- goto err;
- }
- INIT_WORK(&lnw->work, langwell_otg_work);
-
- /* OTG common part */
- lnw->dev = &pdev->dev;
- lnw->iotg.otg.dev = lnw->dev;
- lnw->iotg.otg.label = driver_name;
- lnw->iotg.otg.set_host = langwell_otg_set_host;
- lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral;
- lnw->iotg.otg.set_power = langwell_otg_set_power;
- lnw->iotg.otg.set_vbus = langwell_otg_set_vbus;
- lnw->iotg.otg.start_srp = langwell_otg_start_srp;
- lnw->iotg.otg.state = OTG_STATE_UNDEFINED;
-
- if (otg_set_transceiver(&lnw->iotg.otg)) {
- dev_dbg(lnw->dev, "can't set transceiver\n");
- retval = -EBUSY;
- goto err;
- }
-
- reset_otg();
- init_hsm();
-
- spin_lock_init(&lnw->lock);
- spin_lock_init(&lnw->wq_lock);
- INIT_LIST_HEAD(&active_timers);
- retval = langwell_otg_init_timers(&lnw->iotg.hsm);
- if (retval) {
- dev_dbg(&pdev->dev, "Failed to init timers\n");
- goto err;
- }
-
- init_timer(&lnw->hsm_timer);
- ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier);
-
- lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify;
-
- retval = intel_mid_otg_register_notifier(&lnw->iotg,
- &lnw->iotg_notifier);
- if (retval) {
- dev_dbg(lnw->dev, "Failed to register notifier\n");
- goto err;
- }
-
- if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
- driver_name, lnw) != 0) {
- dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq);
- retval = -EBUSY;
- goto err;
- }
-
- /* enable OTGSC int */
- val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
- OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
- writel(val32, lnw->iotg.base + CI_OTGSC);
-
- retval = device_create_file(&pdev->dev, &dev_attr_registers);
- if (retval < 0) {
- dev_dbg(lnw->dev,
- "Can't register sysfs attribute: %d\n", retval);
- goto err;
- }
-
- retval = device_create_file(&pdev->dev, &dev_attr_hsm);
- if (retval < 0) {
- dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval);
- goto err;
- }
-
- retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
- if (retval < 0) {
- dev_dbg(lnw->dev,
- "Can't register sysfs attr group: %d\n", retval);
- goto err;
- }
-
- if (lnw->iotg.otg.state == OTG_STATE_A_IDLE)
- langwell_update_transceiver();
-
- return 0;
-
-err:
- if (the_transceiver)
- langwell_otg_remove(pdev);
-done:
- return retval;
-}
-
-static void langwell_otg_remove(struct pci_dev *pdev)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- if (lnw->qwork) {
- flush_workqueue(lnw->qwork);
- destroy_workqueue(lnw->qwork);
- }
- intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier);
- langwell_otg_free_timers();
-
- /* disable OTGSC interrupt as OTGSC doesn't change in reset */
- writel(0, lnw->iotg.base + CI_OTGSC);
-
- if (pdev->irq)
- free_irq(pdev->irq, lnw);
- if (lnw->usbcfg)
- iounmap(lnw->usbcfg);
- if (lnw->cfg_region)
- release_mem_region(USBCFG_ADDR, USBCFG_LEN);
- if (lnw->iotg.base)
- iounmap(lnw->iotg.base);
- if (lnw->region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
-
- otg_set_transceiver(NULL);
- pci_disable_device(pdev);
- sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
- device_remove_file(&pdev->dev, &dev_attr_hsm);
- device_remove_file(&pdev->dev, &dev_attr_registers);
- kfree(lnw);
- lnw = NULL;
-}
-
-static void transceiver_suspend(struct pci_dev *pdev)
-{
- pci_save_state(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
- langwell_otg_phy_low_power(1);
-}
-
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- int ret = 0;
-
- /* Disbale OTG interrupts */
- langwell_otg_intr(0);
-
- if (pdev->irq)
- free_irq(pdev->irq, lnw);
-
- /* Prevent more otg_work */
- flush_workqueue(lnw->qwork);
- destroy_workqueue(lnw->qwork);
- lnw->qwork = NULL;
-
- /* start actions */
- switch (iotg->otg.state) {
- case OTG_STATE_A_WAIT_VFALL:
- iotg->otg.state = OTG_STATE_A_IDLE;
- case OTG_STATE_A_IDLE:
- case OTG_STATE_B_IDLE:
- case OTG_STATE_A_VBUS_ERR:
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_WAIT_VRISE:
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_WAIT_BCON:
- del_timer_sync(&lnw->hsm_timer);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_HOST:
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
-
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_SUSPEND:
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev, "host driver has been removed.\n");
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_PERIPHERAL:
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(&pdev->dev,
- "client driver has been removed.\n");
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_HOST:
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
- iotg->hsm.b_bus_req = 0;
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(&pdev->dev,
- "client driver has been removed.\n");
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_WAIT_ACON:
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
- iotg->hsm.b_bus_req = 0;
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- default:
- dev_dbg(lnw->dev, "error state before suspend\n");
- break;
- }
-
- return ret;
-}
-
-static void transceiver_resume(struct pci_dev *pdev)
-{
- pci_restore_state(pdev);
- pci_set_power_state(pdev, PCI_D0);
-}
-
-static int langwell_otg_resume(struct pci_dev *pdev)
-{
- struct langwell_otg *lnw = the_transceiver;
- int ret = 0;
-
- transceiver_resume(pdev);
-
- lnw->qwork = create_singlethread_workqueue("langwell_otg_queue");
- if (!lnw->qwork) {
- dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen");
- ret = -ENOMEM;
- goto error;
- }
-
- if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
- driver_name, lnw) != 0) {
- dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq);
- ret = -EBUSY;
- goto error;
- }
-
- /* enable OTG interrupts */
- langwell_otg_intr(1);
-
- update_hsm();
-
- langwell_update_transceiver();
-
- return ret;
-error:
- langwell_otg_intr(0);
- transceiver_suspend(pdev);
- return ret;
-}
-
-static int __init langwell_otg_init(void)
-{
- return pci_register_driver(&otg_pci_driver);
-}
-module_init(langwell_otg_init);
-
-static void __exit langwell_otg_cleanup(void)
-{
- pci_unregister_driver(&otg_pci_driver);
-}
-module_exit(langwell_otg_cleanup);
static void mv_otg_start_host(struct mv_otg *mvotg, int on)
{
+#ifdef CONFIG_USB
struct otg_transceiver *otg = &mvotg->otg;
struct usb_hcd *hcd;
usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
else
usb_remove_hcd(hcd);
+#endif /* CONFIG_USB */
}
static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
struct usbhs_pipe *pipe;
int recip = ctrl->bRequestType & USB_RECIP_MASK;
int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
- int ret;
+ int ret = 0;
int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
struct usb_ctrlrequest *ctrl);
char *msg;
struct usb_serial_port *port);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
+static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
static int cp210x_tiocmget(struct tty_struct *);
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1D
+#define CP210X_SET_BAUDRATE 0x1E
/* CP210X_IFC_ENABLE */
#define UART_ENABLE 0x0001
* Quantises the baud rate as per AN205 Table 1
*/
static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
- if (baud <= 56) baud = 0;
- else if (baud <= 300) baud = 300;
+ if (baud <= 300)
+ baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
- else if (baud <= 1053257) baud = 921600;
- else if (baud <= 1474560) baud = 1228800;
- else if (baud <= 2457600) baud = 1843200;
- else baud = 3686400;
+ else if (baud < 1000000)
+ baud = 921600;
+ else if (baud > 2000000)
+ baud = 2000000;
return baud;
}
return result;
}
- result = usb_serial_generic_open(tty, port);
- if (result)
- return result;
-
/* Configure the termios structure */
cp210x_get_termios(tty, port);
- return 0;
+
+ /* The baud rate must be initialised on cp2104 */
+ if (tty)
+ cp210x_change_speed(tty, port, NULL);
+
+ return usb_serial_generic_open(tty, port);
}
static void cp210x_close(struct usb_serial_port *port)
dbg("%s - port %d", __func__, port->number);
- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
- baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
dbg("%s - baud rate = %d", __func__, baud);
*baudp = baud;
*cflagp = cflag;
}
+/*
+ * CP2101 supports the following baud rates:
+ *
+ * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
+ * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
+ *
+ * CP2102 and CP2103 support the following additional rates:
+ *
+ * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
+ * 576000
+ *
+ * The device will map a requested rate to a supported one, but the result
+ * of requests for rates greater than 1053257 is undefined (see AN205).
+ *
+ * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
+ * respectively, with an error less than 1%. The actual rates are determined
+ * by
+ *
+ * div = round(freq / (2 x prescale x request))
+ * actual = freq / (2 x prescale x div)
+ *
+ * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
+ * or 1 otherwise.
+ * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
+ * otherwise.
+ */
+static void cp210x_change_speed(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ u32 baud;
+
+ baud = tty->termios->c_ospeed;
+
+ /* This maps the requested rate to a rate valid on cp2102 or cp2103,
+ * or to an arbitrary rate in [1M,2M].
+ *
+ * NOTE: B0 is not implemented.
+ */
+ baud = cp210x_quantise_baudrate(baud);
+
+ dbg("%s - setting baud rate to %u", __func__, baud);
+ if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
+ sizeof(baud))) {
+ dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
+ if (old_termios)
+ baud = old_termios->c_ospeed;
+ else
+ baud = 9600;
+ }
+
+ tty_encode_baud_rate(tty, baud, baud);
+}
+
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
- unsigned int baud = 0, bits;
+ unsigned int bits;
unsigned int modem_ctl[4];
dbg("%s - port %d", __func__, port->number);
cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
- baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty));
-
- /* If the baud rate is to be updated*/
- if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
- dbg("%s - Setting baud rate to %d baud", __func__,
- baud);
- if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
- ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
- dbg("Baud rate requested not supported by device");
- baud = tty_termios_baud_rate(old_termios);
- }
- }
- /* Report back the resulting baud rate */
- tty_encode_baud_rate(tty, baud, baud);
+
+ if (tty->termios->c_ospeed != old_termios->c_ospeed)
+ cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
goto check_and_exit;
}
- if ((new_serial.baud_base != priv->baud_base) &&
- (new_serial.baud_base < 9600)) {
+ if (new_serial.baud_base != priv->baud_base) {
mutex_unlock(&priv->cfg_lock);
return -EINVAL;
}
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct ktermios dummy;
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int result;
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
- if (tty)
- ftdi_set_termios(tty, port, tty->termios);
+ if (tty) {
+ memset(&dummy, 0, sizeof(dummy));
+ ftdi_set_termios(tty, port, &dummy);
+ }
/* Start reading from the device */
result = usb_serial_generic_open(tty, port);
/* www.candapter.com Ewert Energy Systems CANdapter device */
#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+/*
+ * Texas Instruments XDS100v2 JTAG / BeagleBone A3
+ * http://processors.wiki.ti.com/index.php/XDS100
+ * http://beagleboard.org/bone
+ */
+#define TI_XDS100V2_PID 0xa6d0
+
#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */
/* US Interface Navigator (http://www.usinterface.com/) */
#define ADI_GNICE_PID 0xF000
#define ADI_GNICEPLUS_PID 0xF001
+/*
+ * Hornby Elite
+ */
+#define HORNBY_VID 0x04D8
+#define HORNBY_ELITE_PID 0x000A
+
/*
* RATOC REX-USB60F
*/
*/
/* TagTracer MIFARE*/
#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
+
+/*
+ * Rainforest Automation
+ */
+/* ZigBee controller */
+#define FTDI_RF_R106 0x8A28
static void edge_disconnect(struct usb_serial *serial)
{
- int i;
- struct edgeport_port *edge_port;
-
dbg("%s", __func__);
-
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- edge_remove_sysfs_attrs(edge_port->port);
- }
}
static void edge_release(struct usb_serial *serial)
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
#include <linux/ioctl.h>
#include "kobil_sct.h"
-static int debug;
+static bool debug;
/* Version Information */
#define DRIVER_VERSION "21/05/2004"
#define ZD_VENDOR_ID 0x0685
#define ZD_PRODUCT_7000 0x7000
+/* LG products */
+#define LG_VENDOR_ID 0x1004
+#define LG_PRODUCT_L02C 0x618f
+
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0,
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
#define UTSTARCOM_PRODUCT_UM175_V1 0x3712
#define UTSTARCOM_PRODUCT_UM175_V2 0x3714
#define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715
+#define PANTECH_PRODUCT_UML190_VZW 0x3716
#define PANTECH_PRODUCT_UML290_VZW 0x3718
/* CMOTECH devices */
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
rts51x_set_stat(chip, RTS51X_STAT_SS);
/* ignore mass storage interface's children */
pm_suspend_ignore_children(&us->pusb_intf->dev, true);
- usb_autopm_put_interface(us->pusb_intf);
+ usb_autopm_put_interface_async(us->pusb_intf);
US_DEBUGP("%s: RTS51X_STAT_SS 01,"
"intf->pm_usage_cnt:%d, power.usage:%d\n",
__func__,
#define USB_SKEL_VENDOR_ID 0xfff0
#define USB_SKEL_PRODUCT_ID 0xfff0
-static DEFINE_MUTEX(skel_mutex);
-
/* table of devices that work with this driver */
static const struct usb_device_id skel_table[] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
goto exit;
}
- mutex_lock(&skel_mutex);
dev = usb_get_intfdata(interface);
if (!dev) {
- mutex_unlock(&skel_mutex);
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
- mutex_unlock(&skel_mutex);
/* lock the device to allow correctly handling errors
* in resumption */
mutex_lock(&dev->io_mutex);
- if (!dev->interface) {
- retval = -ENODEV;
- goto out_err;
- }
retval = usb_autopm_get_interface(interface);
if (retval)
/* save our object in the file's private structure */
file->private_data = dev;
-
-out_err:
mutex_unlock(&dev->io_mutex);
- if (retval)
- kref_put(&dev->kref, skel_delete);
exit:
return retval;
int minor = interface->minor;
dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &skel_class);
usb_kill_anchored_urbs(&dev->submitted);
- mutex_lock(&skel_mutex);
- usb_set_intfdata(interface, NULL);
-
/* decrement our usage count */
kref_put(&dev->kref, skel_delete);
- mutex_unlock(&skel_mutex);
dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
}
depends on EXPERIMENTAL
depends on USB
depends on PCI
- select UWB
+ depends on UWB
select CRYPTO
select CRYPTO_BLKCIPHER
select CRYPTO_CBC
ret = adp8860_read(client, reg, ®_val);
- if (!ret && ((reg_val & bit_mask) == 0)) {
+ if (!ret && ((reg_val & bit_mask) != bit_mask)) {
reg_val |= bit_mask;
ret = adp8860_write(client, reg, reg_val);
}
ret = adp8870_read(client, reg, ®_val);
- if (!ret && ((reg_val & bit_mask) == 0)) {
+ if (!ret && ((reg_val & bit_mask) != bit_mask)) {
reg_val |= bit_mask;
ret = adp8870_write(client, reg, reg_val);
}
priv->io_reg = regulator_get(&spi->dev, "vdd");
if (IS_ERR(priv->io_reg)) {
+ ret = PTR_ERR(priv->io_reg);
dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
__func__);
goto err3;
priv->core_reg = regulator_get(&spi->dev, "vcore");
if (IS_ERR(priv->core_reg)) {
+ ret = PTR_ERR(priv->core_reg);
dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
__func__);
goto err4;
if (!fb_info.screen_base)
return -ENODEV;
- printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
- macfb_fix.smem_start, fb_info.screen_base,
- macfb_fix.smem_len / 1024);
- printk("macfb: mode is %dx%dx%d, linelength=%d\n",
- macfb_defined.xres, macfb_defined.yres,
- macfb_defined.bits_per_pixel, macfb_fix.line_length);
+ pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
+ macfb_fix.smem_start, fb_info.screen_base,
+ macfb_fix.smem_len / 1024);
+ pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
+ macfb_defined.xres, macfb_defined.yres,
+ macfb_defined.bits_per_pixel, macfb_fix.line_length);
/* Fill in the available video resolution */
macfb_defined.xres_virtual = macfb_defined.xres;
switch (macfb_defined.bits_per_pixel) {
case 1:
- /*
- * XXX: I think this will catch any program that tries
- * to do FBIO_PUTCMAP when the visual is monochrome.
- */
macfb_defined.red.length = macfb_defined.bits_per_pixel;
macfb_defined.green.length = macfb_defined.bits_per_pixel;
macfb_defined.blue.length = macfb_defined.bits_per_pixel;
- video_cmap_len = 0;
+ video_cmap_len = 2;
macfb_fix.visual = FB_VISUAL_MONO01;
break;
case 2:
macfb_fix.visual = FB_VISUAL_TRUECOLOR;
break;
default:
- video_cmap_len = 0;
- macfb_fix.visual = FB_VISUAL_MONO01;
- printk("macfb: unknown or unsupported bit depth: %d\n",
+ pr_err("macfb: unknown or unsupported bit depth: %d\n",
macfb_defined.bits_per_pixel);
- break;
+ err = -EINVAL;
+ goto fail_unmap;
}
/*
case MAC_MODEL_Q950:
strcpy(macfb_fix.id, "DAFB");
macfb_setpalette = dafb_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
case MAC_MODEL_LCII:
strcpy(macfb_fix.id, "V8");
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
case MAC_MODEL_P600:
strcpy(macfb_fix.id, "Brazil");
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
case MAC_MODEL_P520:
case MAC_MODEL_P550:
case MAC_MODEL_P460:
- macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "Sonora");
+ macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
*/
case MAC_MODEL_IICI:
case MAC_MODEL_IISI:
- macfb_setpalette = rbv_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "RBV");
+ macfb_setpalette = rbv_setpalette;
rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
*/
case MAC_MODEL_Q840:
case MAC_MODEL_C660:
- macfb_setpalette = civic_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "Civic");
+ macfb_setpalette = civic_setpalette;
civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
* We think this may be like the LC II
*/
case MAC_MODEL_LC:
+ strcpy(macfb_fix.id, "LC");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
}
- strcpy(macfb_fix.id, "LC");
break;
/*
* We think this may be like the LC II
*/
case MAC_MODEL_CCL:
+ strcpy(macfb_fix.id, "Color Classic");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
}
- strcpy(macfb_fix.id, "Color Classic");
break;
/*
case MAC_MODEL_PB270C:
case MAC_MODEL_PB280:
case MAC_MODEL_PB280C:
- macfb_setpalette = csc_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "CSC");
+ macfb_setpalette = csc_setpalette;
csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
default:
if (err)
goto fail_dealloc;
- printk("fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ pr_info("fb%d: %s frame buffer device\n",
+ fb_info.node, fb_info.fix.id);
+
return 0;
fail_dealloc:
#define virtio_rmb(vq) \
do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
#define virtio_wmb(vq) \
- do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
+ do { if ((vq)->weak_barriers) smp_wmb(); else wmb(); } while(0)
#else
/* We must force memory ordering even if guest is UP since host could be
* running on another CPU, but SMP barriers are defined to barrier() in that
bool needs_kick;
START_USE(vq);
- /* Descriptors and available array need to be set before we expose the
- * new available array entries. */
- virtio_wmb(vq);
+ /* We need to expose available array entries before checking avail
+ * event. */
+ virtio_mb(vq);
old = vq->vring.avail->idx - vq->num_added;
new = vq->vring.avail->idx;
if (!mem)
return -EINVAL;
- if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
- "dw_wdt"))
- return -ENOMEM;
-
- dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ dw_wdt.regs = devm_request_and_ioremap(&pdev->dev, mem);
if (!dw_wdt.regs)
return -ENOMEM;
* document number TBD : Patsburg (PBG)
* document number TBD : DH89xxCC
* document number TBD : Panther Point
+ * document number TBD : Lynx Point
*/
/*
TCO_PBG, /* Patsburg */
TCO_DH89XXCC, /* DH89xxCC */
TCO_PPT, /* Panther Point */
+ TCO_LPT, /* Lynx Point */
};
static struct {
{"Patsburg", 2},
{"DH89xxCC", 2},
{"Panther Point", 2},
+ {"Lynx Point", 2},
{NULL, 0}
};
{ PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT},
{ PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT},
{ PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT},
+ { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
static int __init imx2_wdt_probe(struct platform_device *pdev)
{
int ret;
- int res_size;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
return -ENODEV;
}
- res_size = resource_size(res);
- if (!devm_request_mem_region(&pdev->dev, res->start, res_size,
- res->name)) {
- dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
- res_size, res->start);
- return -ENOMEM;
- }
-
- imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size);
+ imx2_wdt.base = devm_request_and_ioremap(&pdev->dev, res);
if (!imx2_wdt.base) {
dev_err(&pdev->dev, "ioremap failed\n");
return -ENOMEM;
};
static unsigned long nuc900wdt_busy;
-struct nuc900_wdt *nuc900_wdt;
+static struct nuc900_wdt *nuc900_wdt;
static inline void nuc900_wdt_keepalive(void)
{
setup_timer(&nuc900_wdt->timer, nuc900_wdt_timer_ping, 0);
- if (misc_register(&nuc900wdt_miscdev)) {
+ ret = misc_register(&nuc900wdt_miscdev);
+ if (ret) {
dev_err(&pdev->dev, "err register miscdev on minor=%d (%d)\n",
WATCHDOG_MINOR, ret);
goto err_clk;
return 0;
err_misc:
+ pm_runtime_disable(wdev->dev);
platform_set_drvdata(pdev, NULL);
iounmap(wdev->base);
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pm_runtime_disable(wdev->dev);
if (!res)
return -ENOENT;
static int pnx4008_wdt_release(struct inode *inode, struct file *file)
{
if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
- printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");
+ printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n");
wdt_disable();
clk_disable(wdt_clk);
if (!nowayout) {
if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
wdt_ping();
- pr_debug("%s: Device closed unexpectdly\n", __func__);
+ pr_debug("%s: Device closed unexpectedly\n", __func__);
ret = -EINVAL;
} else {
wdt_disable();
static int wdt_set_timeout(struct watchdog_device *wdd,
unsigned int new_timeout)
{
- if (new_timeout < 1 || new_timeout > WDT_TIMEOUT_MAX)
- return -EINVAL;
writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
timeout = new_timeout;
return 0;
static struct watchdog_device wdt_dev = {
.info = &wdt_info,
.ops = &wdt_ops,
+ .min_timeout = 1,
+ .max_timeout = WDT_TIMEOUT_MAX,
};
static int __devinit wdt_probe(struct pci_dev *pdev,
pci_disable_device(pdev);
}
-DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
+static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
- wafwdt_start();
+ wafwdt_stop();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
- wafwdt_stop();
+ wafwdt_start();
retval = 0;
}
/* Setting both simultaneously means at least one must fail */
if (options == WDIOS_DISABLECARD)
- ret = wm8350_wdt_start(wm8350);
+ ret = wm8350_wdt_stop(wm8350);
if (options == WDIOS_ENABLECARD)
- ret = wm8350_wdt_stop(wm8350);
+ ret = wm8350_wdt_start(wm8350);
break;
}
int rc;
struct gnttab_set_version gsv;
- gsv.version = 2;
+ if (xen_hvm_domain())
+ gsv.version = 1;
+ else
+ gsv.version = 2;
rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
- if (rc == 0) {
+ if (rc == 0 && gsv.version == 2) {
grant_table_version = 2;
gnttab_interface = &gnttab_v2_ops;
} else if (grant_table_version == 2) {
struct btrfs_delayed_extent_op *extent_op = head->extent_op;
struct rb_node *n = &head->node.rb_node;
int sgn;
- int ret;
+ int ret = 0;
if (extent_op && extent_op->update_key)
btrfs_disk_key_to_cpu(info_key, &extent_op->key);
struct btrfs_key *info_key, int *info_level,
struct list_head *prefs)
{
- int ret;
+ int ret = 0;
int slot;
struct extent_buffer *leaf;
struct btrfs_key key;
block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr,
&state->block_hashtable);
if (NULL != block) {
- u64 bytenr;
+ u64 bytenr = 0;
struct list_head *elem_ref_to;
struct list_head *tmp_ref_to;
printk(KERN_INFO
"submit_bh(rw=0x%x, blocknr=%lu (bytenr %llu),"
" size=%lu, data=%p, bdev=%p)\n",
- rw, bh->b_blocknr,
- (unsigned long long)dev_bytenr, bh->b_size,
- bh->b_data, bh->b_bdev);
+ rw, (unsigned long)bh->b_blocknr,
+ (unsigned long long)dev_bytenr,
+ (unsigned long)bh->b_size, bh->b_data,
+ bh->b_bdev);
btrfsic_process_written_block(dev_state, dev_bytenr,
bh->b_data, bh->b_size, NULL,
NULL, bh, rw);
printk(KERN_INFO
"submit_bio(rw=0x%x, bi_vcnt=%u,"
" bi_sector=%lu (bytenr %llu), bi_bdev=%p)\n",
- rw, bio->bi_vcnt, bio->bi_sector,
+ rw, bio->bi_vcnt, (unsigned long)bio->bi_sector,
(unsigned long long)dev_bytenr,
bio->bi_bdev);
tree = &BTRFS_I(page->mapping->host)->io_tree;
map = &BTRFS_I(page->mapping->host)->extent_tree;
+ /*
+ * We need to mask out eg. __GFP_HIGHMEM and __GFP_DMA32 as we're doing
+ * slab allocation from alloc_extent_state down the callchain where
+ * it'd hit a BUG_ON as those flags are not allowed.
+ */
+ gfp_flags &= ~GFP_SLAB_BUG_MASK;
+
ret = try_release_extent_state(map, tree, page, gfp_flags);
if (!ret)
return 0;
#include "locking.h"
#include "free-space-cache.h"
-/* control flags for do_chunk_alloc's force field
+/*
+ * control flags for do_chunk_alloc's force field
* CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
* if we really need one.
*
- * CHUNK_ALLOC_FORCE means it must try to allocate one
- *
* CHUNK_ALLOC_LIMITED means to only try and allocate one
* if we have very few chunks already allocated. This is
* used as part of the clustering code to help make sure
* we have a good pool of storage to cluster in, without
* filling the FS with empty chunks
*
+ * CHUNK_ALLOC_FORCE means it must try to allocate one
+ *
*/
enum {
CHUNK_ALLOC_NO_FORCE = 0,
- CHUNK_ALLOC_FORCE = 1,
- CHUNK_ALLOC_LIMITED = 2,
+ CHUNK_ALLOC_LIMITED = 1,
+ CHUNK_ALLOC_FORCE = 2,
};
/*
again:
spin_lock(&space_info->lock);
- if (space_info->force_alloc)
+ if (force < space_info->force_alloc)
force = space_info->force_alloc;
if (space_info->full) {
spin_unlock(&space_info->lock);
u64 search_end, struct btrfs_key *ins,
u64 data)
{
+ bool final_tried = false;
int ret;
u64 search_start = 0;
search_start, search_end, hint_byte,
ins, data);
- if (ret == -ENOSPC && num_bytes > min_alloc_size) {
- num_bytes = num_bytes >> 1;
- num_bytes = num_bytes & ~(root->sectorsize - 1);
- num_bytes = max(num_bytes, min_alloc_size);
- do_chunk_alloc(trans, root->fs_info->extent_root,
- num_bytes, data, CHUNK_ALLOC_FORCE);
- goto again;
- }
- if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
- struct btrfs_space_info *sinfo;
-
- sinfo = __find_space_info(root->fs_info, data);
- printk(KERN_ERR "btrfs allocation failed flags %llu, "
- "wanted %llu\n", (unsigned long long)data,
- (unsigned long long)num_bytes);
- dump_space_info(sinfo, num_bytes, 1);
+ if (ret == -ENOSPC) {
+ if (!final_tried) {
+ num_bytes = num_bytes >> 1;
+ num_bytes = num_bytes & ~(root->sectorsize - 1);
+ num_bytes = max(num_bytes, min_alloc_size);
+ do_chunk_alloc(trans, root->fs_info->extent_root,
+ num_bytes, data, CHUNK_ALLOC_FORCE);
+ if (num_bytes == min_alloc_size)
+ final_tried = true;
+ goto again;
+ } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+ struct btrfs_space_info *sinfo;
+
+ sinfo = __find_space_info(root->fs_info, data);
+ printk(KERN_ERR "btrfs allocation failed flags %llu, "
+ "wanted %llu\n", (unsigned long long)data,
+ (unsigned long long)num_bytes);
+ dump_space_info(sinfo, num_bytes, 1);
+ }
}
trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
while (start <= end) {
index = start >> PAGE_CACHE_SHIFT;
page = find_get_page(tree->mapping, index);
+ if (!page)
+ return 1;
uptodate = PageUptodate(page);
page_cache_release(page);
if (!uptodate) {
if (entry->bitmap) {
ret = btrfs_alloc_from_bitmap(block_group,
cluster, entry, bytes,
- min_start);
+ cluster->window_start);
if (ret == 0) {
node = rb_next(&entry->offset_index);
if (!node)
offset_index);
continue;
}
+ cluster->window_start += bytes;
} else {
ret = entry->offset;
}
list_for_each_entry(entry, bitmaps, list) {
- if (entry->bytes < min_bytes)
+ if (entry->bytes < bytes)
continue;
ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
bytes, cont1_bytes, min_bytes);
unsigned long zero_start;
loff_t size;
int ret;
+ int reserved = 0;
u64 page_start;
u64 page_end;
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
- if (!ret)
+ if (!ret) {
ret = btrfs_update_time(vma->vm_file);
+ reserved = 1;
+ }
if (ret) {
if (ret == -ENOMEM)
ret = VM_FAULT_OOM;
else /* -ENOSPC, -EIO, etc */
ret = VM_FAULT_SIGBUS;
- goto out;
+ if (reserved)
+ goto out;
+ goto out_noreserve;
}
ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
unlock_page(page);
out:
btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
+out_noreserve:
return ret;
}
i = range->start >> PAGE_CACHE_SHIFT;
}
if (!max_to_defrag)
- max_to_defrag = last_index;
+ max_to_defrag = last_index + 1;
/*
* make writeback starts from i, so the defrag range can be
finish_wait(&root->log_commit_wait[index], &wait);
mutex_lock(&root->log_mutex);
- } while (root->log_transid < transid + 2 &&
+ } while (root->fs_info->last_trans_log_full_commit !=
+ trans->transid && root->log_transid < transid + 2 &&
atomic_read(&root->log_commit[index]));
return 0;
}
struct btrfs_root *root)
{
DEFINE_WAIT(wait);
- while (atomic_read(&root->log_writers)) {
+ while (root->fs_info->last_trans_log_full_commit !=
+ trans->transid && atomic_read(&root->log_writers)) {
prepare_to_wait(&root->log_writer_wait,
&wait, TASK_UNINTERRUPTIBLE);
mutex_unlock(&root->log_mutex);
config CIFS_FSCACHE
bool "Provide CIFS client caching support (EXPERIMENTAL)"
- depends on EXPERIMENTAL
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
help
Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
config CIFS_ACL
bool "Provide CIFS ACL support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && CIFS_XATTR && KEYS
+ depends on CIFS_XATTR && KEYS
help
Allows to fetch CIFS/NTFS ACL from the server. The DACL blob
is handed over to the application/caller.
{
char c;
int rc;
+ static bool warned;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
multiuser_mount = 0;
- else if (c == '1' || c == 'y' || c == 'Y')
+ else if (c == '1' || c == 'y' || c == 'Y') {
multiuser_mount = 1;
+ if (!warned) {
+ warned = true;
+ printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
+ "mount code is scheduled to be deprecated in "
+ "3.5. Please switch to using the multiuser "
+ "mount option.");
+ }
+ }
return count;
}
MAX_MECH_STR_LEN +
UID_KEY_LEN + (sizeof(uid_t) * 2) +
CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
- USER_KEY_LEN + strlen(sesInfo->user_name) +
PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
+ if (sesInfo->user_name)
+ desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
+
spnego_key = ERR_PTR(-ENOMEM);
description = kzalloc(desc_len, GFP_KERNEL);
if (description == NULL)
dp = description + strlen(description);
sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
- dp = description + strlen(description);
- sprintf(dp, ";user=%s", sesInfo->user_name);
+ if (sesInfo->user_name) {
+ dp = description + strlen(description);
+ sprintf(dp, ";user=%s", sesInfo->user_name);
+ }
dp = description + strlen(description);
sprintf(dp, ";pid=0x%x", current->pid);
#include "cifs_debug.h"
/*
- * cifs_ucs2_bytes - how long will a string be after conversion?
- * @ucs - pointer to input string
+ * cifs_utf16_bytes - how long will a string be after conversion?
+ * @utf16 - pointer to input string
* @maxbytes - don't go past this many bytes of input string
* @codepage - destination codepage
*
- * Walk a ucs2le string and return the number of bytes that the string will
+ * Walk a utf16le string and return the number of bytes that the string will
* be after being converted to the given charset, not including any null
* termination required. Don't walk past maxbytes in the source buffer.
*/
int
-cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+cifs_utf16_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage)
{
int i;
}
/*
- * cifs_from_ucs2 - convert utf16le string to local charset
+ * cifs_from_utf16 - convert utf16le string to local charset
* @to - destination buffer
* @from - source buffer
* @tolen - destination buffer size (in bytes)
* @codepage - codepage to which characters should be converted
* @mapchar - should characters be remapped according to the mapchars option?
*
- * Convert a little-endian ucs2le string (as sent by the server) to a string
+ * Convert a little-endian utf16le string (as sent by the server) to a string
* in the provided codepage. The tolen and fromlen parameters are to ensure
* that the code doesn't walk off of the end of the buffer (which is always
* a danger if the alignment of the source buffer is off). The destination
* null terminator).
*
* Note that some windows versions actually send multiword UTF-16 characters
- * instead of straight UCS-2. The linux nls routines however aren't able to
+ * instead of straight UTF16-2. The linux nls routines however aren't able to
* deal with those characters properly. In the event that we get some of
* those characters, they won't be translated properly.
*/
int
-cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *codepage, bool mapchar)
{
int i, charlen, safelen;
}
/*
- * NAME: cifs_strtoUCS()
+ * NAME: cifs_strtoUTF16()
*
* FUNCTION: Convert character string to unicode string
*
*/
int
-cifs_strtoUCS(__le16 *to, const char *from, int len,
+cifs_strtoUTF16(__le16 *to, const char *from, int len,
const struct nls_table *codepage)
{
int charlen;
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
charlen = codepage->char2uni(from, len, &wchar_to);
if (charlen < 1) {
- cERROR(1, "strtoUCS: char2uni of 0x%x returned %d",
+ cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d",
*from, charlen);
/* A question mark */
wchar_to = 0x003f;
}
/*
- * cifs_strndup_from_ucs - copy a string from wire format to the local codepage
+ * cifs_strndup_from_utf16 - copy a string from wire format to the local
+ * codepage
* @src - source string
* @maxlen - don't walk past this many bytes in the source string
* @is_unicode - is this a unicode string?
* error.
*/
char *
-cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
- const struct nls_table *codepage)
+cifs_strndup_from_utf16(const char *src, const int maxlen,
+ const bool is_unicode, const struct nls_table *codepage)
{
int len;
char *dst;
if (is_unicode) {
- len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
+ len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
len += nls_nullsize(codepage);
dst = kmalloc(len, GFP_KERNEL);
if (!dst)
return NULL;
- cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
+ cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
false);
} else {
len = strnlen(src, maxlen);
* names are little endian 16 bit Unicode on the wire
*/
int
-cifsConvertToUCS(__le16 *target, const char *source, int srclen,
+cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapChars)
{
int i, j, charlen;
wchar_t tmp;
if (!mapChars)
- return cifs_strtoUCS(target, source, PATH_MAX, cp);
+ return cifs_strtoUTF16(target, source, PATH_MAX, cp);
for (i = 0, j = 0; i < srclen; j++) {
src_char = source[i];
switch (src_char) {
case 0:
put_unaligned(0, &target[j]);
- goto ctoUCS_out;
+ goto ctoUTF16_out;
case ':':
dst_char = cpu_to_le16(UNI_COLON);
break;
put_unaligned(dst_char, &target[j]);
}
-ctoUCS_out:
+ctoUTF16_out:
return i;
}
#endif /* UNIUPR_NOLOWER */
#ifdef __KERNEL__
-int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
- const struct nls_table *codepage, bool mapchar);
-int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
- const struct nls_table *codepage);
-int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
-char *cifs_strndup_from_ucs(const char *src, const int maxlen,
- const bool is_unicode,
- const struct nls_table *codepage);
-extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
- const struct nls_table *cp, int mapChars);
+int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, bool mapchar);
+int cifs_utf16_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage);
+int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup_from_utf16(const char *src, const int maxlen,
+ const bool is_unicode,
+ const struct nls_table *codepage);
+extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
+ const struct nls_table *cp, int mapChars);
#endif
umode_t group_mask = S_IRWXG;
umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
+ if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
+ return;
ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
GFP_KERNEL);
if (!ppace) {
attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
attrptr->length = cpu_to_le16(2 * dlen);
blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
- cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+ cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
return 0;
}
kmalloc(attrsize + 1, GFP_KERNEL);
if (!ses->domainName)
return -ENOMEM;
- cifs_from_ucs2(ses->domainName,
+ cifs_from_utf16(ses->domainName,
(__le16 *)blobptr, attrsize, attrsize,
nls_cp, false);
break;
}
/* convert ses->user_name to unicode and uppercase */
- len = strlen(ses->user_name);
+ len = ses->user_name ? strlen(ses->user_name) : 0;
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL) {
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
rc = -ENOMEM;
return rc;
}
- len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
- UniStrupr(user);
+
+ if (len) {
+ len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp);
+ UniStrupr(user);
+ } else {
+ memset(user, '\0', 2);
+ }
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
(char *)user, 2 * len);
rc = -ENOMEM;
return rc;
}
- len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
- nls_cp);
+ len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
+ nls_cp);
rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
(char *)domain, 2 * len);
rc = -ENOMEM;
return rc;
}
- len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
+ len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
nls_cp);
rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
#define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */
#endif /* UPCALL */
#else /* do not allow weak pw hash */
+#define CIFSSEC_MUST_LANMAN 0
+#define CIFSSEC_MUST_PLNTXT 0
#ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
#else
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB add path length overrun check */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve check for buffer overruns BB */
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
- PATH_MAX, nls_codepage, remap);
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve check for buffer overruns BB */
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
- PATH_MAX, nls_codepage, remap);
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, name,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
count = 1; /* account for one byte pad to word boundary */
name_len =
- cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
- fileName, PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+ fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
count = 1; /* account for one byte pad to word boundary */
name_len =
- cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
- fileName, PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+ fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->NameLength = cpu_to_le16(name_len);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
- cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
- toName, PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+ toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
/* unicode only call */
if (target_name == NULL) {
sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
- len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+ len_of_str =
+ cifsConvertToUTF16((__le16 *)rename_info->target_name,
dummy_string, 24, nls_codepage, remap);
} else {
- len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+ len_of_str =
+ cifsConvertToUTF16((__le16 *)rename_info->target_name,
target_name, PATH_MAX, nls_codepage,
remap);
}
pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
- fromName, PATH_MAX, nls_codepage,
- remap);
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
+ fromName, PATH_MAX, nls_codepage,
+ remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
- cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
- toName, PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+ toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
- /* find define for this maxpathcomponent */
- , nls_codepage);
+ cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
+ /* find define for this maxpathcomponent */
+ PATH_MAX, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target =
- cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
- /* find define for this maxpathcomponent */
- , nls_codepage);
+ cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
name_len_target++; /* trailing null */
name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
- PATH_MAX, nls_codepage, remap);
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target =
- cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
- nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) data_offset, fromName,
+ PATH_MAX, nls_codepage, remap);
name_len_target++; /* trailing null */
name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0x04;
pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
name_len2 =
- cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
- toName, PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+ toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage);
+ cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
is_unicode = false;
/* BB FIXME investigate remapping reserved chars here */
- *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
- is_unicode, nls_codepage);
+ *symlinkinfo = cifs_strndup_from_utf16(data_start,
+ count, is_unicode, nls_codepage);
if (!*symlinkinfo)
rc = -ENOMEM;
}
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ searchName, PATH_MAX, nls_codepage,
+ remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->FileName[name_len] = 0;
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ searchName, PATH_MAX, nls_codepage,
+ remap);
name_len++; /* trailing null */
name_len *= 2;
} else {
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
/* We can not add the asterik earlier in case
it got remapped to 0xF03A as if it were part of the
directory name instead of a wildcard */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ searchName, PATH_MAX, nls_codepage,
+ remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
rc = -ENOMEM;
goto parse_DFS_referrals_exit;
}
- cifsConvertToUCS((__le16 *) tmp, searchName,
- PATH_MAX, nls_codepage, remap);
- node->path_consumed = cifs_ucs2_bytes(tmp,
+ cifsConvertToUTF16((__le16 *) tmp, searchName,
+ PATH_MAX, nls_codepage, remap);
+ node->path_consumed = cifs_utf16_bytes(tmp,
le16_to_cpu(pSMBr->PathConsumed),
nls_codepage);
kfree(tmp);
/* copy DfsPath */
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
max_len = data_end - temp;
- node->path_name = cifs_strndup_from_ucs(temp, max_len,
- is_unicode, nls_codepage);
+ node->path_name = cifs_strndup_from_utf16(temp, max_len,
+ is_unicode, nls_codepage);
if (!node->path_name) {
rc = -ENOMEM;
goto parse_DFS_referrals_exit;
/* copy link target UNC */
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
max_len = data_end - temp;
- node->node_name = cifs_strndup_from_ucs(temp, max_len,
- is_unicode, nls_codepage);
+ node->node_name = cifs_strndup_from_utf16(temp, max_len,
+ is_unicode, nls_codepage);
if (!node->node_name)
rc = -ENOMEM;
}
if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
name_len =
- cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
- searchName, PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
+ searchName, PATH_MAX, nls_codepage,
+ remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- ConvertToUCS((__le16 *) pSMB->fileName, fileName,
- PATH_MAX, nls_codepage);
+ ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
+ PATH_MAX, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
list_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
list_len++; /* trailing null */
list_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
#include <asm/processor.h>
#include <linux/inet.h>
#include <linux/module.h>
+#include <keys/user-type.h>
#include <net/ipv6.h>
#include "cifspdu.h"
#include "cifsglob.h"
static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
{
- struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
+ struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond;
struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
- char *data_area_of_target;
- char *data_area_of_buf2;
+ char *data_area_of_tgt;
+ char *data_area_of_src;
int remaining;
- unsigned int byte_count, total_in_buf;
- __u16 total_data_size, total_in_buf2;
+ unsigned int byte_count, total_in_tgt;
+ __u16 tgt_total_cnt, src_total_cnt, total_in_src;
- total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+ src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
+ tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
- if (total_data_size !=
- get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount))
- cFYI(1, "total data size of primary and secondary t2 differ");
+ if (tgt_total_cnt != src_total_cnt)
+ cFYI(1, "total data count of primary and secondary t2 differ "
+ "source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
- total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+ total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
- remaining = total_data_size - total_in_buf;
+ remaining = tgt_total_cnt - total_in_tgt;
- if (remaining < 0)
+ if (remaining < 0) {
+ cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
+ "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
return -EPROTO;
+ }
- if (remaining == 0) /* nothing to do, ignore */
+ if (remaining == 0) {
+ /* nothing to do, ignore */
+ cFYI(1, "no more data remains");
return 0;
+ }
- total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount);
- if (remaining < total_in_buf2) {
+ total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
+ if (remaining < total_in_src)
cFYI(1, "transact2 2nd response contains too much data");
- }
/* find end of first SMB data area */
- data_area_of_target = (char *)&pSMBt->hdr.Protocol +
+ data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
- /* validate target area */
- data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol +
- get_unaligned_le16(&pSMB2->t2_rsp.DataOffset);
+ /* validate target area */
+ data_area_of_src = (char *)&pSMBs->hdr.Protocol +
+ get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
- data_area_of_target += total_in_buf;
+ data_area_of_tgt += total_in_tgt;
- /* copy second buffer into end of first buffer */
- total_in_buf += total_in_buf2;
+ total_in_tgt += total_in_src;
/* is the result too big for the field? */
- if (total_in_buf > USHRT_MAX)
+ if (total_in_tgt > USHRT_MAX) {
+ cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
return -EPROTO;
- put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
+ }
+ put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
/* fix up the BCC */
byte_count = get_bcc(pTargetSMB);
- byte_count += total_in_buf2;
+ byte_count += total_in_src;
/* is the result too big for the field? */
- if (byte_count > USHRT_MAX)
+ if (byte_count > USHRT_MAX) {
+ cFYI(1, "coalesced BCC too large (%u)", byte_count);
return -EPROTO;
+ }
put_bcc(byte_count, pTargetSMB);
byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
- byte_count += total_in_buf2;
+ byte_count += total_in_src;
/* don't allow buffer to overflow */
- if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
+ if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+ cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
return -ENOBUFS;
+ }
pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
- memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
+ /* copy second buffer into end of first buffer */
+ memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
- if (remaining == total_in_buf2) {
- cFYI(1, "found the last secondary response");
- return 0; /* we are done */
- } else /* more responses to go */
+ if (remaining != total_in_src) {
+ /* more responses to go */
+ cFYI(1, "waiting for more secondary responses");
return 1;
+ }
+
+ /* we are done */
+ cFYI(1, "found the last secondary response");
+ return 0;
}
static void
}
}
- if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
- cERROR(1, "Multiuser mounts currently require krb5 "
- "authentication!");
+#ifndef CONFIG_KEYS
+ /* Muliuser mounts require CONFIG_KEYS support */
+ if (vol->multiuser) {
+ cERROR(1, "Multiuser mounts require kernels with "
+ "CONFIG_KEYS enabled.");
goto cifs_parse_mount_err;
}
+#endif
if (vol->UNCip == NULL)
vol->UNCip = &vol->UNC[2];
return 0;
break;
default:
+ /* NULL username means anonymous session */
+ if (ses->user_name == NULL) {
+ if (!vol->nullauth)
+ return 0;
+ break;
+ }
+
/* anything else takes username/password */
- if (ses->user_name == NULL)
- return 0;
- if (strncmp(ses->user_name, vol->username,
+ if (strncmp(ses->user_name,
+ vol->username ? vol->username : "",
MAX_USERNAME_SIZE))
return 0;
if (strlen(vol->username) != 0 &&
cifs_put_tcp_session(server);
}
+#ifdef CONFIG_KEYS
+
+/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
+
+/* Populate username and pw fields from keyring if possible */
+static int
+cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
+{
+ int rc = 0;
+ char *desc, *delim, *payload;
+ ssize_t len;
+ struct key *key;
+ struct TCP_Server_Info *server = ses->server;
+ struct sockaddr_in *sa;
+ struct sockaddr_in6 *sa6;
+ struct user_key_payload *upayload;
+
+ desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ /* try to find an address key first */
+ switch (server->dstaddr.ss_family) {
+ case AF_INET:
+ sa = (struct sockaddr_in *)&server->dstaddr;
+ sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)&server->dstaddr;
+ sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
+ break;
+ default:
+ cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ cFYI(1, "%s: desc=%s", __func__, desc);
+ key = request_key(&key_type_logon, desc, "");
+ if (IS_ERR(key)) {
+ if (!ses->domainName) {
+ cFYI(1, "domainName is NULL");
+ rc = PTR_ERR(key);
+ goto out_err;
+ }
+
+ /* didn't work, try to find a domain key */
+ sprintf(desc, "cifs:d:%s", ses->domainName);
+ cFYI(1, "%s: desc=%s", __func__, desc);
+ key = request_key(&key_type_logon, desc, "");
+ if (IS_ERR(key)) {
+ rc = PTR_ERR(key);
+ goto out_err;
+ }
+ }
+
+ down_read(&key->sem);
+ upayload = key->payload.data;
+ if (IS_ERR_OR_NULL(upayload)) {
+ rc = PTR_ERR(key);
+ goto out_key_put;
+ }
+
+ /* find first : in payload */
+ payload = (char *)upayload->data;
+ delim = strnchr(payload, upayload->datalen, ':');
+ cFYI(1, "payload=%s", payload);
+ if (!delim) {
+ cFYI(1, "Unable to find ':' in payload (datalen=%d)",
+ upayload->datalen);
+ rc = -EINVAL;
+ goto out_key_put;
+ }
+
+ len = delim - payload;
+ if (len > MAX_USERNAME_SIZE || len <= 0) {
+ cFYI(1, "Bad value from username search (len=%ld)", len);
+ rc = -EINVAL;
+ goto out_key_put;
+ }
+
+ vol->username = kstrndup(payload, len, GFP_KERNEL);
+ if (!vol->username) {
+ cFYI(1, "Unable to allocate %ld bytes for username", len);
+ rc = -ENOMEM;
+ goto out_key_put;
+ }
+ cFYI(1, "%s: username=%s", __func__, vol->username);
+
+ len = key->datalen - (len + 1);
+ if (len > MAX_PASSWORD_SIZE || len <= 0) {
+ cFYI(1, "Bad len for password search (len=%ld)", len);
+ rc = -EINVAL;
+ kfree(vol->username);
+ vol->username = NULL;
+ goto out_key_put;
+ }
+
+ ++delim;
+ vol->password = kstrndup(delim, len, GFP_KERNEL);
+ if (!vol->password) {
+ cFYI(1, "Unable to allocate %ld bytes for password", len);
+ rc = -ENOMEM;
+ kfree(vol->username);
+ vol->username = NULL;
+ goto out_key_put;
+ }
+
+out_key_put:
+ up_read(&key->sem);
+ key_put(key);
+out_err:
+ kfree(desc);
+ cFYI(1, "%s: returning %d", __func__, rc);
+ return rc;
+}
+#else /* ! CONFIG_KEYS */
+static inline int
+cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
+ struct cifs_ses *ses __attribute__((unused)))
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_KEYS */
+
static bool warned_on_ntlm; /* globals init to false automatically */
static struct cifs_ses *
#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
/*
- * Windows only supports a max of 60k reads. Default to that when posix
- * extensions aren't in force.
+ * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
+ * those values when posix extensions aren't in force. In actuality here, we
+ * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
+ * to be ok with the extra byte even though Windows doesn't send writes that
+ * are that large.
+ *
+ * Citation:
+ *
+ * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
*/
#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
+#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
static unsigned int
cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
{
__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
- CIFS_DEFAULT_IOSIZE;
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+ if (pvolume_info->wsize)
+ wsize = pvolume_info->wsize;
+ else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+ wsize = CIFS_DEFAULT_IOSIZE;
+ else
+ wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
/* can server support 24-bit write sizes? (via UNIX extensions) */
if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
return -EINVAL;
if (volume_info->nullauth) {
- cFYI(1, "null user");
- volume_info->username = kzalloc(1, GFP_KERNEL);
- if (volume_info->username == NULL)
- return -ENOMEM;
+ cFYI(1, "Anonymous login");
+ kfree(volume_info->username);
+ volume_info->username = NULL;
} else if (volume_info->username) {
/* BB fixme parse for domain name here */
cFYI(1, "Username: %s", volume_info->username);
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
length =
- cifs_strtoUCS((__le16 *) bcc_ptr, tree,
+ cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
6 /* max utf8 char length in bytes */ *
(/* server len*/ + 256 /* share len */), nls_codepage);
bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
/* mostly informational -- no need to fail on error here */
kfree(tcon->nativeFileSystem);
- tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
+ tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
bytes_left, is_unicode,
nls_codepage);
return rc;
}
+static int
+cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
+{
+ switch (ses->server->secType) {
+ case Kerberos:
+ vol->secFlg = CIFSSEC_MUST_KRB5;
+ return 0;
+ case NTLMv2:
+ vol->secFlg = CIFSSEC_MUST_NTLMV2;
+ break;
+ case NTLM:
+ vol->secFlg = CIFSSEC_MUST_NTLM;
+ break;
+ case RawNTLMSSP:
+ vol->secFlg = CIFSSEC_MUST_NTLMSSP;
+ break;
+ case LANMAN:
+ vol->secFlg = CIFSSEC_MUST_LANMAN;
+ break;
+ }
+
+ return cifs_set_cifscreds(vol, ses);
+}
+
static struct cifs_tcon *
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
{
+ int rc;
struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
struct cifs_ses *ses;
struct cifs_tcon *tcon = NULL;
struct smb_vol *vol_info;
- char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
- /* We used to have this as MAX_USERNAME which is */
- /* way too big now (256 instead of 32) */
vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
if (vol_info == NULL) {
goto out;
}
- snprintf(username, sizeof(username), "krb50x%x", fsuid);
- vol_info->username = username;
vol_info->local_nls = cifs_sb->local_nls;
vol_info->linux_uid = fsuid;
vol_info->cred_uid = fsuid;
vol_info->local_lease = master_tcon->local_lease;
vol_info->no_linux_ext = !master_tcon->unix_ext;
- /* FIXME: allow for other secFlg settings */
- vol_info->secFlg = CIFSSEC_MUST_KRB5;
+ rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
+ if (rc) {
+ tcon = ERR_PTR(rc);
+ goto out;
+ }
/* get a reference for the same TCP session */
spin_lock(&cifs_tcp_ses_lock);
if (ses->capabilities & CAP_UNIX)
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
out:
+ kfree(vol_info->username);
+ kfree(vol_info->password);
kfree(vol_info);
return tcon;
name.name = scratch_buf;
name.len =
- cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
- UNICODE_NAME_MAX,
- min(de.namelen, (size_t)max_len), nlt,
- cifs_sb->mnt_cifs_flags &
+ cifs_from_utf16((char *)name.name, (__le16 *)de.name,
+ UNICODE_NAME_MAX,
+ min_t(size_t, de.namelen,
+ (size_t)max_len), nlt,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
name.len -= nls_nullsize(nlt);
} else {
int bytes_ret = 0;
/* Copy OS version */
- bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
- nls_cp);
+ bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
+ nls_cp);
bcc_ptr += 2 * bytes_ret;
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
- 32, nls_cp);
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
+ 32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 32, nls_cp);
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
*(bcc_ptr+1) = 0;
bytes_ret = 0;
} else
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
- 256, nls_cp);
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
+ 256, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
} else {
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name,
- MAX_USERNAME_SIZE, nls_cp);
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
+ MAX_USERNAME_SIZE, nls_cp);
}
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */
cFYI(1, "bleft %d", bleft);
kfree(ses->serverOS);
- ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
cFYI(1, "serverOS=%s", ses->serverOS);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len;
return;
kfree(ses->serverNOS);
- ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
cFYI(1, "serverNOS=%s", ses->serverNOS);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len;
return;
kfree(ses->serverDomain);
- ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
cFYI(1, "serverDomain=%s", ses->serverDomain);
return;
tmp += 2;
} else {
int len;
- len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
- MAX_USERNAME_SIZE, nls_cp);
+ len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
+ MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->DomainName.Length = cpu_to_le16(len);
tmp += 2;
} else {
int len;
- len = cifs_strtoUCS((__le16 *)tmp, ses->user_name,
- MAX_USERNAME_SIZE, nls_cp);
+ len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
+ MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->UserName.Length = cpu_to_le16(len);
/* Password cannot be longer than 128 characters */
if (passwd) /* Password must be converted to NT unicode */
- len = cifs_strtoUCS(wpwd, passwd, 128, codepage);
+ len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
else {
len = 0;
*wpwd = 0; /* Ensure string is null terminated */
* debugfs_print_regs32 - use seq_print to describe a set of registers
* @s: the seq_file structure being used to generate output
* @regs: an array if struct debugfs_reg32 structures
- * @mregs: the length of the above array
+ * @nregs: the length of the above array
* @base: the base address to be used in reading the registers
* @prefix: a string to be prefixed to every output line
*
(unsigned long long)(extent_base + extent_offset), rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "encryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(page)
- + (extent_offset * crypt_stat->extent_size)),
- 8);
- }
rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
page, (extent_offset
* crypt_stat->extent_size),
goto out;
}
rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; "
- "rc = [%d]\n",
- (unsigned long long)(extent_base + extent_offset), rc);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "encryption:\n");
- ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
- }
out:
return rc;
}
(unsigned long long)(extent_base + extent_offset), rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "decryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(enc_extent_page)
- + (extent_offset * crypt_stat->extent_size)),
- 8);
- }
rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
(extent_offset
* crypt_stat->extent_size),
goto out;
}
rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; "
- "rc = [%d]\n",
- (unsigned long long)(extent_base + extent_offset), rc);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "decryption:\n");
- ecryptfs_dump_hex((char *)(page_address(page)
- + (extent_offset
- * crypt_stat->extent_size)), 8);
- }
out:
return rc;
}
*/
int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
{
- int rc = 0;
- char *page_virt = NULL;
+ int rc;
+ char *page_virt;
struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
ecryptfs_dentry,
ECRYPTFS_VALIDATE_HEADER_SIZE);
if (rc) {
+ /* metadata is not in the file header, so try xattrs */
memset(page_virt, 0, PAGE_CACHE_SIZE);
rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
- "file header region or xattr region\n");
+ "file header region or xattr region, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
goto out;
}
ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
- "file xattr region either\n");
+ "file xattr region either, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
}
if (crypt_stat->mount_crypt_stat->flags
"crypto metadata only in the extended attribute "
"region, but eCryptfs was mounted without "
"xattr support enabled. eCryptfs will not treat "
- "this like an encrypted file.\n");
+ "this like an encrypted file, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
}
}
* dentry name */
#define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as
* metadata */
+#define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */
+#define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to
+ * ecryptfs_parse_packet_length() and
+ * ecryptfs_write_packet_length()
+ */
/* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >=
* ECRYPTFS_MAX_IV_BYTES */
#define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16
size_t num_zeros = (PAGE_CACHE_SIZE
- (ia->ia_size & ~PAGE_CACHE_MASK));
-
- /*
- * XXX(truncate) this should really happen at the begginning
- * of ->setattr. But the code is too messy to that as part
- * of a larger patch. ecryptfs is also totally missing out
- * on the inode_change_ok check at the beginning of
- * ->setattr while would include this.
- */
- rc = inode_newsize_ok(inode, ia->ia_size);
- if (rc)
- goto out;
-
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
truncate_setsize(inode, ia->ia_size);
lower_ia->ia_size = ia->ia_size;
return rc;
}
+static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
+{
+ struct ecryptfs_crypt_stat *crypt_stat;
+ loff_t lower_oldsize, lower_newsize;
+
+ crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+ lower_oldsize = upper_size_to_lower_size(crypt_stat,
+ i_size_read(inode));
+ lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
+ if (lower_newsize > lower_oldsize) {
+ /*
+ * The eCryptfs inode and the new *lower* size are mixed here
+ * because we may not have the lower i_mutex held and/or it may
+ * not be appropriate to call inode_newsize_ok() with inodes
+ * from other filesystems.
+ */
+ return inode_newsize_ok(inode, lower_newsize);
+ }
+
+ return 0;
+}
+
/**
* ecryptfs_truncate
* @dentry: The ecryptfs layer dentry
struct iattr lower_ia = { .ia_valid = 0 };
int rc;
+ rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length);
+ if (rc)
+ return rc;
+
rc = truncate_upper(dentry, &ia, &lower_ia);
if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
}
}
mutex_unlock(&crypt_stat->cs_mutex);
+
+ rc = inode_change_ok(inode, ia);
+ if (rc)
+ goto out;
+ if (ia->ia_valid & ATTR_SIZE) {
+ rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
+ if (rc)
+ goto out;
+ }
+
if (S_ISREG(inode->i_mode)) {
rc = filemap_write_and_wait(inode->i_mapping);
if (rc)
(*size) += ((unsigned char)(data[1]) + 192);
(*length_size) = 2;
} else if (data[0] == 255) {
- /* Five-byte length; we're not supposed to see this */
+ /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
ecryptfs_printk(KERN_ERR, "Five-byte packet length not "
"supported\n");
rc = -EINVAL;
/**
* ecryptfs_write_packet_length
* @dest: The byte array target into which to write the length. Must
- * have at least 5 bytes allocated.
+ * have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated.
* @size: The length to write.
* @packet_size_length: The number of bytes used to encode the packet
* length is written to this address.
dest[1] = ((size - 192) % 256);
(*packet_size_length) = 2;
} else {
+ /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
rc = -EINVAL;
ecryptfs_printk(KERN_WARNING,
"Unsupported packet size: [%zd]\n", size);
return rc;
}
+/*
+ * miscdevfs packet format:
+ * Octet 0: Type
+ * Octets 1-4: network byte order msg_ctx->counter
+ * Octets 5-N0: Size of struct ecryptfs_message to follow
+ * Octets N0-N1: struct ecryptfs_message (including data)
+ *
+ * Octets 5-N1 not written if the packet type does not include a message
+ */
+#define PKT_TYPE_SIZE 1
+#define PKT_CTR_SIZE 4
+#define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE)
+#define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+ + ECRYPTFS_MIN_PKT_LEN_SIZE)
+/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */
+#define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+ + ECRYPTFS_MAX_PKT_LEN_SIZE \
+ + sizeof(struct ecryptfs_message) \
+ + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)
+#define PKT_TYPE_OFFSET 0
+#define PKT_CTR_OFFSET PKT_TYPE_SIZE
+#define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE)
+
/**
* ecryptfs_miscdev_read - format and send message from queue
* @file: fs/ecryptfs/euid miscdevfs handle (ignored)
struct ecryptfs_daemon *daemon;
struct ecryptfs_msg_ctx *msg_ctx;
size_t packet_length_size;
- char packet_length[3];
+ char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
size_t i;
size_t total_length;
uid_t euid = current_euid();
packet_length_size = 0;
msg_ctx->msg_size = 0;
}
- /* miscdevfs packet format:
- * Octet 0: Type
- * Octets 1-4: network byte order msg_ctx->counter
- * Octets 5-N0: Size of struct ecryptfs_message to follow
- * Octets N0-N1: struct ecryptfs_message (including data)
- *
- * Octets 5-N1 not written if the packet type does not
- * include a message */
- total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
+ total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
+ + msg_ctx->msg_size);
if (count < total_length) {
rc = 0;
printk(KERN_WARNING "%s: Only given user buffer of "
rc = -EFAULT;
if (put_user(msg_ctx->type, buf))
goto out_unlock_msg_ctx;
- if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1)))
+ if (put_user(cpu_to_be32(msg_ctx->counter),
+ (__be32 __user *)(&buf[PKT_CTR_OFFSET])))
goto out_unlock_msg_ctx;
- i = 5;
+ i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
if (msg_ctx->msg) {
if (copy_to_user(&buf[i], packet_length, packet_length_size))
goto out_unlock_msg_ctx;
* @count: Amount of data in @buf
* @ppos: Pointer to offset in file (ignored)
*
- * miscdevfs packet format:
- * Octet 0: Type
- * Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
- * Octets 5-N0: Size of struct ecryptfs_message to follow
- * Octets N0-N1: struct ecryptfs_message (including data)
- *
* Returns the number of bytes read from @buf
*/
static ssize_t
{
__be32 counter_nbo;
u32 seq;
- size_t packet_size, packet_size_length, i;
- ssize_t sz = 0;
+ size_t packet_size, packet_size_length;
char *data;
uid_t euid = current_euid();
- int rc;
+ unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE];
+ ssize_t rc;
- if (count == 0)
- goto out;
+ if (count == 0) {
+ return 0;
+ } else if (count == MIN_NON_MSG_PKT_SIZE) {
+ /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
+ goto memdup;
+ } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) {
+ printk(KERN_WARNING "%s: Acceptable packet size range is "
+ "[%d-%lu], but amount of data written is [%zu].",
+ __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count);
+ return -EINVAL;
+ }
+
+ if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET],
+ sizeof(packet_size_peek))) {
+ printk(KERN_WARNING "%s: Error while inspecting packet size\n",
+ __func__);
+ return -EFAULT;
+ }
+ rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
+ &packet_size_length);
+ if (rc) {
+ printk(KERN_WARNING "%s: Error parsing packet length; "
+ "rc = [%zd]\n", __func__, rc);
+ return rc;
+ }
+
+ if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size)
+ != count) {
+ printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
+ packet_size);
+ return -EINVAL;
+ }
+
+memdup:
data = memdup_user(buf, count);
if (IS_ERR(data)) {
printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
__func__, PTR_ERR(data));
- goto out;
+ return PTR_ERR(data);
}
- sz = count;
- i = 0;
- switch (data[i++]) {
+ switch (data[PKT_TYPE_OFFSET]) {
case ECRYPTFS_MSG_RESPONSE:
- if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
+ if (count < (MIN_MSG_PKT_SIZE
+ + sizeof(struct ecryptfs_message))) {
printk(KERN_WARNING "%s: Minimum acceptable packet "
"size is [%zd], but amount of data written is "
"only [%zd]. Discarding response packet.\n",
__func__,
- (1 + 4 + 1 + sizeof(struct ecryptfs_message)),
- count);
+ (MIN_MSG_PKT_SIZE
+ + sizeof(struct ecryptfs_message)), count);
+ rc = -EINVAL;
goto out_free;
}
- memcpy(&counter_nbo, &data[i], 4);
+ memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);
seq = be32_to_cpu(counter_nbo);
- i += 4;
- rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
- &packet_size_length);
+ rc = ecryptfs_miscdev_response(
+ &data[PKT_LEN_OFFSET + packet_size_length],
+ packet_size, euid, current_user_ns(),
+ task_pid(current), seq);
if (rc) {
- printk(KERN_WARNING "%s: Error parsing packet length; "
- "rc = [%d]\n", __func__, rc);
- goto out_free;
- }
- i += packet_size_length;
- if ((1 + 4 + packet_size_length + packet_size) != count) {
- printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
- " + packet_size([%zd]))([%zd]) != "
- "count([%zd]). Invalid packet format.\n",
- __func__, packet_size_length, packet_size,
- (1 + packet_size_length + packet_size), count);
- goto out_free;
- }
- rc = ecryptfs_miscdev_response(&data[i], packet_size,
- euid, current_user_ns(),
- task_pid(current), seq);
- if (rc)
printk(KERN_WARNING "%s: Failed to deliver miscdev "
- "response to requesting operation; rc = [%d]\n",
+ "response to requesting operation; rc = [%zd]\n",
__func__, rc);
+ goto out_free;
+ }
break;
case ECRYPTFS_MSG_HELO:
case ECRYPTFS_MSG_QUIT:
ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
"message of unrecognized type [%d]\n",
data[0]);
- break;
+ rc = -EINVAL;
+ goto out_free;
}
+ rc = count;
out_free:
kfree(data);
-out:
- return sz;
+ return rc;
}
* @page: Page that is locked before this call is made
*
* Returns zero on success; non-zero otherwise
+ *
+ * This is where we encrypt the data and pass the encrypted data to
+ * the lower filesystem. In OpenPGP-compatible mode, we operate on
+ * entire underlying packets.
*/
static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
{
* @copied: The amount of data copied
* @page: The eCryptfs page
* @fsdata: The fsdata (unused)
- *
- * This is where we encrypt the data and pass the encrypted data to
- * the lower filesystem. In OpenPGP-compatible mode, we operate on
- * entire underlying packets.
*/
static int ecryptfs_write_end(struct file *file,
struct address_space *mapping,
pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
- size_t total_remaining_bytes = ((offset + size) - pos);
+ loff_t total_remaining_bytes = ((offset + size) - pos);
+
+ if (fatal_signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
if (num_bytes > total_remaining_bytes)
num_bytes = total_remaining_bytes;
if (pos < offset) {
/* remaining zeros to write, up to destination offset */
- size_t total_remaining_zeros = (offset - pos);
+ loff_t total_remaining_zeros = (offset - pos);
if (num_bytes > total_remaining_zeros)
num_bytes = total_remaining_zeros;
}
pos += num_bytes;
}
- if ((offset + size) > ecryptfs_file_size) {
- i_size_write(ecryptfs_inode, (offset + size));
+ if (pos > ecryptfs_file_size) {
+ i_size_write(ecryptfs_inode, pos);
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
- rc = ecryptfs_write_inode_size_to_metadata(
+ int rc2;
+
+ rc2 = ecryptfs_write_inode_size_to_metadata(
ecryptfs_inode);
- if (rc) {
+ if (rc2) {
printk(KERN_ERR "Problem with "
"ecryptfs_write_inode_size_to_metadata; "
- "rc = [%d]\n", rc);
+ "rc = [%d]\n", rc2);
+ if (!rc)
+ rc = rc2;
goto out;
}
}
flush_dcache_page(page_for_ecryptfs);
return rc;
}
-
-#if 0
-/**
- * ecryptfs_read
- * @data: The virtual address into which to write the data read (and
- * possibly decrypted) from the lower file
- * @offset: The offset in the decrypted view of the file from which to
- * read into @data
- * @size: The number of bytes to read into @data
- * @ecryptfs_file: The eCryptfs file from which to read
- *
- * Read an arbitrary amount of data from an arbitrary location in the
- * eCryptfs page cache. This is done on an extent-by-extent basis;
- * individual extents are decrypted and read from the lower page
- * cache (via VFS reads). This function takes care of all the
- * address translation to locations in the lower filesystem.
- *
- * Returns zero on success; non-zero otherwise
- */
-int ecryptfs_read(char *data, loff_t offset, size_t size,
- struct file *ecryptfs_file)
-{
- struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode;
- struct page *ecryptfs_page;
- char *ecryptfs_page_virt;
- loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
- loff_t data_offset = 0;
- loff_t pos;
- int rc = 0;
-
- if ((offset + size) > ecryptfs_file_size) {
- rc = -EINVAL;
- printk(KERN_ERR "%s: Attempt to read data past the end of the "
- "file; offset = [%lld]; size = [%td]; "
- "ecryptfs_file_size = [%lld]\n",
- __func__, offset, size, ecryptfs_file_size);
- goto out;
- }
- pos = offset;
- while (pos < (offset + size)) {
- pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
- size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
- size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
- size_t total_remaining_bytes = ((offset + size) - pos);
-
- if (num_bytes > total_remaining_bytes)
- num_bytes = total_remaining_bytes;
- ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode,
- ecryptfs_page_idx);
- if (IS_ERR(ecryptfs_page)) {
- rc = PTR_ERR(ecryptfs_page);
- printk(KERN_ERR "%s: Error getting page at "
- "index [%ld] from eCryptfs inode "
- "mapping; rc = [%d]\n", __func__,
- ecryptfs_page_idx, rc);
- goto out;
- }
- ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
- memcpy((data + data_offset),
- ((char *)ecryptfs_page_virt + start_offset_in_page),
- num_bytes);
- kunmap_atomic(ecryptfs_page_virt, KM_USER0);
- flush_dcache_page(ecryptfs_page);
- SetPageUptodate(ecryptfs_page);
- unlock_page(ecryptfs_page);
- page_cache_release(ecryptfs_page);
- pos += num_bytes;
- data_offset += num_bytes;
- }
-out:
- return rc;
-}
-#endif /* 0 */
flags = flags & EXT2_FL_USER_MODIFIABLE;
flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
ei->i_flags = flags;
- mutex_unlock(&inode->i_mutex);
ext2_set_inode_flags(inode);
inode->i_ctime = CURRENT_TIME_SEC;
+ mutex_unlock(&inode->i_mutex);
+
mark_inode_dirty(inode);
setflags_out:
mnt_drop_write_file(filp);
}
case EXT2_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *) arg);
- case EXT2_IOC_SETVERSION:
+ case EXT2_IOC_SETVERSION: {
+ __u32 generation;
+
if (!inode_owner_or_capable(inode))
return -EPERM;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
- if (get_user(inode->i_generation, (int __user *) arg)) {
+ if (get_user(generation, (int __user *) arg)) {
ret = -EFAULT;
- } else {
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
+ goto setversion_out;
}
+
+ mutex_lock(&inode->i_mutex);
+ inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_generation = generation;
+ mutex_unlock(&inode->i_mutex);
+
+ mark_inode_dirty(inode);
+setversion_out:
mnt_drop_write_file(filp);
return ret;
+ }
case EXT2_IOC_GETRSVSZ:
if (test_opt(inode->i_sb, RESERVATION)
&& S_ISREG(inode->i_mode)
*
* Return <0 on error, 0 on success, 1 if there was nothing to clean up.
*
- * Called with the journal lock held.
- *
* This is the only part of the journaling code which really needs to be
* aware of transaction aborts. Checkpointing involves writing to the
* main filesystem area rather than to the journal, so it can proceed
if (is_journal_aborted(journal))
return 1;
- /* OK, work out the oldest transaction remaining in the log, and
+ /*
+ * OK, work out the oldest transaction remaining in the log, and
* the log block it starts at.
*
* If the log is now empty, we need to work out which is the
* next transaction ID we will write, and where it will
- * start. */
-
+ * start.
+ */
spin_lock(&journal->j_state_lock);
spin_lock(&journal->j_list_lock);
transaction = journal->j_checkpoint_transactions;
spin_unlock(&journal->j_state_lock);
return 1;
}
+ spin_unlock(&journal->j_state_lock);
+
+ /*
+ * We need to make sure that any blocks that were recently written out
+ * --- perhaps by log_do_checkpoint() --- are flushed out before we
+ * drop the transactions from the journal. It's unlikely this will be
+ * necessary, especially with an appropriately sized journal, but we
+ * need this to guarantee correctness. Fortunately
+ * cleanup_journal_tail() doesn't get called all that often.
+ */
+ if (journal->j_flags & JFS_BARRIER)
+ blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+ spin_lock(&journal->j_state_lock);
+ if (!tid_gt(first_tid, journal->j_tail_sequence)) {
+ spin_unlock(&journal->j_state_lock);
+ /* Someone else cleaned up journal so return 0 */
+ return 0;
+ }
/* OK, update the superblock to recover the freed space.
* Physical blocks come first: have we wrapped beyond the end of
* the log? */
#include <linux/fs.h>
#include <linux/jbd.h>
#include <linux/errno.h>
+#include <linux/blkdev.h>
#endif
/*
err2 = sync_blockdev(journal->j_fs_dev);
if (!err)
err = err2;
+ /* Flush disk caches to get replayed data on the permanent storage */
+ if (journal->j_flags & JFS_BARRIER)
+ blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
return err;
}
if (!page)
continue;
+ if (PageReserved(page))
+ continue;
+
/* Clear accessed and referenced bits. */
ptep_test_and_clear_young(vma, addr, pte);
ClearPageReferenced(page);
mutex_unlock(&dqopt->dqio_mutex);
goto out_file_init;
}
+ if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
+ dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
mutex_unlock(&dqopt->dqio_mutex);
spin_lock(&dq_state_lock);
dqopt->flags |= dquot_state_flag(flags, type);
spin_lock(&dq_data_lock);
ii->dqi_bgrace = mi->dqi_bgrace;
ii->dqi_igrace = mi->dqi_igrace;
- ii->dqi_flags = mi->dqi_flags & DQF_MASK;
+ ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
ii->dqi_valid = IIF_ALL;
spin_unlock(&dq_data_lock);
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
if (ii->dqi_valid & IIF_IGRACE)
mi->dqi_igrace = ii->dqi_igrace;
if (ii->dqi_valid & IIF_FLAGS)
- mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) |
- (ii->dqi_flags & DQF_MASK);
+ mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) |
+ (ii->dqi_flags & DQF_SETINFO_MASK);
spin_unlock(&dq_data_lock);
mark_info_dirty(sb, type);
/* Force write to disk */
const void *ns = NULL;
int err;
+ if (!dir_sd) {
+ WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
+ kobject_name(kobj));
+ return -ENOENT;
+ }
+
err = 0;
if (!sysfs_ns_type(dir_sd))
goto out;
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
- if (!dir_sd)
+ if (!dir_sd) {
+ WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
+ name);
return -ENOENT;
+ }
sysfs_addrm_start(&acxt, dir_sd);
__func__, (unsigned long long) ip->i_ino,
(long long) pathlen);
ASSERT(0);
- return XFS_ERROR(EFSCORRUPTED);
+ error = XFS_ERROR(EFSCORRUPTED);
+ goto out;
}
*/
acpi_status
acpi_os_read_memory(acpi_physical_address address, u32 * value, u32 width);
+acpi_status
+acpi_os_read_memory64(acpi_physical_address address, u64 *value, u32 width);
acpi_status
acpi_os_write_memory(acpi_physical_address address, u32 value, u32 width);
+acpi_status
+acpi_os_write_memory64(acpi_physical_address address, u64 value, u32 width);
/*
* Platform and hardware-independent PCI configuration space access
+++ /dev/null
-#ifndef ACPI_ATOMIC_IO_H
-#define ACPI_ATOMIC_IO_H
-
-int acpi_pre_map_gar(struct acpi_generic_address *reg);
-int acpi_post_unmap_gar(struct acpi_generic_address *reg);
-
-int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg);
-int acpi_atomic_write(u64 val, struct acpi_generic_address *reg);
-
-#endif
u8 has_cst:1;
u8 power_setup_done:1;
u8 bm_rld_set:1;
+ u8 need_hotplug_init:1;
};
struct acpi_processor {
struct drm_file *file_priv);
extern int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
/* Cache management (drm_cache.c) */
void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
/*****************************************************************************/
/*
- * the payload for a key of type "user"
+ * the payload for a key of type "user" or "logon"
* - once filled in and attached to a key:
* - the payload struct is invariant may not be changed, only replaced
* - the payload must be read with RCU procedures or with the key semaphore
};
extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
extern int user_instantiate(struct key *key, const void *data, size_t datalen);
extern int user_update(struct key *key, const void *data, size_t datalen);
/**
* struct subsys_interface - interfaces to device functions
- * @name name of the device function
- * @subsystem subsytem of the devices to attach to
- * @node the list of functions registered at the subsystem
- * @add device hookup to device function handler
- * @remove device hookup to device function handler
+ * @name: name of the device function
+ * @subsys: subsytem of the devices to attach to
+ * @node: the list of functions registered at the subsystem
+ * @add_dev: device hookup to device function handler
+ * @remove_dev: device hookup to device function handler
*
* Simple interfaces attached to a subsystem. Multiple interfaces can
* attach to a subsystem and its devices. Unlike drivers, they do not
* @archdata: For arch-specific additions.
* @of_node: Associated device tree node.
* @devt: For creating the sysfs "dev".
+ * @id: device instance
* @devres_lock: Spinlock to protect the resource of the device.
* @devres_head: The resources list of the device.
* @knode_class: The node used to add the device to the class list.
* Each module may only use this macro once, and calling it replaces
* module_init() and module_exit().
*
+ * @__driver: driver name
+ * @__register: register function for this driver type
+ * @__unregister: unregister function for this driver type
+ *
* Use this macro to construct bus specific macros for registering
* drivers, and do not use it on its own.
*/
extern int freeze_processes(void);
extern int freeze_kernel_threads(void);
extern void thaw_processes(void);
+extern void thaw_kernel_threads(void);
static inline bool try_to_freeze(void)
{
static inline int freeze_processes(void) { return -ENOSYS; }
static inline int freeze_kernel_threads(void) { return -ENOSYS; }
static inline void thaw_processes(void) {}
+static inline void thaw_kernel_threads(void) {}
static inline bool try_to_freeze(void) { return false; }
#include <linux/rculist_bl.h>
#include <linux/atomic.h>
#include <linux/shrinker.h>
+#include <linux/migrate_mode.h>
#include <asm/byteorder.h>
struct page;
struct address_space;
struct writeback_control;
-enum migrate_mode;
struct iov_iter {
const struct iovec *iov;
u32 speed;
u8 duplex;
+ /* Custom gennetlink interface related flags */
+ bool changed;
+ bool removed;
+
struct rcu_head rcu;
};
enum team_option_type type;
int (*getter)(struct team *team, void *arg);
int (*setter)(struct team *team, void *arg);
+
+ /* Custom gennetlink interface related flags */
+ bool changed;
+ bool removed;
};
struct team_mode {
TEAM_ATTR_OPTION_CHANGED, /* flag */
TEAM_ATTR_OPTION_TYPE, /* u8 */
TEAM_ATTR_OPTION_DATA, /* dynamic */
+ TEAM_ATTR_OPTION_REMOVED, /* flag */
__TEAM_ATTR_OPTION_MAX,
TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1,
TEAM_ATTR_PORT_LINKUP, /* flag */
TEAM_ATTR_PORT_SPEED, /* u32 */
TEAM_ATTR_PORT_DUPLEX, /* u8 */
+ TEAM_ATTR_PORT_REMOVED, /* flag */
__TEAM_ATTR_PORT_MAX,
TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1,
* note header. For kdump, the code in vmcore.c runs in the context
* of the second kernel to combine them into one note.
*/
+#ifndef KEXEC_NOTE_BYTES
#define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) + \
KEXEC_CORE_NOTE_NAME_BYTES + \
KEXEC_CORE_NOTE_DESC_BYTES )
+#endif
/*
* This structure is used to hold the arguments that are used when loading
#ifndef MCP_H
#define MCP_H
-#include <linux/mod_devicetable.h>
#include <mach/dma.h>
struct mcp_ops;
dma_device_t dma_telco_rd;
dma_device_t dma_telco_wr;
struct device attached_device;
- const char *codec;
+ int gpio_base;
};
struct mcp_ops {
unsigned int mcp_reg_read(struct mcp *, unsigned int);
void mcp_enable(struct mcp *);
void mcp_disable(struct mcp *);
-const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp);
#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
struct mcp *mcp_host_alloc(struct device *, size_t);
-int mcp_host_register(struct mcp *, void *);
+int mcp_host_register(struct mcp *);
void mcp_host_unregister(struct mcp *);
struct mcp_driver {
void (*remove)(struct mcp *);
int (*suspend)(struct mcp *, pm_message_t);
int (*resume)(struct mcp *);
- const struct mcp_device_id *id_table;
};
int mcp_driver_register(struct mcp_driver *);
#define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device)
#define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d)
-#define mcp_priv(mcp) ((void *)((mcp)+1))
+static inline void *mcp_priv(struct mcp *mcp)
+{
+ return mcp + 1;
+}
#endif
#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
#define UCB_MODE_AUD_OFF_CAN (1 << 13)
-struct ucb1x00_plat_data {
- int gpio_base;
-};
struct ucb1x00_irq {
void *devid;
unsigned int irq;
struct semaphore adc_sem;
spinlock_t io_lock;
- const struct mcp_device_id *id;
+ u16 id;
u16 io_dir;
u16 io_out;
u16 adc_cr;
#include <linux/mm.h>
#include <linux/mempolicy.h>
+#include <linux/migrate_mode.h>
typedef struct page *new_page_t(struct page *, unsigned long private, int **);
-/*
- * MIGRATE_ASYNC means never block
- * MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
- * on most operations but not ->writepage as the potential stall time
- * is too significant
- * MIGRATE_SYNC will block when migrating pages
- */
-enum migrate_mode {
- MIGRATE_ASYNC,
- MIGRATE_SYNC_LIGHT,
- MIGRATE_SYNC,
-};
-
#ifdef CONFIG_MIGRATION
#define PAGE_MIGRATION 1
--- /dev/null
+#ifndef MIGRATE_MODE_H_INCLUDED
+#define MIGRATE_MODE_H_INCLUDED
+/*
+ * MIGRATE_ASYNC means never block
+ * MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
+ * on most operations but not ->writepage as the potential stall time
+ * is too significant
+ * MIGRATE_SYNC will block when migrating pages
+ */
+enum migrate_mode {
+ MIGRATE_ASYNC,
+ MIGRATE_SYNC_LIGHT,
+ MIGRATE_SYNC,
+};
+
+#endif /* MIGRATE_MODE_H_INCLUDED */
int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn);
void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn);
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap);
int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
-/* mcp */
-
-#define MCP_NAME_SIZE 20
-#define MCP_MODULE_PREFIX "mcp:"
-
-struct mcp_device_id {
- char name[MCP_NAME_SIZE];
- kernel_ulong_t driver_data /* Data private to the driver */
- __attribute__((aligned(sizeof(kernel_ulong_t))));
-};
-
/* dmi */
enum dmi_field {
DMI_NONE,
struct super_block;
#define DQF_MASK 0xffff /* Mask for format specific flags */
-#define DQF_INFO_DIRTY_B 16
+#define DQF_GETINFO_MASK 0x1ffff /* Mask for flags passed to userspace */
+#define DQF_SETINFO_MASK 0xffff /* Mask for flags modifiable from userspace */
+#define DQF_SYS_FILE_B 16
+#define DQF_SYS_FILE (1 << DQF_SYS_FILE_B) /* Quota file stored as system file */
+#define DQF_INFO_DIRTY_B 31
#define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
extern void mark_info_dirty(struct super_block *sb, int type);
*
* returns 0 on success and <0 if the counter->usage will exceed the
* counter->limit _locked call expects the counter->lock to be taken
+ *
+ * charge_nofail works the same, except that it charges the resource
+ * counter unconditionally, and returns < 0 if the after the current
+ * charge we are over limit.
*/
int __must_check res_counter_charge_locked(struct res_counter *counter,
unsigned long val);
int __must_check res_counter_charge(struct res_counter *counter,
unsigned long val, struct res_counter **limit_fail_at);
+int __must_check res_counter_charge_nofail(struct res_counter *counter,
+ unsigned long val, struct res_counter **limit_fail_at);
/*
* uncharge - tell that some portion of the resource is released
unsigned long flags;
spin_lock_irqsave(&cnt->lock, flags);
- margin = cnt->limit - cnt->usage;
+ if (cnt->limit > cnt->usage)
+ margin = cnt->limit - cnt->usage;
+ else
+ margin = 0;
spin_unlock_irqrestore(&cnt->lock, flags);
return margin;
}
extern struct task_struct *idle_task(int cpu);
/**
* is_idle_task - is the specified task an idle task?
- * @tsk: the task in question.
+ * @p: the task in question.
*/
-static inline bool is_idle_task(struct task_struct *p)
+static inline bool is_idle_task(const struct task_struct *p)
{
return p->pid == 0;
}
loff_t size, unsigned long flags);
extern int shmem_zero_setup(struct vm_area_struct *);
extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
+extern void shmem_unlock_mapping(struct address_space *mapping);
extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
pgoff_t index, gfp_t gfp_mask);
extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
LINUX_MIB_TCPPARTIALUNDO, /* TCPPartialUndo */
LINUX_MIB_TCPDSACKUNDO, /* TCPDSACKUndo */
LINUX_MIB_TCPLOSSUNDO, /* TCPLossUndo */
- LINUX_MIB_TCPLOSS, /* TCPLoss */
LINUX_MIB_TCPLOSTRETRANSMIT, /* TCPLostRetransmit */
LINUX_MIB_TCPRENOFAILURES, /* TCPRenoFailures */
LINUX_MIB_TCPSACKFAILURES, /* TCPSackFailures */
static inline void lock_system_sleep(void)
{
- freezer_do_not_count();
+ current->flags |= PF_FREEZER_SKIP;
mutex_lock(&pm_mutex);
}
static inline void unlock_system_sleep(void)
{
+ /*
+ * Don't use freezer_count() because we don't want the call to
+ * try_to_freeze() here.
+ *
+ * Reason:
+ * Fundamentally, we just don't need it, because freezing condition
+ * doesn't come into effect until we release the pm_mutex lock,
+ * since the freezer always works with pm_mutex held.
+ *
+ * More importantly, in the case of hibernation,
+ * unlock_system_sleep() gets called in snapshot_read() and
+ * snapshot_write() when the freezing condition is still in effect.
+ * Which means, if we use try_to_freeze() here, it would make them
+ * enter the refrigerator, thus causing hibernation to lockup.
+ */
+ current->flags &= ~PF_FREEZER_SKIP;
mutex_unlock(&pm_mutex);
- freezer_count();
}
#else /* !CONFIG_PM_SLEEP */
#endif
extern int page_evictable(struct page *page, struct vm_area_struct *vma);
-extern void scan_mapping_unevictable_pages(struct address_space *);
+extern void check_move_unevictable_pages(struct page **, int nr_pages);
extern unsigned long scan_unevictable_pages;
extern int scan_unevictable_handler(struct ctl_table *, int,
+++ /dev/null
-/**
- * System devices follow a slightly different driver model.
- * They don't need to do dynammic driver binding, can't be probed,
- * and don't reside on any type of peripheral bus.
- * So, we represent and treat them a little differently.
- *
- * We still have a notion of a driver for a system device, because we still
- * want to perform basic operations on these devices.
- *
- * We also support auxiliary drivers binding to devices of a certain class.
- *
- * This allows configurable drivers to register themselves for devices of
- * a certain type. And, it allows class definitions to reside in generic
- * code while arch-specific code can register specific drivers.
- *
- * Auxiliary drivers registered with a NULL cls are registered as drivers
- * for all system devices, and get notification calls for each device.
- */
-
-
-#ifndef _SYSDEV_H_
-#define _SYSDEV_H_
-
-#include <linux/kobject.h>
-#include <linux/pm.h>
-
-
-struct sys_device;
-struct sysdev_class_attribute;
-
-struct sysdev_class {
- const char *name;
- struct list_head drivers;
- struct sysdev_class_attribute **attrs;
- struct kset kset;
-};
-
-struct sysdev_class_attribute {
- struct attribute attr;
- ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *,
- char *);
- ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *,
- const char *, size_t);
-};
-
-#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
-{ \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-}
-
-#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
- struct sysdev_class_attribute attr_##_name = \
- _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
-
-
-extern int sysdev_class_register(struct sysdev_class *);
-extern void sysdev_class_unregister(struct sysdev_class *);
-
-extern int sysdev_class_create_file(struct sysdev_class *,
- struct sysdev_class_attribute *);
-extern void sysdev_class_remove_file(struct sysdev_class *,
- struct sysdev_class_attribute *);
-/**
- * Auxiliary system device drivers.
- */
-
-struct sysdev_driver {
- struct list_head entry;
- int (*add)(struct sys_device *);
- int (*remove)(struct sys_device *);
-};
-
-
-extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *);
-extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *);
-
-
-/**
- * sys_devices can be simplified a lot from regular devices, because they're
- * simply not as versatile.
- */
-
-struct sys_device {
- u32 id;
- struct sysdev_class * cls;
- struct kobject kobj;
-};
-
-extern int sysdev_register(struct sys_device *);
-extern void sysdev_unregister(struct sys_device *);
-
-
-struct sysdev_attribute {
- struct attribute attr;
- ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
- ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
- const char *, size_t);
-};
-
-
-#define _SYSDEV_ATTR(_name, _mode, _show, _store) \
-{ \
- .attr = { .name = __stringify(_name), .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-}
-
-#define SYSDEV_ATTR(_name, _mode, _show, _store) \
- struct sysdev_attribute attr_##_name = \
- _SYSDEV_ATTR(_name, _mode, _show, _store);
-
-extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
-extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
-
-/* Create/remove NULL terminated attribute list */
-static inline int
-sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a)
-{
- return sysfs_create_files(&d->kobj, (const struct attribute **)a);
-}
-
-static inline void
-sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a)
-{
- return sysfs_remove_files(&d->kobj, (const struct attribute **)a);
-}
-
-struct sysdev_ext_attribute {
- struct sysdev_attribute attr;
- void *var;
-};
-
-/*
- * Support for simple variable sysdev attributes.
- * The pointer to the variable is stored in a sysdev_ext_attribute
- */
-
-/* Add more types as needed */
-
-extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
- char *);
-extern ssize_t sysdev_store_ulong(struct sys_device *,
- struct sysdev_attribute *, const char *, size_t);
-extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
- char *);
-extern ssize_t sysdev_store_int(struct sys_device *,
- struct sysdev_attribute *, const char *, size_t);
-
-#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \
- { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
- &(_var) }
-#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \
- struct sysdev_ext_attribute attr_##_name = \
- _SYSDEV_ULONG_ATTR(_name, _mode, _var);
-#define _SYSDEV_INT_ATTR(_name, _mode, _var) \
- { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
- &(_var) }
-#define SYSDEV_INT_ATTR(_name, _mode, _var) \
- struct sysdev_ext_attribute attr_##_name = \
- _SYSDEV_INT_ATTR(_name, _mode, _var);
-
-#endif /* _SYSDEV_H_ */
void thermal_cooling_device_unregister(struct thermal_cooling_device *);
#ifdef CONFIG_NET
-extern int generate_netlink_event(u32 orig, enum events event);
+extern int thermal_generate_netlink_event(u32 orig, enum events event);
#else
-static inline int generate_netlink_event(u32 orig, enum events event)
+static inline int thermal_generate_netlink_event(u32 orig, enum events event)
{
return 0;
}
* which the host controller driver should use in preference to the
* transfer_buffer.
* @sg: scatter gather buffer list
+ * @num_mapped_sgs: (internal) number of mapped sg entries
* @num_sgs: number of entries in the sg list
* @transfer_buffer_length: How big is transfer_buffer. The transfer may
* be broken up into chunks according to the current maximum packet
+++ /dev/null
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __LANGWELL_OTG_H
-#define __LANGWELL_OTG_H
-
-#include <linux/usb/intel_mid_otg.h>
-
-#define CI_USBCMD 0x30
-# define USBCMD_RST BIT(1)
-# define USBCMD_RS BIT(0)
-#define CI_USBSTS 0x34
-# define USBSTS_SLI BIT(8)
-# define USBSTS_URI BIT(6)
-# define USBSTS_PCI BIT(2)
-#define CI_PORTSC1 0x74
-# define PORTSC_PP BIT(12)
-# define PORTSC_LS (BIT(11) | BIT(10))
-# define PORTSC_SUSP BIT(7)
-# define PORTSC_CCS BIT(0)
-#define CI_HOSTPC1 0xb4
-# define HOSTPC1_PHCD BIT(22)
-#define CI_OTGSC 0xf4
-# define OTGSC_DPIE BIT(30)
-# define OTGSC_1MSE BIT(29)
-# define OTGSC_BSEIE BIT(28)
-# define OTGSC_BSVIE BIT(27)
-# define OTGSC_ASVIE BIT(26)
-# define OTGSC_AVVIE BIT(25)
-# define OTGSC_IDIE BIT(24)
-# define OTGSC_DPIS BIT(22)
-# define OTGSC_1MSS BIT(21)
-# define OTGSC_BSEIS BIT(20)
-# define OTGSC_BSVIS BIT(19)
-# define OTGSC_ASVIS BIT(18)
-# define OTGSC_AVVIS BIT(17)
-# define OTGSC_IDIS BIT(16)
-# define OTGSC_DPS BIT(14)
-# define OTGSC_1MST BIT(13)
-# define OTGSC_BSE BIT(12)
-# define OTGSC_BSV BIT(11)
-# define OTGSC_ASV BIT(10)
-# define OTGSC_AVV BIT(9)
-# define OTGSC_ID BIT(8)
-# define OTGSC_HABA BIT(7)
-# define OTGSC_HADP BIT(6)
-# define OTGSC_IDPU BIT(5)
-# define OTGSC_DP BIT(4)
-# define OTGSC_OT BIT(3)
-# define OTGSC_HAAR BIT(2)
-# define OTGSC_VC BIT(1)
-# define OTGSC_VD BIT(0)
-# define OTGSC_INTEN_MASK (0x7f << 24)
-# define OTGSC_INT_MASK (0x5f << 24)
-# define OTGSC_INTSTS_MASK (0x7f << 16)
-#define CI_USBMODE 0xf8
-# define USBMODE_CM (BIT(1) | BIT(0))
-# define USBMODE_IDLE 0
-# define USBMODE_DEVICE 0x2
-# define USBMODE_HOST 0x3
-#define USBCFG_ADDR 0xff10801c
-#define USBCFG_LEN 4
-# define USBCFG_VBUSVAL BIT(14)
-# define USBCFG_AVALID BIT(13)
-# define USBCFG_BVALID BIT(12)
-# define USBCFG_SESEND BIT(11)
-
-#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
-
-enum langwell_otg_timer_type {
- TA_WAIT_VRISE_TMR,
- TA_WAIT_BCON_TMR,
- TA_AIDL_BDIS_TMR,
- TB_ASE0_BRST_TMR,
- TB_SE0_SRP_TMR,
- TB_SRP_INIT_TMR,
- TB_SRP_FAIL_TMR,
- TB_BUS_SUSPEND_TMR
-};
-
-#define TA_WAIT_VRISE 100
-#define TA_WAIT_BCON 30000
-#define TA_AIDL_BDIS 15000
-#define TB_ASE0_BRST 5000
-#define TB_SE0_SRP 2
-#define TB_SRP_INIT 100
-#define TB_SRP_FAIL 5500
-#define TB_BUS_SUSPEND 500
-
-struct langwell_otg_timer {
- unsigned long expires; /* Number of count increase to timeout */
- unsigned long count; /* Tick counter */
- void (*function)(unsigned long); /* Timeout function */
- unsigned long data; /* Data passed to function */
- struct list_head list;
-};
-
-struct langwell_otg {
- struct intel_mid_otg_xceiv iotg;
- struct device *dev;
-
- void __iomem *usbcfg; /* SCCBUSB config Reg */
-
- unsigned region;
- unsigned cfg_region;
-
- struct work_struct work;
- struct workqueue_struct *qwork;
- struct timer_list hsm_timer;
-
- spinlock_t lock;
- spinlock_t wq_lock;
-
- struct notifier_block iotg_notifier;
-};
-
-static inline
-struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg)
-{
- return container_of(iotg, struct langwell_otg, iotg);
-}
-
-#endif /* __LANGWELL_OTG_H__ */
};
#define IREQ_CACHE_FLUSH 0x0001
-extern int enable_hs;
+extern bool enable_hs;
#endif /* __HCI_H */
* @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
* search for IBSSs with a different BSSID.
* @channel: The channel to use if no IBSS can be found to join.
+ * @channel_type: channel type (HT mode)
* @channel_fixed: The channel should be fixed -- do not search for
* IBSSs to join on other channels.
* @ie: information element(s) to include in the beacon
* configured as RX antennas. Antenna configuration commands will be
* rejected unless this or @available_antennas_tx is set.
*
+ * @probe_resp_offload:
+ * Bitmap of supported protocols for probe response offloading.
+ * See &enum nl80211_probe_resp_offload_support_attr. Only valid
+ * when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+ *
* @max_remain_on_channel_duration: Maximum time a remain-on-channel operation
* may request, if implemented.
*
ptr = ng->ptr[id - 1];
rcu_read_unlock();
+ BUG_ON(!ptr);
return ptr;
}
#endif
#ifndef _NETPRIO_CGROUP_H
#define _NETPRIO_CGROUP_H
-#include <linux/module.h>
#include <linux/cgroup.h>
#include <linux/hardirq.h>
#include <linux/rcupdate.h>
#include <linux/uaccess.h>
#include <linux/memcontrol.h>
#include <linux/res_counter.h>
+#include <linux/jump_label.h>
#include <linux/filter.h>
#include <linux/rculist_nulls.h>
* @sk_ack_backlog: current listen backlog
* @sk_max_ack_backlog: listen backlog set in listen()
* @sk_priority: %SO_PRIORITY setting
+ * @sk_cgrp_prioidx: socket group's priority map index
* @sk_type: socket type (%SOCK_STREAM, etc)
* @sk_protocol: which protocol this socket belongs in this network family
* @sk_peer_pid: &struct pid for this socket's peer
#define sk_refcnt_debug_release(sk) do { } while (0)
#endif /* SOCK_REFCNT_DEBUG */
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_NET)
extern struct jump_label_key memcg_socket_limit_enabled;
static inline struct cg_proto *parent_cg_proto(struct proto *proto,
struct cg_proto *cg_proto)
struct res_counter *fail;
int ret;
- ret = res_counter_charge(prot->memory_allocated,
- amt << PAGE_SHIFT, &fail);
-
+ ret = res_counter_charge_nofail(prot->memory_allocated,
+ amt << PAGE_SHIFT, &fail);
if (ret < 0)
*parent_status = OVER_LIMIT;
}
}
static inline void
-sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status)
+sk_memory_allocated_sub(struct sock *sk, int amt)
{
struct proto *prot = sk->sk_prot;
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
- parent_status != OVER_LIMIT) /* Otherwise was uncharged already */
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
memcg_memory_allocated_sub(sk->sk_cgrp, amt);
atomic_long_sub(amt, prot->memory_allocated);
#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
+extern void tcp_init_mem(struct net *net);
+
extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how);
if (S_ISREG(mode)) {
struct mqueue_inode_info *info;
- struct task_struct *p = current;
unsigned long mq_bytes, mq_msg_tblsz;
inode->i_fop = &mqueue_file_operations;
spin_lock(&mq_lock);
if (u->mq_bytes + mq_bytes < u->mq_bytes ||
- u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
+ u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
spin_unlock(&mq_lock);
/* mqueue_evict_inode() releases info->messages */
ret = -EMFILE;
case SHM_LOCK:
case SHM_UNLOCK:
{
- struct file *uninitialized_var(shm_file);
-
- lru_add_drain_all(); /* drain pagevecs to lru lists */
+ struct file *shm_file;
shp = shm_lock_check(ns, shmid);
if (IS_ERR(shp)) {
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock;
-
- if(cmd==SHM_LOCK) {
+
+ shm_file = shp->shm_file;
+ if (is_file_hugepages(shm_file))
+ goto out_unlock;
+
+ if (cmd == SHM_LOCK) {
struct user_struct *user = current_user();
- if (!is_file_hugepages(shp->shm_file)) {
- err = shmem_lock(shp->shm_file, 1, user);
- if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
- shp->shm_perm.mode |= SHM_LOCKED;
- shp->mlock_user = user;
- }
+ err = shmem_lock(shm_file, 1, user);
+ if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
+ shp->shm_perm.mode |= SHM_LOCKED;
+ shp->mlock_user = user;
}
- } else if (!is_file_hugepages(shp->shm_file)) {
- shmem_lock(shp->shm_file, 0, shp->mlock_user);
- shp->shm_perm.mode &= ~SHM_LOCKED;
- shp->mlock_user = NULL;
+ goto out_unlock;
}
+
+ /* SHM_UNLOCK */
+ if (!(shp->shm_perm.mode & SHM_LOCKED))
+ goto out_unlock;
+ shmem_lock(shm_file, 0, shp->mlock_user);
+ shp->shm_perm.mode &= ~SHM_LOCKED;
+ shp->mlock_user = NULL;
+ get_file(shm_file);
shm_unlock(shp);
+ shmem_unlock_mapping(shm_file->f_mapping);
+ fput(shm_file);
goto out;
}
case IPC_RMID:
/**
* audit_syscall_exit - deallocate audit context after a system call
- * @pt_regs: syscall registers
+ * @success: success value of the syscall
+ * @return_code: return value of the syscall
*
* Tear down after system call. If the audit context has been marked as
* auditable (either because of the AUDIT_RECORD_CONTEXT state from
- * filtering, or because some other part of the kernel write an audit
+ * filtering, or because some other part of the kernel wrote an audit
* message), then write out the syscall information. In call cases,
* free the names stored from getname().
*/
}
err = alloc_callchain_buffers();
- if (err)
- release_callchain_buffers();
exit:
mutex_unlock(&callchain_mutex);
* here.
*/
if (is_cgroup_event(event))
- run_end = perf_event_time(event);
+ run_end = perf_cgroup_event_time(event);
else if (ctx->is_active)
run_end = ctx->time;
else
/* Early boot. kretprobe_table_locks not yet initialized. */
return;
+ INIT_HLIST_HEAD(&empty_rp);
hash = hash_ptr(tk, KPROBE_HASH_BITS);
head = &kretprobe_inst_table[hash];
kretprobe_table_lock(hash, &flags);
recycle_rp_inst(ri, &empty_rp);
}
kretprobe_table_unlock(hash, &flags);
- INIT_HLIST_HEAD(&empty_rp);
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
hlist_del(&ri->hlist);
kfree(ri);
printk("done.\n");
}
+void thaw_kernel_threads(void)
+{
+ struct task_struct *g, *p;
+
+ pm_nosig_freezing = false;
+ printk("Restarting kernel threads ... ");
+
+ thaw_workqueues();
+
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
+ __thaw_task(p);
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+
+ schedule();
+ printk("done.\n");
+}
unsigned int res;
res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK);
- res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE);
+ res += DIV_ROUND_UP(res * sizeof(struct bm_block),
+ LINKED_PAGE_DATA_SIZE);
return 2 * res;
}
swsusp_free();
memset(&data->handle, 0, sizeof(struct snapshot_handle));
data->ready = 0;
+ /*
+ * It is necessary to thaw kernel threads here, because
+ * SNAPSHOT_CREATE_IMAGE may be invoked directly after
+ * SNAPSHOT_FREE. In that case, if kernel threads were not
+ * thawed, the preallocation of memory carried out by
+ * hibernation_snapshot() might run into problems (i.e. it
+ * might fail or even deadlock).
+ */
+ thaw_kernel_threads();
break;
case SNAPSHOT_PREF_IMAGE_SIZE:
static int nfakewriters = 4; /* # fake writer threads */
static int stat_interval; /* Interval between stats, in seconds. */
/* Defaults to "only at end of test". */
-static int verbose; /* Print more debug info. */
-static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
+static bool verbose; /* Print more debug info. */
+static bool test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
static int stutter = 5; /* Start/stop testing interval (in sec) */
static int irqreader = 1; /* RCU readers from irq (timers). */
* Execute random CPU-hotplug operations at the interval specified
* by the onoff_interval.
*/
-static int
+static int __cpuinit
rcu_torture_onoff(void *arg)
{
int cpu;
return 0;
}
-static int
+static int __cpuinit
rcu_torture_onoff_init(void)
{
if (onoff_interval <= 0)
return ret;
}
+int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
+ struct res_counter **limit_fail_at)
+{
+ int ret, r;
+ unsigned long flags;
+ struct res_counter *c;
+
+ r = ret = 0;
+ *limit_fail_at = NULL;
+ local_irq_save(flags);
+ for (c = counter; c != NULL; c = c->parent) {
+ spin_lock(&c->lock);
+ r = res_counter_charge_locked(c, val);
+ if (r)
+ c->usage += val;
+ spin_unlock(&c->lock);
+ if (r < 0 && ret == 0) {
+ *limit_fail_at = c;
+ ret = r;
+ }
+ }
+ local_irq_restore(flags);
+
+ return ret;
+}
void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
{
if (WARN_ON(counter->usage < val))
* cpupri_set - update the cpu priority setting
* @cp: The cpupri context
* @cpu: The target cpu
- * @pri: The priority (INVALID-RT99) to assign to this CPU
+ * @newpri: The priority (INVALID-RT99) to assign to this CPU
*
* Note: Assumes cpu_rq(cpu)->lock is locked
*
/**
* cpupri_init - initialize the cpupri structure
* @cp: The cpupri context
- * @bootmem: true if allocations need to use bootmem
*
* Returns: -ENOMEM if memory fails.
*/
{
struct hstate *h = hstate_vma(vma);
int ret = VM_FAULT_SIGBUS;
+ int anon_rmap = 0;
pgoff_t idx;
unsigned long size;
struct page *page;
spin_lock(&inode->i_lock);
inode->i_blocks += blocks_per_huge_page(h);
spin_unlock(&inode->i_lock);
- page_dup_rmap(page);
} else {
lock_page(page);
if (unlikely(anon_vma_prepare(vma))) {
ret = VM_FAULT_OOM;
goto backout_unlocked;
}
- hugepage_add_new_anon_rmap(page, vma, address);
+ anon_rmap = 1;
}
} else {
/*
VM_FAULT_SET_HINDEX(h - hstates);
goto backout_unlocked;
}
- page_dup_rmap(page);
}
/*
if (!huge_pte_none(huge_ptep_get(ptep)))
goto backout;
+ if (anon_rmap)
+ hugepage_add_new_anon_rmap(page, vma, address);
+ else
+ page_dup_rmap(page);
new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
&& (vma->vm_flags & VM_SHARED)));
set_huge_pte_at(mm, address, ptep, new_pte);
if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
end = memblock.current_limit;
- /* adjust @start to avoid underflow and allocating the first page */
- start = max3(start, size, (phys_addr_t)PAGE_SIZE);
+ /* avoid allocating the first page */
+ start = max_t(phys_addr_t, start, PAGE_SIZE);
end = max(start, end);
for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
this_start = clamp(this_start, start, end);
this_end = clamp(this_end, start, end);
+ if (this_end < size)
+ continue;
+
cand = round_down(this_end - size, align);
if (cand >= this_start)
return cand;
static bool mem_cgroup_is_root(struct mem_cgroup *memcg);
void sock_update_memcg(struct sock *sk)
{
- if (static_branch(&memcg_socket_limit_enabled)) {
+ if (mem_cgroup_sockets_enabled) {
struct mem_cgroup *memcg;
BUG_ON(!sk->sk_prot->proto_cgroup);
void sock_release_memcg(struct sock *sk)
{
- if (static_branch(&memcg_socket_limit_enabled) && sk->sk_cgrp) {
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
struct mem_cgroup *memcg;
WARN_ON(!sk->sk_cgrp->memcg);
memcg = sk->sk_cgrp->memcg;
ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
else
ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
- __mem_cgroup_commit_charge(memcg, page, 1, pc, ctype);
+ __mem_cgroup_commit_charge(memcg, newpage, 1, pc, ctype);
return ret;
}
}
if (likely(!non_swap_entry(entry)))
rss[MM_SWAPENTS]++;
- else if (is_write_migration_entry(entry) &&
- is_cow_mapping(vm_flags)) {
- /*
- * COW mappings require pages in both parent
- * and child to be set to read.
- */
- make_migration_entry_read(&entry);
- pte = swp_entry_to_pte(entry);
- set_pte_at(src_mm, addr, src_pte, pte);
+ else if (is_migration_entry(entry)) {
+ page = migration_entry_to_page(entry);
+
+ if (PageAnon(page))
+ rss[MM_ANONPAGES]++;
+ else
+ rss[MM_FILEPAGES]++;
+
+ if (is_write_migration_entry(entry) &&
+ is_cow_mapping(vm_flags)) {
+ /*
+ * COW mappings require pages in both
+ * parent and child to be set to read.
+ */
+ make_migration_entry_read(&entry);
+ pte = swp_entry_to_pte(entry);
+ set_pte_at(src_mm, addr, src_pte, pte);
+ }
}
}
goto out_set_pte;
if (!non_swap_entry(entry))
rss[MM_SWAPENTS]--;
+ else if (is_migration_entry(entry)) {
+ struct page *page;
+
+ page = migration_entry_to_page(entry);
+
+ if (PageAnon(page))
+ rss[MM_ANONPAGES]--;
+ else
+ rss[MM_FILEPAGES]--;
+ }
if (unlikely(!free_swap_and_cache(entry)))
print_bad_pte(vma, addr, ptent, NULL);
}
bool is_pageblock_removable_nolock(struct page *page)
{
- struct zone *zone = page_zone(page);
+ struct zone *zone;
+ unsigned long pfn;
+
+ /*
+ * We have to be careful here because we are iterating over memory
+ * sections which are not zone aware so we might end up outside of
+ * the zone but still within the section.
+ * We have to take care about the node as well. If the node is offline
+ * its NODE_DATA will be NULL - see page_zone.
+ */
+ if (!node_online(page_to_nid(page)))
+ return false;
+
+ zone = page_zone(page);
+ pfn = page_to_pfn(page);
+ if (zone->zone_start_pfn > pfn ||
+ zone->zone_start_pfn + zone->spanned_pages <= pfn)
+ return false;
+
return __count_immobile_pages(zone, page, 0);
}
/*
* Pagevec may contain swap entries, so shuffle up pages before releasing.
*/
-static void shmem_pagevec_release(struct pagevec *pvec)
+static void shmem_deswap_pagevec(struct pagevec *pvec)
{
int i, j;
pvec->pages[j++] = page;
}
pvec->nr = j;
- pagevec_release(pvec);
+}
+
+/*
+ * SysV IPC SHM_UNLOCK restore Unevictable pages to their evictable lists.
+ */
+void shmem_unlock_mapping(struct address_space *mapping)
+{
+ struct pagevec pvec;
+ pgoff_t indices[PAGEVEC_SIZE];
+ pgoff_t index = 0;
+
+ pagevec_init(&pvec, 0);
+ /*
+ * Minor point, but we might as well stop if someone else SHM_LOCKs it.
+ */
+ while (!mapping_unevictable(mapping)) {
+ /*
+ * Avoid pagevec_lookup(): find_get_pages() returns 0 as if it
+ * has finished, if it hits a row of PAGEVEC_SIZE swap entries.
+ */
+ pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
+ PAGEVEC_SIZE, pvec.pages, indices);
+ if (!pvec.nr)
+ break;
+ index = indices[pvec.nr - 1] + 1;
+ shmem_deswap_pagevec(&pvec);
+ check_move_unevictable_pages(pvec.pages, pvec.nr);
+ pagevec_release(&pvec);
+ cond_resched();
+ }
}
/*
}
unlock_page(page);
}
- shmem_pagevec_release(&pvec);
+ shmem_deswap_pagevec(&pvec);
+ pagevec_release(&pvec);
mem_cgroup_uncharge_end();
cond_resched();
index++;
continue;
}
if (index == start && indices[0] > end) {
- shmem_pagevec_release(&pvec);
+ shmem_deswap_pagevec(&pvec);
+ pagevec_release(&pvec);
break;
}
mem_cgroup_uncharge_start();
}
unlock_page(page);
}
- shmem_pagevec_release(&pvec);
+ shmem_deswap_pagevec(&pvec);
+ pagevec_release(&pvec);
mem_cgroup_uncharge_end();
index++;
}
user_shm_unlock(inode->i_size, user);
info->flags &= ~VM_LOCKED;
mapping_clear_unevictable(file->f_mapping);
- /*
- * Ensure that a racing putback_lru_page() can see
- * the pages of this mapping are evictable when we
- * skip them due to !PageLRU during the scan.
- */
- smp_mb__after_clear_bit();
- scan_mapping_unevictable_pages(file->f_mapping);
}
retval = 0;
return 0;
}
+void shmem_unlock_mapping(struct address_space *mapping)
+{
+}
+
void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
{
truncate_inode_pages_range(inode->i_mapping, lstart, lend);
#include <linux/buffer_head.h> /* for try_to_release_page(),
buffer_heads_over_limit */
#include <linux/mm_inline.h>
-#include <linux/pagevec.h>
#include <linux/backing-dev.h>
#include <linux/rmap.h>
#include <linux/topology.h>
* When racing with an mlock or AS_UNEVICTABLE clearing
* (page is unlocked) make sure that if the other thread
* does not observe our setting of PG_lru and fails
- * isolation/check_move_unevictable_page,
+ * isolation/check_move_unevictable_pages,
* we see PG_mlocked/AS_UNEVICTABLE cleared below and move
* the page back to the evictable list.
*
return 1;
}
+#ifdef CONFIG_SHMEM
/**
- * check_move_unevictable_page - check page for evictability and move to appropriate zone lru list
- * @page: page to check evictability and move to appropriate lru list
- * @zone: zone page is in
+ * check_move_unevictable_pages - check pages for evictability and move to appropriate zone lru list
+ * @pages: array of pages to check
+ * @nr_pages: number of pages to check
*
- * Checks a page for evictability and moves the page to the appropriate
- * zone lru list.
+ * Checks pages for evictability and moves them to the appropriate lru list.
*
- * Restrictions: zone->lru_lock must be held, page must be on LRU and must
- * have PageUnevictable set.
+ * This function is only used for SysV IPC SHM_UNLOCK.
*/
-static void check_move_unevictable_page(struct page *page, struct zone *zone)
+void check_move_unevictable_pages(struct page **pages, int nr_pages)
{
struct lruvec *lruvec;
+ struct zone *zone = NULL;
+ int pgscanned = 0;
+ int pgrescued = 0;
+ int i;
- VM_BUG_ON(PageActive(page));
-retry:
- ClearPageUnevictable(page);
- if (page_evictable(page, NULL)) {
- enum lru_list l = page_lru_base_type(page);
-
- __dec_zone_state(zone, NR_UNEVICTABLE);
- lruvec = mem_cgroup_lru_move_lists(zone, page,
- LRU_UNEVICTABLE, l);
- list_move(&page->lru, &lruvec->lists[l]);
- __inc_zone_state(zone, NR_INACTIVE_ANON + l);
- __count_vm_event(UNEVICTABLE_PGRESCUED);
- } else {
- /*
- * rotate unevictable list
- */
- SetPageUnevictable(page);
- lruvec = mem_cgroup_lru_move_lists(zone, page, LRU_UNEVICTABLE,
- LRU_UNEVICTABLE);
- list_move(&page->lru, &lruvec->lists[LRU_UNEVICTABLE]);
- if (page_evictable(page, NULL))
- goto retry;
- }
-}
-
-/**
- * scan_mapping_unevictable_pages - scan an address space for evictable pages
- * @mapping: struct address_space to scan for evictable pages
- *
- * Scan all pages in mapping. Check unevictable pages for
- * evictability and move them to the appropriate zone lru list.
- */
-void scan_mapping_unevictable_pages(struct address_space *mapping)
-{
- pgoff_t next = 0;
- pgoff_t end = (i_size_read(mapping->host) + PAGE_CACHE_SIZE - 1) >>
- PAGE_CACHE_SHIFT;
- struct zone *zone;
- struct pagevec pvec;
-
- if (mapping->nrpages == 0)
- return;
-
- pagevec_init(&pvec, 0);
- while (next < end &&
- pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
- int i;
- int pg_scanned = 0;
-
- zone = NULL;
-
- for (i = 0; i < pagevec_count(&pvec); i++) {
- struct page *page = pvec.pages[i];
- pgoff_t page_index = page->index;
- struct zone *pagezone = page_zone(page);
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page = pages[i];
+ struct zone *pagezone;
- pg_scanned++;
- if (page_index > next)
- next = page_index;
- next++;
+ pgscanned++;
+ pagezone = page_zone(page);
+ if (pagezone != zone) {
+ if (zone)
+ spin_unlock_irq(&zone->lru_lock);
+ zone = pagezone;
+ spin_lock_irq(&zone->lru_lock);
+ }
- if (pagezone != zone) {
- if (zone)
- spin_unlock_irq(&zone->lru_lock);
- zone = pagezone;
- spin_lock_irq(&zone->lru_lock);
- }
+ if (!PageLRU(page) || !PageUnevictable(page))
+ continue;
- if (PageLRU(page) && PageUnevictable(page))
- check_move_unevictable_page(page, zone);
+ if (page_evictable(page, NULL)) {
+ enum lru_list lru = page_lru_base_type(page);
+
+ VM_BUG_ON(PageActive(page));
+ ClearPageUnevictable(page);
+ __dec_zone_state(zone, NR_UNEVICTABLE);
+ lruvec = mem_cgroup_lru_move_lists(zone, page,
+ LRU_UNEVICTABLE, lru);
+ list_move(&page->lru, &lruvec->lists[lru]);
+ __inc_zone_state(zone, NR_INACTIVE_ANON + lru);
+ pgrescued++;
}
- if (zone)
- spin_unlock_irq(&zone->lru_lock);
- pagevec_release(&pvec);
-
- count_vm_events(UNEVICTABLE_PGSCANNED, pg_scanned);
}
+ if (zone) {
+ __count_vm_events(UNEVICTABLE_PGRESCUED, pgrescued);
+ __count_vm_events(UNEVICTABLE_PGSCANNED, pgscanned);
+ spin_unlock_irq(&zone->lru_lock);
+ }
}
+#endif /* CONFIG_SHMEM */
static void warn_scan_unevictable_pages(void)
{
#define AUTO_OFF_TIMEOUT 2000
-int enable_hs;
+bool enable_hs;
static void hci_rx_work(struct work_struct *work);
static void hci_cmd_work(struct work_struct *work);
{
struct caif_net *caifn;
caifn = net_generic(net, caif_net_id);
- if (!caifn)
- return NULL;
return caifn->cfg;
}
EXPORT_SYMBOL(get_cfcnfg);
{
struct caif_net *caifn;
caifn = net_generic(net, caif_net_id);
- if (!caifn)
- return NULL;
return &caifn->caifdevs;
}
struct caif_device_entry *caifd;
caifdevs = caif_device_list(dev_net(dev));
- if (!caifdevs)
- return NULL;
caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
if (!caifd)
struct caif_device_entry_list *caifdevs =
caif_device_list(dev_net(dev));
struct caif_device_entry *caifd;
- if (!caifdevs)
- return NULL;
list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
if (caifd->netdev == dev)
struct caif_device_entry_list *caifdevs;
caifdevs = caif_device_list(dev_net(dev));
- if (!cfg || !caifdevs)
- return;
caifd = caif_device_alloc(dev);
if (!caifd)
return;
cfg = get_cfcnfg(dev_net(dev));
caifdevs = caif_device_list(dev_net(dev));
- if (!cfg || !caifdevs)
- return 0;
caifd = caif_get(dev);
if (caifd == NULL && dev->type != ARPHRD_CAIF)
static int caif_init_net(struct net *net)
{
struct caif_net *caifn = net_generic(net, caif_net_id);
- if (WARN_ON(!caifn))
- return -EINVAL;
-
INIT_LIST_HEAD(&caifn->caifdevs.list);
mutex_init(&caifn->caifdevs.lock);
caif_device_list(net);
struct cfcnfg *cfg = get_cfcnfg(net);
- if (!cfg || !caifdevs)
- return;
-
rtnl_lock();
mutex_lock(&caifdevs->lock);
{
int result;
- result = register_pernet_device(&caif_net_ops);
+ result = register_pernet_subsys(&caif_net_ops);
if (result)
return result;
static void __exit caif_device_exit(void)
{
- unregister_pernet_device(&caif_net_ops);
+ unregister_pernet_subsys(&caif_net_ops);
unregister_netdevice_notifier(&caif_device_notifier);
dev_remove_pack(&caif_packet_type);
}
int err;
struct cfctrl_link_param param;
struct cfcnfg *cfg = get_cfcnfg(net);
- caif_assert(cfg != NULL);
rcu_read_lock();
err = caif_connect_req_to_link_param(cfg, conn_req, ¶m);
case ETHTOOL_GRXCSUM:
case ETHTOOL_GTXCSUM:
case ETHTOOL_GSG:
+ case ETHTOOL_GSSET_INFO:
case ETHTOOL_GSTRINGS:
case ETHTOOL_GTSO:
case ETHTOOL_GPERMADDR:
#include <linux/skbuff.h>
+#include <linux/export.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/if_vlan.h>
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
+static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
+
+static struct net_generic *net_alloc_generic(void)
+{
+ struct net_generic *ng;
+ size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
+
+ ng = kzalloc(generic_size, GFP_KERNEL);
+ if (ng)
+ ng->len = max_gen_ptrs;
+
+ return ng;
+}
+
static int net_assign_generic(struct net *net, int id, void *data)
{
struct net_generic *ng, *old_ng;
if (old_ng->len >= id)
goto assign;
- ng = kzalloc(sizeof(struct net_generic) +
- id * sizeof(void *), GFP_KERNEL);
+ ng = net_alloc_generic();
if (ng == NULL)
return -ENOMEM;
* the old copy for kfree after a grace period.
*/
- ng->len = id;
memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
rcu_assign_pointer(net->gen, ng);
goto out;
}
-static struct net_generic *net_alloc_generic(void)
-{
- struct net_generic *ng;
- size_t generic_size = sizeof(struct net_generic) +
- INITIAL_NET_GEN_PTRS * sizeof(void *);
-
- ng = kzalloc(generic_size, GFP_KERNEL);
- if (ng)
- ng->len = INITIAL_NET_GEN_PTRS;
-
- return ng;
-}
#ifdef CONFIG_NET_NS
static struct kmem_cache *net_cachep;
}
return error;
}
+ max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
}
error = __register_pernet_operations(list, ops);
if (error) {
return i;
}
-static unsigned long num_arg(const char __user * user_buffer,
- unsigned long maxlen, unsigned long *num)
+static long num_arg(const char __user *user_buffer, unsigned long maxlen,
+ unsigned long *num)
{
int i;
*num = 0;
if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev),
+ min_ifinfo_dump_size);
+
return err;
}
/* Alas. Undo changes. */
sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
- sk_memory_allocated_sub(sk, amt, parent_status);
+ sk_memory_allocated_sub(sk, amt);
return 0;
}
void __sk_mem_reclaim(struct sock *sk)
{
sk_memory_allocated_sub(sk,
- sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, 0);
+ sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT);
sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
if (sk_under_memory_pressure(sk) &&
smallest_size = tb->num_owners;
smallest_rover = rover;
if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
- spin_unlock(&head->lock);
snum = smallest_rover;
- goto have_snum;
+ goto tb_found;
}
}
+ if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+ snum = rover;
+ goto tb_found;
+ }
goto next;
}
break;
if (register_netdevice(dev) < 0)
goto failed_free;
+ /* Can use a lockless transmit, unless we generate output sequences */
+ if (!(nt->parms.o_flags & GRE_SEQ))
+ dev->features |= NETIF_F_LLTX;
+
dev_hold(dev);
ipgre_tunnel_link(ign, nt);
return nt;
SNMP_MIB_ITEM("TCPPartialUndo", LINUX_MIB_TCPPARTIALUNDO),
SNMP_MIB_ITEM("TCPDSACKUndo", LINUX_MIB_TCPDSACKUNDO),
SNMP_MIB_ITEM("TCPLossUndo", LINUX_MIB_TCPLOSSUNDO),
- SNMP_MIB_ITEM("TCPLoss", LINUX_MIB_TCPLOSS),
SNMP_MIB_ITEM("TCPLostRetransmit", LINUX_MIB_TCPLOSTRETRANSMIT),
SNMP_MIB_ITEM("TCPRenoFailures", LINUX_MIB_TCPRENOFAILURES),
SNMP_MIB_ITEM("TCPSackFailures", LINUX_MIB_TCPSACKFAILURES),
net->ipv4.sysctl_rt_cache_rebuild_count = 4;
+ tcp_init_mem(net);
limit = nr_free_buffer_pages() / 8;
limit = max(limit, 128UL);
net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
}
__setup("thash_entries=", set_thash_entries);
+void tcp_init_mem(struct net *net)
+{
+ /* Set per-socket limits to no more than 1/128 the pressure threshold */
+ unsigned long limit = nr_free_buffer_pages() / 8;
+ limit = max(limit, 128UL);
+ net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
+ net->ipv4.sysctl_tcp_mem[1] = limit;
+ net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
+}
+
void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
sysctl_tcp_max_orphans = cnt / 2;
sysctl_max_syn_backlog = max(128, cnt / 256);
- /* Set per-socket limits to no more than 1/128 the pressure threshold */
- limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1])
- << (PAGE_SHIFT - 7);
+ tcp_init_mem(&init_net);
+ limit = nr_free_buffer_pages() / 8;
+ limit = max(limit, 128UL);
max_share = min(4UL*1024*1024, limit);
sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
{
ca->cnt = 0;
ca->last_max_cwnd = 0;
- ca->loss_cwnd = 0;
ca->last_cwnd = 0;
ca->last_time = 0;
ca->epoch_start = 0;
static void bictcp_init(struct sock *sk)
{
- bictcp_reset(inet_csk_ca(sk));
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ bictcp_reset(ca);
+ ca->loss_cwnd = 0;
+
if (initial_ssthresh)
tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
}
}
/* if in slow start or link utilization is very low */
- if (ca->loss_cwnd == 0) {
+ if (ca->last_max_cwnd == 0) {
if (ca->cnt > 20) /* increase cwnd 5% per RTT */
ca->cnt = 20;
}
{
const struct tcp_sock *tp = tcp_sk(sk);
const struct bictcp *ca = inet_csk_ca(sk);
- return max(tp->snd_cwnd, ca->last_max_cwnd);
+ return max(tp->snd_cwnd, ca->loss_cwnd);
}
static void bictcp_state(struct sock *sk, u8 new_state)
{
ca->cnt = 0;
ca->last_max_cwnd = 0;
- ca->loss_cwnd = 0;
ca->last_cwnd = 0;
ca->last_time = 0;
ca->bic_origin_point = 0;
static void bictcp_init(struct sock *sk)
{
- bictcp_reset(inet_csk_ca(sk));
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ bictcp_reset(ca);
+ ca->loss_cwnd = 0;
if (hystart)
bictcp_hystart_reset(sk);
* The initial growth of cubic function may be too conservative
* when the available bandwidth is still unknown.
*/
- if (ca->loss_cwnd == 0 && ca->cnt > 20)
+ if (ca->last_max_cwnd == 0 && ca->cnt > 20)
ca->cnt = 20; /* increase cwnd 5% per RTT */
/* TCP Friendly */
{
struct bictcp *ca = inet_csk_ca(sk);
- return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
+ return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
}
static void bictcp_state(struct sock *sk, u8 new_state)
#define FLAG_SYN_ACKED 0x10 /* This ACK acknowledged SYN. */
#define FLAG_DATA_SACKED 0x20 /* New SACK. */
#define FLAG_ECE 0x40 /* ECE in this ACK */
-#define FLAG_DATA_LOST 0x80 /* SACK detected data lossage. */
#define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/
#define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */
#define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
* These 6 states form finite state machine, controlled by the following events:
* 1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue())
* 2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue())
- * 3. Loss detection event of one of three flavors:
+ * 3. Loss detection event of two flavors:
* A. Scoreboard estimator decided the packet is lost.
* A'. Reno "three dupacks" marks head of queue lost.
- * A''. Its FACK modfication, head until snd.fack is lost.
- * B. SACK arrives sacking data transmitted after never retransmitted
- * hole was sent out.
- * C. SACK arrives sacking SND.NXT at the moment, when the
+ * A''. Its FACK modification, head until snd.fack is lost.
+ * B. SACK arrives sacking SND.NXT at the moment, when the
* segment was retransmitted.
* 4. D-SACK added new rule: D-SACK changes any tag to S.
*
}
/* Check for lost retransmit. This superb idea is borrowed from "ratehalving".
- * Event "C". Later note: FACK people cheated me again 8), we have to account
+ * Event "B". Later note: FACK people cheated me again 8), we have to account
* for reordering! Ugly, but should help.
*
* Search retransmitted skbs from write_queue that were sent when snd_nxt was
if (found_dup_sack && ((i + 1) == first_sack_index))
next_dup = &sp[i + 1];
- /* Event "B" in the comment above. */
- if (after(end_seq, tp->high_seq))
- state.flag |= FLAG_DATA_LOST;
-
/* Skip too early cached blocks */
while (tcp_sack_cache_ok(tp, cache) &&
!before(start_seq, cache->end_seq))
tcp_verify_left_out(tp);
}
-/* Mark head of queue up as lost. With RFC3517 SACK, the packets is
- * is against sacked "cnt", otherwise it's against facked "cnt"
+/* Detect loss in event "A" above by marking head of queue up as lost.
+ * For FACK or non-SACK(Reno) senders, the first "packets" number of segments
+ * are considered lost. For RFC3517 SACK, a segment is considered lost if it
+ * has at least tp->reordering SACKed seqments above it; "packets" refers to
+ * the maximum SACKed segments to pass before reaching this limit.
*/
static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
{
int cnt, oldcnt;
int err;
unsigned int mss;
+ /* Use SACK to deduce losses of new sequences sent during recovery */
+ const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq;
WARN_ON(packets > tp->packets_out);
if (tp->lost_skb_hint) {
tp->lost_skb_hint = skb;
tp->lost_cnt_hint = cnt;
- if (after(TCP_SKB_CB(skb)->end_seq, tp->high_seq))
+ if (after(TCP_SKB_CB(skb)->end_seq, loss_high))
break;
oldcnt = cnt;
if (tcp_check_sack_reneging(sk, flag))
return;
- /* C. Process data loss notification, provided it is valid. */
- if (tcp_is_fack(tp) && (flag & FLAG_DATA_LOST) &&
- before(tp->snd_una, tp->high_seq) &&
- icsk->icsk_ca_state != TCP_CA_Open &&
- tp->fackets_out > tp->reordering) {
- tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering, 0);
- NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSS);
- }
-
- /* D. Check consistency of the current state. */
+ /* C. Check consistency of the current state. */
tcp_verify_left_out(tp);
- /* E. Check state exit conditions. State can be terminated
+ /* D. Check state exit conditions. State can be terminated
* when high_seq is ACKed. */
if (icsk->icsk_ca_state == TCP_CA_Open) {
WARN_ON(tp->retrans_out != 0);
}
}
- /* F. Process state. */
+ /* E. Process state. */
switch (icsk->icsk_ca_state) {
case TCP_CA_Recovery:
if (!(flag & FLAG_SND_UNA_ADVANCED)) {
arg.iov[0].iov_len = sizeof(rep.th);
#ifdef CONFIG_TCP_MD5SIG
- key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
+ key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
if (key) {
rep.opt[0] = htonl((TCPOPT_NOP << 24) |
(TCPOPT_NOP << 16) |
sk_mem_uncharge(sk, len);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
- /* Any change of skb->len requires recalculation of tso
- * factor and mss.
- */
+ /* Any change of skb->len requires recalculation of tso factor. */
if (tcp_skb_pcount(skb) > 1)
- tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk));
+ tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb));
return 0;
}
rcu_read_unlock();
}
-static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
+static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
{
struct net *net;
+ int old;
+
+ if (!rtnl_trylock())
+ return restart_syscall();
net = (struct net *)table->extra2;
- if (p == &net->ipv6.devconf_dflt->forwarding)
- return 0;
+ old = *p;
+ *p = newf;
- if (!rtnl_trylock()) {
- /* Restore the original values before restarting */
- *p = old;
- return restart_syscall();
+ if (p == &net->ipv6.devconf_dflt->forwarding) {
+ rtnl_unlock();
+ return 0;
}
if (p == &net->ipv6.devconf_all->forwarding) {
- __s32 newf = net->ipv6.devconf_all->forwarding;
net->ipv6.devconf_dflt->forwarding = newf;
addrconf_forward_change(net, newf);
- } else if ((!*p) ^ (!old))
+ } else if ((!newf) ^ (!old))
dev_forward_change((struct inet6_dev *)table->extra1);
rtnl_unlock();
- if (*p)
+ if (newf)
rt6_purge_dflt_routers(net);
return 1;
}
int *valp = ctl->data;
int val = *valp;
loff_t pos = *ppos;
+ ctl_table lctl;
int ret;
- ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ /*
+ * ctl->data points to idev->cnf.forwarding, we should
+ * not modify it until we get the rtnl lock.
+ */
+ lctl = *ctl;
+ lctl.data = &val;
+
+ ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
if (write)
ret = addrconf_fixup_forwarding(ctl, valp, val);
rcu_read_unlock();
}
-static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
+static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
{
struct net *net;
+ int old;
+
+ if (!rtnl_trylock())
+ return restart_syscall();
net = (struct net *)table->extra2;
+ old = *p;
+ *p = newf;
- if (p == &net->ipv6.devconf_dflt->disable_ipv6)
+ if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
+ rtnl_unlock();
return 0;
-
- if (!rtnl_trylock()) {
- /* Restore the original values before restarting */
- *p = old;
- return restart_syscall();
}
if (p == &net->ipv6.devconf_all->disable_ipv6) {
- __s32 newf = net->ipv6.devconf_all->disable_ipv6;
net->ipv6.devconf_dflt->disable_ipv6 = newf;
addrconf_disable_change(net, newf);
- } else if ((!*p) ^ (!old))
+ } else if ((!newf) ^ (!old))
dev_disable_change((struct inet6_dev *)table->extra1);
rtnl_unlock();
int *valp = ctl->data;
int val = *valp;
loff_t pos = *ppos;
+ ctl_table lctl;
int ret;
- ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ /*
+ * ctl->data points to idev->cnf.disable_ipv6, we should
+ * not modify it until we get the rtnl lock.
+ */
+ lctl = *ctl;
+ lctl.data = &val;
+
+ ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
if (write)
ret = addrconf_disable_ipv6(ctl, valp, val);
#ifdef CONFIG_TCP_MD5SIG
if (sk)
- key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
+ key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
#endif
if (th->ack)
{
int rc;
- if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
- goto drop;
-
- nf_reset(skb);
-
/* Charge it to the socket, dropping if the queue is full. */
rc = sock_queue_rcv_skb(sk, skb);
if (rc < 0)
struct sk_buff *skb = NULL;
struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk);
+ unsigned long cpu_flags;
size_t copied = 0;
u32 peek_seq = 0;
u32 *seq;
goto copy_uaddr;
if (!(flags & MSG_PEEK)) {
+ spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
sk_eat_skb(sk, skb, 0);
+ spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
*seq = 0;
}
llc_cmsg_rcv(msg, skb);
if (!(flags & MSG_PEEK)) {
+ spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
sk_eat_skb(sk, skb, 0);
+ spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
*seq = 0;
}
key, &key_##name##_ops);
void ieee80211_debugfs_key_add(struct ieee80211_key *key)
- {
+{
static int keycount;
- char buf[50];
+ char buf[100];
struct sta_info *sta;
if (!key->local->debugfs.keys)
sta = key->sta;
if (sta) {
- sprintf(buf, "../../stations/%pM", sta->sta.addr);
+ sprintf(buf, "../../netdev:%s/stations/%pM",
+ sta->sdata->name, sta->sta.addr);
key->debugfs.stalink =
debugfs_create_symlink("station", key->debugfs.dir, buf);
}
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+ local->oper_channel = chan;
channel_type = ifibss->channel_type;
if (channel_type > NL80211_CHAN_HT20 &&
!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
continue;
}
/* count everything else */
+ sdata->vif.bss_conf.idle = false;
count++;
}
int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
sizeof(mgmt->u.action.u.mesh_action);
- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ skb = dev_alloc_skb(local->tx_headroom +
hdr_len +
2 + 37); /* max HWMP IE */
if (!skb)
return -1;
- skb_reserve(skb, local->hw.extra_tx_headroom);
+ skb_reserve(skb, local->tx_headroom);
mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
memset(mgmt, 0, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
if (time_before(jiffies, ifmsh->next_perr))
return -EAGAIN;
- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ skb = dev_alloc_skb(local->tx_headroom +
hdr_len +
2 + 15 /* PERR IE */);
if (!skb)
return -1;
- skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
+ skb_reserve(skb, local->tx_headroom);
mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
memset(mgmt, 0, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
sizeof(mgmt->u.action.u.self_prot);
- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ skb = dev_alloc_skb(local->tx_headroom +
hdr_len +
2 + /* capability info */
2 + /* AID */
sdata->u.mesh.ie_len);
if (!skb)
return -1;
- skb_reserve(skb, local->hw.extra_tx_headroom);
+ skb_reserve(skb, local->tx_headroom);
mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
memset(mgmt, 0, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_work *wk;
u8 bssid[ETH_ALEN];
bool assoc_bss = false;
assoc_bss = true;
} else {
bool not_auth_yet = false;
+ struct ieee80211_work *tmp, *wk = NULL;
mutex_unlock(&ifmgd->mtx);
mutex_lock(&local->mtx);
- list_for_each_entry(wk, &local->work_list, list) {
- if (wk->sdata != sdata)
+ list_for_each_entry(tmp, &local->work_list, list) {
+ if (tmp->sdata != sdata)
continue;
- if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
- wk->type != IEEE80211_WORK_AUTH &&
- wk->type != IEEE80211_WORK_ASSOC &&
- wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
+ if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
+ tmp->type != IEEE80211_WORK_AUTH &&
+ tmp->type != IEEE80211_WORK_ASSOC &&
+ tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
continue;
- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
+ if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN))
continue;
- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
- list_del_rcu(&wk->list);
- free_work(wk);
+ not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
+ list_del_rcu(&tmp->list);
+ synchronize_rcu();
+ wk = tmp;
break;
}
mutex_unlock(&local->mtx);
+ if (wk && wk->type == IEEE80211_WORK_ASSOC) {
+ /* clean up dummy sta & TX sync */
+ sta_info_destroy_addr(wk->sdata, wk->filter_ta);
+ if (wk->assoc.synced)
+ drv_finish_tx_sync(local, wk->sdata,
+ wk->filter_ta,
+ IEEE80211_TX_SYNC_ASSOC);
+ } else if (wk && wk->type == IEEE80211_WORK_AUTH) {
+ if (wk->probe_auth.synced)
+ drv_finish_tx_sync(local, wk->sdata,
+ wk->filter_ta,
+ IEEE80211_TX_SYNC_AUTH);
+ }
+ kfree(wk);
+
/*
* If somebody requests authentication and we haven't
* sent out an auth frame yet there's no need to send
{
struct sock *sk = sock->sk;
struct rds_sock *rs;
- unsigned long flags;
if (!sk)
goto out;
rds_rdma_drop_keys(rs);
rds_notify_queue_get(rs, NULL);
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
list_del_init(&rs->rs_item);
rds_sock_count--;
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
rds_trans_put(rs->rs_transport);
static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
{
- unsigned long flags;
struct rds_sock *rs;
sock_init_data(sock, sk);
spin_lock_init(&rs->rs_rdma_lock);
rs->rs_rdma_keys = RB_ROOT;
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
list_add_tail(&rs->rs_item, &rds_sock_list);
rds_sock_count++;
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
return 0;
}
{
struct rds_sock *rs;
struct rds_incoming *inc;
- unsigned long flags;
unsigned int total = 0;
len /= sizeof(struct rds_info_message);
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
list_for_each_entry(rs, &rds_sock_list, rs_item) {
read_lock(&rs->rs_recv_lock);
read_unlock(&rs->rs_recv_lock);
}
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
lens->nr = total;
lens->each = sizeof(struct rds_info_message);
{
struct rds_info_socket sinfo;
struct rds_sock *rs;
- unsigned long flags;
len /= sizeof(struct rds_info_socket);
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
if (len < rds_sock_count)
goto out;
lens->nr = rds_sock_count;
lens->each = sizeof(struct rds_info_socket);
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
}
static void rds_exit(void)
cb = netem_skb_cb(skb);
if (q->gap == 0 || /* not doing reordering */
- q->counter < q->gap || /* inside last reordering gap */
+ q->counter < q->gap - 1 || /* inside last reordering gap */
q->reorder < get_crandom(&q->reorder_cor)) {
psched_time_t now;
psched_tdiff_t delay;
if (gcred->acred.group_info != NULL)
get_group_info(gcred->acred.group_info);
gcred->acred.machine_cred = acred->machine_cred;
+ gcred->acred.principal = acred->principal;
dprintk("RPC: allocated %s cred %p for uid %d gid %d\n",
gcred->acred.machine_cred ? "machine" : "generic",
call_rcu(&cred->cr_rcu, generic_free_cred_callback);
}
+static int
+machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags)
+{
+ if (!gcred->acred.machine_cred ||
+ gcred->acred.principal != acred->principal ||
+ gcred->acred.uid != acred->uid ||
+ gcred->acred.gid != acred->gid)
+ return 0;
+ return 1;
+}
+
/*
* Match credentials against current process creds.
*/
struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
int i;
+ if (acred->machine_cred)
+ return machine_cred_match(acred, gcred, flags);
+
if (gcred->acred.uid != acred->uid ||
gcred->acred.gid != acred->gid ||
- gcred->acred.machine_cred != acred->machine_cred)
+ gcred->acred.machine_cred != 0)
goto out_nomatch;
/* Optimisation in the case where pointers are identical... */
struct sk_buff *skb;
unix_state_lock(sk);
- skb = skb_dequeue(&sk->sk_receive_queue);
+ skb = skb_peek(&sk->sk_receive_queue);
if (skb == NULL) {
unix_sk(sk)->recursion_level = 0;
if (copied >= target)
if (check_creds) {
/* Never glue messages from different writers */
if ((UNIXCB(skb).pid != siocb->scm->pid) ||
- (UNIXCB(skb).cred != siocb->scm->cred)) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
+ (UNIXCB(skb).cred != siocb->scm->cred))
break;
- }
} else {
/* Copy credentials */
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
chunk = min_t(unsigned int, skb->len, size);
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
if (copied == 0)
copied = -EFAULT;
break;
if (UNIXCB(skb).fp)
unix_detach_fds(siocb->scm, skb);
- /* put the skb back if we didn't use it up.. */
- if (skb->len) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
+ if (skb->len)
break;
- }
+ skb_unlink(skb, &sk->sk_receive_queue);
consume_skb(skb);
if (siocb->scm->fp)
if (UNIXCB(skb).fp)
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
- /* put message back and return */
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
break;
}
} while (size);
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
## Copyright (C) 2001 Simon Huggins ##
-## Copyright (C) 2005-2010 Randy Dunlap ##
+## Copyright (C) 2005-2012 Randy Dunlap ##
## ##
## #define enhancements by Armin Kuster <akuster@mvista.com> ##
## Copyright (c) 2000 MontaVista Software, Inc. ##
$prototype =~ s/__devinit +//;
$prototype =~ s/__init +//;
$prototype =~ s/__init_or_module +//;
+ $prototype =~ s/__must_check +//;
$prototype =~ s/^#\s*define\s+//; #ak added
$prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
}
ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry);
-/* Looks like: mcp:S */
-static int do_mcp_entry(const char *filename, struct mcp_device_id *id,
- char *alias)
-{
- sprintf(alias, MCP_MODULE_PREFIX "%s", id->name);
-
- return 1;
-}
-ADD_TO_DEVTABLE("mcp", struct mcp_device_id, do_mcp_entry);
-
static const struct dmifield {
const char *prefix;
int field;
extern struct key_type key_type_dead;
extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
/*****************************************************************************/
/*
list_add_tail(&key_type_keyring.link, &key_types_list);
list_add_tail(&key_type_dead.link, &key_types_list);
list_add_tail(&key_type_user.link, &key_types_list);
+ list_add_tail(&key_type_logon.link, &key_types_list);
/* record the root user tracking */
rb_link_node(&root_key_user.node,
#include <asm/uaccess.h>
#include "internal.h"
+static int logon_vet_description(const char *desc);
+
/*
* user defined keys take an arbitrary string as the description and an
* arbitrary blob of data as the payload
EXPORT_SYMBOL_GPL(key_type_user);
+/*
+ * This key type is essentially the same as key_type_user, but it does
+ * not define a .read op. This is suitable for storing username and
+ * password pairs in the keyring that you do not want to be readable
+ * from userspace.
+ */
+struct key_type key_type_logon = {
+ .name = "logon",
+ .instantiate = user_instantiate,
+ .update = user_update,
+ .match = user_match,
+ .revoke = user_revoke,
+ .destroy = user_destroy,
+ .describe = user_describe,
+ .vet_description = logon_vet_description,
+};
+EXPORT_SYMBOL_GPL(key_type_logon);
+
/*
* instantiate a user defined key
*/
}
EXPORT_SYMBOL_GPL(user_read);
+
+/* Vet the description for a "logon" key */
+static int logon_vet_description(const char *desc)
+{
+ char *p;
+
+ /* require a "qualified" description string */
+ p = strchr(desc, ':');
+ if (!p)
+ return -EINVAL;
+
+ /* also reject description with ':' as first char */
+ if (p == desc)
+ return -EINVAL;
+
+ return 0;
+}
params = kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
- if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
- return -EFAULT;
+ if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
+ retval = -EFAULT;
+ goto out;
+ }
retval = snd_compr_allocate_buffer(stream, params);
if (retval) {
- kfree(params);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
retval = stream->ops->set_params(stream, params);
if (retval)
goto out;
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- } else
+ } else {
return -EPERM;
+ }
out:
kfree(params);
return retval;
/* Looks like the unsol event is incompatible with the standard
* definition. 4bit tag is placed at 28 bit!
*/
- switch (res >> 28) {
+ res >>= 28;
+ switch (res) {
case ALC_MIC_EVENT:
alc88x_simple_mic_automute(codec);
break;
default:
- alc_sku_unsol_event(codec, res);
+ alc_exec_unsol_event(codec, res);
break;
}
}
+static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ alc_exec_unsol_event(codec, res >> 28);
+}
+
static void alc880_uniwill_p53_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
/* Looks like the unsol event is incompatible with the standard
* definition. 4bit tag is placed at 28 bit!
*/
- if ((res >> 28) == ALC_DCVOL_EVENT)
+ res >>= 28;
+ if (res == ALC_DCVOL_EVENT)
alc880_uniwill_p53_dcvol_automute(codec);
else
- alc_sku_unsol_event(codec, res);
+ alc_exec_unsol_event(codec, res);
}
/*
.channel_mode = alc880_lg_ch_modes,
.need_dac_fix = 1,
.input_mux = &alc880_lg_capture_source,
- .unsol_event = alc_sku_unsol_event,
+ .unsol_event = alc880_unsol_event,
.setup = alc880_lg_setup,
.init_hook = alc_hp_automute,
#ifdef CONFIG_SND_HDA_POWER_SAVE
alc889A_mb31_automute(codec);
}
+static void alc882_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ alc_exec_unsol_event(codec, res >> 26);
+}
+
/*
* configuration and preset
*/
.channel_mode = alc885_mba21_ch_modes,
.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
.input_mux = &alc882_capture_source,
- .unsol_event = alc_sku_unsol_event,
+ .unsol_event = alc882_unsol_event,
.setup = alc885_mba21_setup,
.init_hook = alc_hp_automute,
},
.input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
+ .unsol_event = alc882_unsol_event,
.setup = alc885_mbp3_setup,
.init_hook = alc_hp_automute,
},
.input_mux = &mb5_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
+ .unsol_event = alc882_unsol_event,
.setup = alc885_mb5_setup,
.init_hook = alc_hp_automute,
},
.input_mux = &macmini3_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
+ .unsol_event = alc882_unsol_event,
.setup = alc885_macmini3_setup,
.init_hook = alc_hp_automute,
},
.input_mux = &alc889A_imac91_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
+ .unsol_event = alc882_unsol_event,
.setup = alc885_imac91_setup,
.init_hook = alc_hp_automute,
},
unsigned int irq_pending_warned :1;
unsigned int probing :1; /* codec probing phase */
unsigned int snoop:1;
+ unsigned int align_buffer_size:1;
/* for debugging */
unsigned int last_cmd[AZX_MAX_CODECS];
runtime->hw.rates = hinfo->rates;
snd_pcm_limit_hw_rates(runtime);
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- if (align_buffer_size)
+ if (chip->align_buffer_size)
/* constrain buffer sizes to be multiple of 128
bytes. This is more efficient in terms of memory
access but isn't required by the HDA spec and
}
/* disable buffer size rounding to 128-byte multiples if supported */
+ chip->align_buffer_size = align_buffer_size;
if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
- align_buffer_size = 0;
+ chip->align_buffer_size = 0;
/* allow 64bit DMA address if supported by H/W */
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
- SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO),
SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO),
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
- unsigned int use_jack_tbl:1; /* 1 for model=auto */
/* auto-mute control */
int automute_mode;
alc_mux_select(codec, 0, spec->int_mic_idx, false);
}
-/* unsolicited event for HP jack sensing */
-static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+/* handle the specified unsol action (ALC_XXX_EVENT) */
+static void alc_exec_unsol_event(struct hda_codec *codec, int action)
{
- struct alc_spec *spec = codec->spec;
- if (codec->vendor_id == 0x10ec0880)
- res >>= 28;
- else
- res >>= 26;
- if (spec->use_jack_tbl)
- res = snd_hda_jack_get_action(codec, res);
- switch (res) {
+ switch (action) {
case ALC_HP_EVENT:
alc_hp_automute(codec);
break;
snd_hda_jack_report_sync(codec);
}
+/* unsolicited event for HP jack sensing */
+static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ if (codec->vendor_id == 0x10ec0880)
+ res >>= 28;
+ else
+ res >>= 26;
+ res = snd_hda_jack_get_action(codec, res);
+ alc_exec_unsol_event(codec, res);
+}
+
/* call init functions of standard auto-mute helpers */
static void alc_inithook(struct hda_codec *codec)
{
};
#endif
-static int alc_build_controls(struct hda_codec *codec)
+static int __alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct snd_kcontrol *kctl = NULL;
alc_free_kctls(codec); /* no longer needed */
- err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ return 0;
+}
+
+static int alc_build_controls(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err = __alc_build_controls(codec);
if (err < 0)
return err;
-
- return 0;
+ return snd_hda_jack_add_kctls(codec, &spec->autocfg);
}
int i, err, noutputs;
noutputs = cfg->line_outs;
- if (spec->multi_ios > 0)
+ if (spec->multi_ios > 0 && cfg->line_outs < 3)
noutputs += spec->multi_ios;
for (i = 0; i < noutputs; i++) {
static void alc_auto_init_std(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->use_jack_tbl = 1;
alc_auto_init_multi_out(codec);
alc_auto_init_extra_out(codec);
alc_auto_init_analog_input(codec);
codec->patch_ops = alc_patch_ops;
if (board_config == ALC_MODEL_AUTO)
spec->init_hook = alc_auto_init_std;
+ else
+ codec->patch_ops.build_controls = __alc_build_controls;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc880_loopbacks;
codec->patch_ops = alc_patch_ops;
if (board_config == ALC_MODEL_AUTO)
spec->init_hook = alc_auto_init_std;
+ else
+ codec->patch_ops.build_controls = __alc_build_controls;
spec->shutup = alc_eapd_shutup;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC_MODEL_AUTO)
spec->init_hook = alc_auto_init_std;
+ else
+ codec->patch_ops.build_controls = __alc_build_controls;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
/* Pin config fixes */
enum {
PINFIX_FSC_AMILO_PI1505,
+ PINFIX_ASUS_A6RP,
};
static const struct alc_fixup alc861_fixups[] = {
{ }
}
},
+ [PINFIX_ASUS_A6RP] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* node 0x0f VREF seems controlling the master output */
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+ { }
+ },
+ },
};
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP),
+ SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
{}
};
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
"Alienware M17x", STAC_ALIENWARE_M17X),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
- "Alienware M17x", STAC_ALIENWARE_M17X),
+ "Alienware M17x R3", STAC_DELL_EQ),
{} /* terminator */
};
return 1;
}
-static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
+static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
{
int i;
for (i = 0; i < cfg->hp_outs; i++)
if (cfg->hp_pins[i] == nid)
return 1; /* nid is a HP-Out */
-
+ for (i = 0; i < cfg->line_outs; i++)
+ if (cfg->line_out_pins[i] == nid)
+ return 1; /* nid is a line-Out */
return 0; /* nid is not a HP-Out */
};
continue;
}
- if (is_nid_hp_pin(cfg, nid))
+ if (is_nid_out_jack_pin(cfg, nid))
continue; /* already has an unsol event */
pinctl = snd_hda_codec_read(codec, nid, 0,
/* BIOS bug: unfilled OEM string */
if (strstr(dev->name, "HP_Mute_LED_P_G")) {
set_hp_led_gpio(codec);
- spec->gpio_led_polarity = 1;
+ switch (codec->subsystem_id) {
+ case 0x103c148a:
+ spec->gpio_led_polarity = 0;
+ break;
+ default:
+ spec->gpio_led_polarity = 1;
+ break;
+ }
return 1;
}
}
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_pcm_4ch(chip, 2, NULL)) < 0) {
+ err = snd_ymfpci_mixer(chip, rear_switch[dev]);
+ if (err < 0) {
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_pcm2(chip, 3, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) {
- snd_card_free(card);
- return err;
+ if (chip->ac97->ext_id & AC97_EI_SDAC) {
+ err = snd_ymfpci_pcm_4ch(chip, 2, NULL);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ err = snd_ymfpci_pcm2(chip, 3, NULL);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
}
if ((err = snd_ymfpci_timer(chip, 0)) < 0) {
snd_card_free(card);
return change;
}
+static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "4ch Duplication",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ymfpci_info_dup4ch,
+ .get = snd_ymfpci_get_dup4ch,
+ .put = snd_ymfpci_put_dup4ch,
+};
static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
{
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4),
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "4ch Duplication",
- .info = snd_ymfpci_info_dup4ch,
- .get = snd_ymfpci_get_dup4ch,
- .put = snd_ymfpci_put_dup4ch,
-},
};
if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)
return err;
}
+ if (chip->ac97->ext_id & AC97_EI_SDAC) {
+ kctl = snd_ctl_new1(&snd_ymfpci_dup4ch, chip);
+ err = snd_ctl_add(chip->card, kctl);
+ if (err < 0)
+ return err;
+ }
/* add S/PDIF control */
if (snd_BUG_ON(!chip->pcm_spdif))
/* restore regular registers */
for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
- /* this regs depends on the others */
+ /* These regs should restore in particular order */
if (reg == SGTL5000_CHIP_ANA_POWER ||
reg == SGTL5000_CHIP_CLK_CTRL ||
reg == SGTL5000_CHIP_LINREG_CTRL ||
reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
- reg == SGTL5000_CHIP_CLK_CTRL)
+ reg == SGTL5000_CHIP_REF_CTRL)
continue;
snd_soc_write(codec, reg, cache[reg]);
snd_soc_write(codec, reg, cache[reg]);
/*
- * restore power and other regs according
- * to set_power() and set_clock()
+ * restore these regs according to the power setting sequence in
+ * sgtl5000_set_power_regs() and clock setting sequence in
+ * sgtl5000_set_clock().
+ *
+ * The order of restore is:
+ * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
+ * SGTL5000_CHIP_ANA_POWER PLL bits set
+ * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
+ * SGTL5000_CHIP_ANA_POWER LINREG_D restored
+ * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
+ * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
*/
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
cache[SGTL5000_CHIP_LINREG_CTRL]);
struct aic32x4_priv {
u32 sysclk;
- s32 master;
u8 page_no;
void *control_data;
u32 power_cfg;
static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u8 iface_reg_1;
u8 iface_reg_2;
u8 iface_reg_3;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
- aic32x4->master = 1;
iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
- aic32x4->master = 0;
break;
default:
printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-
switch (level) {
case SND_SOC_BIAS_ON:
- if (aic32x4->master) {
- /* Switch on PLL */
- snd_soc_update_bits(codec, AIC32X4_PLLPR,
- AIC32X4_PLLEN, AIC32X4_PLLEN);
-
- /* Switch on NDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_NDAC,
- AIC32X4_NDACEN, AIC32X4_NDACEN);
-
- /* Switch on MDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_MDAC,
- AIC32X4_MDACEN, AIC32X4_MDACEN);
-
- /* Switch on NADC Divider */
- snd_soc_update_bits(codec, AIC32X4_NADC,
- AIC32X4_NADCEN, AIC32X4_NADCEN);
-
- /* Switch on MADC Divider */
- snd_soc_update_bits(codec, AIC32X4_MADC,
- AIC32X4_MADCEN, AIC32X4_MADCEN);
-
- /* Switch on BCLK_N Divider */
- snd_soc_update_bits(codec, AIC32X4_BCLKN,
- AIC32X4_BCLKEN, AIC32X4_BCLKEN);
- }
+ /* Switch on PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, AIC32X4_PLLEN);
+
+ /* Switch on NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, AIC32X4_NDACEN);
+
+ /* Switch on MDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MDAC,
+ AIC32X4_MDACEN, AIC32X4_MDACEN);
+
+ /* Switch on NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, AIC32X4_NADCEN);
+
+ /* Switch on MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, AIC32X4_MADCEN);
+
+ /* Switch on BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, AIC32X4_BCLKEN);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
- if (aic32x4->master) {
- /* Switch off PLL */
- snd_soc_update_bits(codec, AIC32X4_PLLPR,
- AIC32X4_PLLEN, 0);
-
- /* Switch off NDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_NDAC,
- AIC32X4_NDACEN, 0);
-
- /* Switch off MDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_MDAC,
- AIC32X4_MDACEN, 0);
-
- /* Switch off NADC Divider */
- snd_soc_update_bits(codec, AIC32X4_NADC,
- AIC32X4_NADCEN, 0);
-
- /* Switch off MADC Divider */
- snd_soc_update_bits(codec, AIC32X4_MADC,
- AIC32X4_MADCEN, 0);
-
- /* Switch off BCLK_N Divider */
- snd_soc_update_bits(codec, AIC32X4_BCLKN,
- AIC32X4_BCLKEN, 0);
- }
+ /* Switch off PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, 0);
+
+ /* Switch off NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, 0);
+
+ /* Switch off MDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MDAC,
+ AIC32X4_MDACEN, 0);
+
+ /* Switch off NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, 0);
+
+ /* Switch off MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, 0);
+
+ /* Switch off BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, 0);
break;
case SND_SOC_BIAS_OFF:
break;
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
}
- if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
- snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN);
- }
+
+ tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
+ AIC32X4_LDOCTLEN : 0;
+ snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
+
tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
tmp_reg |= AIC32X4_LDOIN_18_36;
struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata;
const char *filename;
- const struct firmware *fw;
- int reg, ret;
+ const struct firmware *fw = NULL;
+ int ret;
+ int reg;
u16 id;
wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
ret = PTR_ERR(wm2000->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ goto out;
}
/* Verify that this is a WM2000 */
if (id != 0x2000) {
dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
ret = -ENODEV;
- goto err_regmap;
+ goto out_regmap_exit;
}
reg = wm2000_read(i2c, WM2000_REG_REVISON);
ret = request_firmware(&fw, filename, &i2c->dev);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
- goto err_regmap;
+ goto out_regmap_exit;
}
/* Pre-cook the concatenation of the register address onto the image */
if (wm2000->anc_download == NULL) {
dev_err(&i2c->dev, "Out of memory\n");
ret = -ENOMEM;
- goto err_fw;
+ goto out_regmap_exit;
}
wm2000->anc_download[0] = 0x80;
wm2000->anc_download[1] = 0x00;
memcpy(wm2000->anc_download + 2, fw->data, fw->size);
- release_firmware(fw);
-
wm2000->anc_eng_ena = 1;
wm2000->anc_active = 1;
wm2000->spk_ena = 1;
wm2000_reset(wm2000);
- ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000,
- NULL, 0);
- if (ret != 0)
- goto err_fw;
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
+ if (!ret)
+ goto out;
- return 0;
-
-err_fw:
- release_firmware(fw);
-err_regmap:
+out_regmap_exit:
regmap_exit(wm2000->regmap);
-err:
+out:
+ release_firmware(fw);
return ret;
}
switch (wm5100->rev) {
case 0:
+ regcache_cache_bypass(wm5100->regmap, true);
snd_soc_write(codec, 0x11, 0x3);
snd_soc_write(codec, 0x203, 0xc);
snd_soc_write(codec, 0x206, 0);
snd_soc_write(codec,
wm5100_reva_patches[i].reg,
wm5100_reva_patches[i].val);
+ regcache_cache_bypass(wm5100->regmap, false);
break;
default:
break;
break;
case SND_SOC_BIAS_OFF:
+ regcache_cache_only(wm5100->regmap, true);
if (wm5100->pdata.ldo_ena)
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
return 0;
if (fw->size < 32) {
- dev_err(codec->dev, "%s: firmware too short (%d bytes)\n",
+ dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n",
name, fw->size);
goto err;
}
SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int lfclk = 0;
int ratediv = 0;
+ int sync = WM8996_REG_SYNC;
int src;
int old;
case 32000:
case 32768:
lfclk = WM8996_LFCLK_ENA;
+ sync = 0;
break;
default:
dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK,
src << WM8996_SYSCLK_SRC_SHIFT | ratediv);
snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk);
+ snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1,
+ WM8996_REG_SYNC, sync);
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
WM8996_SYSCLK_ENA, old);
/*
* R257 (0x101) - Control Interface (1)
*/
+#define WM8996_REG_SYNC 0x8000 /* REG_SYNC */
+#define WM8996_REG_SYNC_MASK 0x8000 /* REG_SYNC */
+#define WM8996_REG_SYNC_SHIFT 15 /* REG_SYNC */
+#define WM8996_REG_SYNC_WIDTH 1 /* REG_SYNC */
#define WM8996_AUTO_INC 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */
*
* If MCLK is not used, we just set saif clk to 512*fs.
*/
+ clk_prepare_enable(master_saif->clk);
+
if (master_saif->mclk_in_use) {
if (mclk % 32 == 0) {
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
ret = clk_set_rate(master_saif->clk, 384 * rate);
} else {
/* SAIF MCLK should be either 32x or 48x */
+ clk_disable_unprepare(master_saif->clk);
return -EINVAL;
}
} else {
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
}
+ clk_disable_unprepare(master_saif->clk);
+
if (ret)
return ret;