diff options
-rw-r--r-- | arch/arm/configs/u8500_defconfig | 59 | ||||
-rw-r--r-- | arch/arm/configs/vexpress_defconfig | 140 | ||||
-rw-r--r-- | arch/arm/kernel/etm.c | 4 | ||||
-rw-r--r-- | drivers/amba/bus.c | 348 | ||||
-rw-r--r-- | drivers/char/hw_random/nomadik-rng.c | 2 | ||||
-rw-r--r-- | drivers/dma/amba-pl08x.c | 2 | ||||
-rw-r--r-- | drivers/dma/pl330.c | 2 | ||||
-rw-r--r-- | drivers/gpio/pl061.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/ambakmi.c | 3 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 348 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 15 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl030.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 2 | ||||
-rw-r--r-- | drivers/spi/amba-pl022.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/amba-pl010.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 513 | ||||
-rw-r--r-- | drivers/video/Kconfig | 18 | ||||
-rw-r--r-- | drivers/video/amba-clcd.c | 2 | ||||
-rw-r--r-- | drivers/video/cyber2000fb.c | 263 | ||||
-rw-r--r-- | drivers/video/cyber2000fb.h | 16 | ||||
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 2 | ||||
-rw-r--r-- | include/linux/amba/bus.h | 8 | ||||
-rw-r--r-- | include/linux/amba/mmci.h | 17 | ||||
-rw-r--r-- | sound/arm/aaci.c | 285 | ||||
-rw-r--r-- | sound/arm/aaci.h | 9 |
25 files changed, 1710 insertions, 356 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 52d86c4485b..a5cce242a77 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,7 +1,6 @@ CONFIG_EXPERIMENTAL=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y @@ -13,43 +12,89 @@ CONFIG_UX500_SOC_DB5500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_U8500=y CONFIG_MACH_U5500=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_VFP=y CONFIG_NEON=y +CONFIG_NET=y +CONFIG_PHONET=y +CONFIG_PHONET_PIPECTRLR=y +# CONFIG_WIRELESS is not set +CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +CONFIG_AB8500_PWM=y +CONFIG_SENSORS_BH1780=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_NOMADIK=y +CONFIG_KEYBOARD_STMPE=y +CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_BU21013=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AB8500_PONKEY=y # CONFIG_SERIO is not set CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y # CONFIG_LEGACY_PTYS is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_NOMADIK=y +CONFIG_I2C=y +CONFIG_I2C_NOMADIK=y CONFIG_SPI=y CONFIG_SPI_PL022=y +CONFIG_GPIO_STMPE=y +CONFIG_GPIO_TC3589X=y # CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set +CONFIG_MFD_STMPE=y +CONFIG_MFD_TC3589X=y +CONFIG_AB8500_CORE=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_AB8500=y # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_LP5521=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AB8500=y +CONFIG_RTC_DRV_PL031=y +CONFIG_DMADEVICES=y +CONFIG_STE_DMA40=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y -CONFIG_INOTIFY=y +CONFIG_EXT3_FS=y +CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_CONFIGFS_FS=m # CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set # CONFIG_DEBUG_PREEMPT is not set @@ -58,5 +103,3 @@ CONFIG_DEBUG_INFO=y # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y -CONFIG_CRC_T10DIF=m -# CONFIG_CRC32 is not set diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig new file mode 100644 index 00000000000..f2de51f0bd1 --- /dev/null +++ b/arch/arm/configs/vexpress_defconfig @@ -0,0 +1,140 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CPUSETS=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_VEXPRESS=y +CONFIG_ARCH_VEXPRESS_CA9X4=y +# CONFIG_SWP_EMULATE is not set +CONFIG_SMP=y +CONFIG_VMSPLIT_2G=y +CONFIG_HOTPLUG_CPU=y +CONFIG_AEABI=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M" +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_MTD=y +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MISC_DEVICES=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +# CONFIG_SATA_PMP is not set +CONFIG_NETDEVICES=y +CONFIG_NET_ETHERNET=y +CONFIG_SMSC911X=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_FB=y +CONFIG_FB_ARMCLCD=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +# CONFIG_SND_DRIVERS is not set +CONFIG_SND_ARMAACI=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_NTRIG=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_MON=y +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_DEBUG_INFO=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 11db62806a1..052b509e2d5 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -338,7 +338,7 @@ static struct miscdevice etb_miscdev = { .fops = &etb_fops, }; -static int __init etb_probe(struct amba_device *dev, struct amba_id *id) +static int __init etb_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; @@ -530,7 +530,7 @@ static ssize_t trace_mode_store(struct kobject *kobj, static struct kobj_attribute trace_mode_attr = __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); -static int __init etm_probe(struct amba_device *dev, struct amba_id *id) +static int __init etm_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index e7df019d29d..6d2bb2524b6 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -13,16 +13,17 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/io.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> #include <linux/amba/bus.h> #include <asm/irq.h> #include <asm/sizes.h> -#define to_amba_device(d) container_of(d, struct amba_device, dev) #define to_amba_driver(d) container_of(d, struct amba_driver, drv) -static struct amba_id * -amba_lookup(struct amba_id *table, struct amba_device *dev) +static const struct amba_id * +amba_lookup(const struct amba_id *table, struct amba_device *dev) { int ret = 0; @@ -57,26 +58,6 @@ static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) #define amba_uevent NULL #endif -static int amba_suspend(struct device *dev, pm_message_t state) -{ - struct amba_driver *drv = to_amba_driver(dev->driver); - int ret = 0; - - if (dev->driver && drv->suspend) - ret = drv->suspend(to_amba_device(dev), state); - return ret; -} - -static int amba_resume(struct device *dev) -{ - struct amba_driver *drv = to_amba_driver(dev->driver); - int ret = 0; - - if (dev->driver && drv->resume) - ret = drv->resume(to_amba_device(dev)); - return ret; -} - #define amba_attr_func(name,fmt,arg...) \ static ssize_t name##_show(struct device *_dev, \ struct device_attribute *attr, char *buf) \ @@ -102,17 +83,330 @@ static struct device_attribute amba_dev_attrs[] = { __ATTR_NULL, }; +#ifdef CONFIG_PM_SLEEP + +static int amba_legacy_suspend(struct device *dev, pm_message_t mesg) +{ + struct amba_driver *adrv = to_amba_driver(dev->driver); + struct amba_device *adev = to_amba_device(dev); + int ret = 0; + + if (dev->driver && adrv->suspend) + ret = adrv->suspend(adev, mesg); + + return ret; +} + +static int amba_legacy_resume(struct device *dev) +{ + struct amba_driver *adrv = to_amba_driver(dev->driver); + struct amba_device *adev = to_amba_device(dev); + int ret = 0; + + if (dev->driver && adrv->resume) + ret = adrv->resume(adev); + + return ret; +} + +static int amba_pm_prepare(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (drv && drv->pm && drv->pm->prepare) + ret = drv->pm->prepare(dev); + + return ret; +} + +static void amba_pm_complete(struct device *dev) +{ + struct device_driver *drv = dev->driver; + + if (drv && drv->pm && drv->pm->complete) + drv->pm->complete(dev); +} + +#else /* !CONFIG_PM_SLEEP */ + +#define amba_pm_prepare NULL +#define amba_pm_complete NULL + +#endif /* !CONFIG_PM_SLEEP */ + +#ifdef CONFIG_SUSPEND + +static int amba_pm_suspend(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend) + ret = drv->pm->suspend(dev); + } else { + ret = amba_legacy_suspend(dev, PMSG_SUSPEND); + } + + return ret; +} + +static int amba_pm_suspend_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend_noirq) + ret = drv->pm->suspend_noirq(dev); + } + + return ret; +} + +static int amba_pm_resume(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume) + ret = drv->pm->resume(dev); + } else { + ret = amba_legacy_resume(dev); + } + + return ret; +} + +static int amba_pm_resume_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume_noirq) + ret = drv->pm->resume_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_SUSPEND */ + +#define amba_pm_suspend NULL +#define amba_pm_resume NULL +#define amba_pm_suspend_noirq NULL +#define amba_pm_resume_noirq NULL + +#endif /* !CONFIG_SUSPEND */ + +#ifdef CONFIG_HIBERNATION + +static int amba_pm_freeze(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze) + ret = drv->pm->freeze(dev); + } else { + ret = amba_legacy_suspend(dev, PMSG_FREEZE); + } + + return ret; +} + +static int amba_pm_freeze_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze_noirq) + ret = drv->pm->freeze_noirq(dev); + } + + return ret; +} + +static int amba_pm_thaw(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->thaw) + ret = drv->pm->thaw(dev); + } else { + ret = amba_legacy_resume(dev); + } + + return ret; +} + +static int amba_pm_thaw_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->thaw_noirq) + ret = drv->pm->thaw_noirq(dev); + } + + return ret; +} + +static int amba_pm_poweroff(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->poweroff) + ret = drv->pm->poweroff(dev); + } else { + ret = amba_legacy_suspend(dev, PMSG_HIBERNATE); + } + + return ret; +} + +static int amba_pm_poweroff_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->poweroff_noirq) + ret = drv->pm->poweroff_noirq(dev); + } + + return ret; +} + +static int amba_pm_restore(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->restore) + ret = drv->pm->restore(dev); + } else { + ret = amba_legacy_resume(dev); + } + + return ret; +} + +static int amba_pm_restore_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->restore_noirq) + ret = drv->pm->restore_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_HIBERNATION */ + +#define amba_pm_freeze NULL +#define amba_pm_thaw NULL +#define amba_pm_poweroff NULL +#define amba_pm_restore NULL +#define amba_pm_freeze_noirq NULL +#define amba_pm_thaw_noirq NULL +#define amba_pm_poweroff_noirq NULL +#define amba_pm_restore_noirq NULL + +#endif /* !CONFIG_HIBERNATION */ + +#ifdef CONFIG_PM + +static const struct dev_pm_ops amba_pm = { + .prepare = amba_pm_prepare, + .complete = amba_pm_complete, + .suspend = amba_pm_suspend, + .resume = amba_pm_resume, + .freeze = amba_pm_freeze, + .thaw = amba_pm_thaw, + .poweroff = amba_pm_poweroff, + .restore = amba_pm_restore, + .suspend_noirq = amba_pm_suspend_noirq, + .resume_noirq = amba_pm_resume_noirq, + .freeze_noirq = amba_pm_freeze_noirq, + .thaw_noirq = amba_pm_thaw_noirq, + .poweroff_noirq = amba_pm_poweroff_noirq, + .restore_noirq = amba_pm_restore_noirq, + SET_RUNTIME_PM_OPS( + pm_generic_runtime_suspend, + pm_generic_runtime_resume, + pm_generic_runtime_idle + ) +}; + +#define AMBA_PM (&amba_pm) + +#else /* !CONFIG_PM */ + +#define AMBA_PM NULL + +#endif /* !CONFIG_PM */ + /* * Primecells are part of the Advanced Microcontroller Bus Architecture, * so we call the bus "amba". */ -static struct bus_type amba_bustype = { +struct bus_type amba_bustype = { .name = "amba", .dev_attrs = amba_dev_attrs, .match = amba_match, .uevent = amba_uevent, - .suspend = amba_suspend, - .resume = amba_resume, + .pm = AMBA_PM, }; static int __init amba_init(void) @@ -188,7 +482,7 @@ static int amba_probe(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *pcdrv = to_amba_driver(dev->driver); - struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); + const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); int ret; do { diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index a348c7e9aa0..dd1d143eb8e 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c @@ -39,7 +39,7 @@ static struct hwrng nmk_rng = { .read = nmk_rng_read, }; -static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id) +static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) { void __iomem *base; int ret; diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 07bca4970e5..e6d7228b147 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1845,7 +1845,7 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) } #endif -static int pl08x_probe(struct amba_device *adev, struct amba_id *id) +static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) { struct pl08x_driver_data *pl08x; const struct vendor_data *vd = id->data; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 7c50f6dfd3f..6abe1ec1f2c 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -657,7 +657,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data) } static int __devinit -pl330_probe(struct amba_device *adev, struct amba_id *id) +pl330_probe(struct amba_device *adev, const struct amba_id *id) { struct dma_pl330_platdata *pdat; struct dma_pl330_dmac *pdmac; diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 2975d22daff..838ddbdf90c 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -232,7 +232,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) desc->irq_data.chip->irq_unmask(&desc->irq_data); } -static int pl061_probe(struct amba_device *dev, struct amba_id *id) +static int pl061_probe(struct amba_device *dev, const struct amba_id *id) { struct pl061_platform_data *pdata; struct pl061_gpio *chip; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 92563a681d6..12abc50508e 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -107,7 +107,8 @@ static void amba_kmi_close(struct serio *io) clk_disable(kmi->clk); } -static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit amba_kmi_probe(struct amba_device *dev, + const struct amba_id *id) { struct amba_kmi_port *kmi; struct serio *io; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2d6de3e03e2..5bbb87d1025 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -2,7 +2,7 @@ * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver * * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * Copyright (C) 2010 ST-Ericsson AB. + * Copyright (C) 2010 ST-Ericsson SA * * 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 @@ -25,8 +25,10 @@ #include <linux/clk.h> #include <linux/scatterlist.h> #include <linux/gpio.h> -#include <linux/amba/mmci.h> #include <linux/regulator/consumer.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/amba/mmci.h> #include <asm/div64.h> #include <asm/io.h> @@ -142,9 +144,6 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) host->mrq = NULL; host->cmd = NULL; - if (mrq->data) - mrq->data->bytes_xfered = host->data_xfered; - /* * Need to drop the host lock here; mmc_request_done may call * back into the driver... @@ -189,6 +188,248 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); } +/* + * All the DMA operation mode stuff goes inside this ifdef. + * This assumes that you have a generic DMA device interface, + * no custom DMA interfaces are supported. + */ +#ifdef CONFIG_DMA_ENGINE +static void __devinit mmci_dma_setup(struct mmci_host *host) +{ + struct mmci_platform_data *plat = host->plat; + const char *rxname, *txname; + dma_cap_mask_t mask; + + if (!plat || !plat->dma_filter) { + dev_info(mmc_dev(host->mmc), "no DMA platform data\n"); + return; + } + + /* Try to acquire a generic DMA engine slave channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* + * If only an RX channel is specified, the driver will + * attempt to use it bidirectionally, however if it is + * is specified but cannot be located, DMA will be disabled. + */ + if (plat->dma_rx_param) { + host->dma_rx_channel = dma_request_channel(mask, + plat->dma_filter, + plat->dma_rx_param); + /* E.g if no DMA hardware is present */ + if (!host->dma_rx_channel) + dev_err(mmc_dev(host->mmc), "no RX DMA channel\n"); + } + + if (plat->dma_tx_param) { + host->dma_tx_channel = dma_request_channel(mask, + plat->dma_filter, + plat->dma_tx_param); + if (!host->dma_tx_channel) + dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n"); + } else { + host->dma_tx_channel = host->dma_rx_channel; + } + + if (host->dma_rx_channel) + rxname = dma_chan_name(host->dma_rx_channel); + else + rxname = "none"; + + if (host->dma_tx_channel) + txname = dma_chan_name(host->dma_tx_channel); + else + txname = "none"; + + dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n", + rxname, txname); + + /* + * Limit the maximum segment size in any SG entry according to + * the parameters of the DMA engine device. + */ + if (host->dma_tx_channel) { + struct device *dev = host->dma_tx_channel->device->dev; + unsigned int max_seg_size = dma_get_max_seg_size(dev); + + if (max_seg_size < host->mmc->max_seg_size) + host->mmc->max_seg_size = max_seg_size; + } + if (host->dma_rx_channel) { + struct device *dev = host->dma_rx_channel->device->dev; + unsigned int max_seg_size = dma_get_max_seg_size(dev); + + if (max_seg_size < host->mmc->max_seg_size) + host->mmc->max_seg_size = max_seg_size; + } +} + +/* + * This is used in __devinit or __devexit so inline it + * so it can be discarded. + */ +static inline void mmci_dma_release(struct mmci_host *host) +{ + struct mmci_platform_data *plat = host->plat; + + if (host->dma_rx_channel) + dma_release_channel(host->dma_rx_channel); + if (host->dma_tx_channel && plat->dma_tx_param) + dma_release_channel(host->dma_tx_channel); + host->dma_rx_channel = host->dma_tx_channel = NULL; +} + +static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) +{ + struct dma_chan *chan = host->dma_current; + enum dma_data_direction dir; + u32 status; + int i; + + /* Wait up to 1ms for the DMA to complete */ + for (i = 0; ; i++) { + status = readl(host->base + MMCISTATUS); + if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100) + break; + udelay(10); + } + + /* + * Check to see whether we still have some data left in the FIFO - + * this catches DMA controllers which are unable to monitor the + * DMALBREQ and DMALSREQ signals while allowing us to DMA to non- + * contiguous buffers. On TX, we'll get a FIFO underrun error. + */ + if (status & MCI_RXDATAAVLBLMASK) { + dmaengine_terminate_all(chan); + if (!data->error) + data->error = -EIO; + } + + if (data->flags & MMC_DATA_WRITE) { + dir = DMA_TO_DEVICE; + } else { + dir = DMA_FROM_DEVICE; + } + + dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); + + /* + * Use of DMA with scatter-gather is impossible. + * Give up with DMA and switch back to PIO mode. + */ + if (status & MCI_RXDATAAVLBLMASK) { + dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n"); + mmci_dma_release(host); + } +} + +static void mmci_dma_data_error(struct mmci_host *host) +{ + dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); + dmaengine_terminate_all(host->dma_current); +} + +static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) +{ + struct variant_data *variant = host->variant; + struct dma_slave_config conf = { + .src_addr = host->phybase + MMCIFIFO, + .dst_addr = host->phybase + MMCIFIFO, + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + .src_maxburst = variant->fifohalfsize >> 2, /* # of words */ + .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */ + }; + struct mmc_data *data = host->data; + struct dma_chan *chan; + struct dma_device *device; + struct dma_async_tx_descriptor *desc; + int nr_sg; + + host->dma_current = NULL; + + if (data->flags & MMC_DATA_READ) { + conf.direction = DMA_FROM_DEVICE; + chan = host->dma_rx_channel; + } else { + conf.direction = DMA_TO_DEVICE; + chan = host->dma_tx_channel; + } + + /* If there's no DMA channel, fall back to PIO */ + if (!chan) + return -EINVAL; + + /* If less than or equal to the fifo size, don't bother with DMA */ + if (host->size <= variant->fifosize) + return -EINVAL; + + device = chan->device; + nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction); + if (nr_sg == 0) + return -EINVAL; + + dmaengine_slave_config(chan, &conf); + desc = device->device_prep_slave_sg(chan, data->sg, nr_sg, + conf.direction, DMA_CTRL_ACK); + if (!desc) + goto unmap_exit; + + /* Okay, go for it. */ + host->dma_current = chan; + + dev_vdbg(mmc_dev(host->mmc), + "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n", + data->sg_len, data->blksz, data->blocks, data->flags); + dmaengine_submit(desc); + dma_async_issue_pending(chan); + + datactrl |= MCI_DPSM_DMAENABLE; + + /* Trigger the DMA transfer */ + writel(datactrl, host->base + MMCIDATACTRL); + + /* + * Let the MMCI say when the data is ended and it's time + * to fire next DMA request. When that happens, MMCI will + * call mmci_data_end() + */ + writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK, + host->base + MMCIMASK0); + return 0; + +unmap_exit: + dmaengine_terminate_all(chan); + dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction); + return -ENOMEM; +} +#else +/* Blank functions if the DMA engine is not available */ +static inline void mmci_dma_setup(struct mmci_host *host) +{ +} + +static inline void mmci_dma_release(struct mmci_host *host) +{ +} + +static inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) +{ +} + +static inline void mmci_dma_data_error(struct mmci_host *host) +{ +} + +static inline int mmci_dma_start_data(str |