* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
bugs, x86: Fix printk levels for panic, softlockups and stack dumps
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf top: Fix number of samples displayed
perf tools: Fix strlen() bug in perf_event__synthesize_event_type()
perf tools: Fix broken build by defining _GNU_SOURCE in Makefile
x86/dumpstack: Remove unneeded check in dump_trace()
perf: Fix broken interrupt rate throttling
* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
sched/rt: Fix task stack corruption under __ARCH_WANT_INTERRUPTS_ON_CTXSW
sched: Fix ancient race in do_exit()
sched/nohz: Fix nohz cpu idle load balancing state with cpu hotplug
sched/s390: Fix compile error in sched/core.c
sched: Fix rq->nr_uninterruptible update race
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/reboot: Remove VersaLogic Menlow reboot quirk
x86/reboot: Skip DMI checks if reboot set by user
x86: Properly parenthesize cmpxchg() macro arguments
!Iinclude/linux/device.h
</sect1>
<sect1><title>Device Drivers Base</title>
+!Idrivers/base/init.c
!Edrivers/base/driver.c
!Edrivers/base/core.c
+!Edrivers/base/syscore.c
!Edrivers/base/class.c
+!Idrivers/base/node.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c
<!-- Cannot be included, because
exceed allowed 44 characters maximum
X!Edrivers/base/attribute_container.c
-->
-!Edrivers/base/sys.c
+!Edrivers/base/dd.c
<!--
X!Edrivers/base/interface.c
-->
!Iinclude/linux/platform_device.h
!Edrivers/base/platform.c
!Edrivers/base/bus.c
+ </sect1>
+ <sect1><title>Device Drivers DMA Management</title>
+!Edrivers/base/dma-buf.c
+!Edrivers/base/dma-coherent.c
+!Edrivers/base/dma-mapping.c
</sect1>
<sect1><title>Device Drivers Power Management</title>
!Edrivers/base/power/main.c
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
!Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250.c
+!Edrivers/tty/serial/8250/8250.c
</chapter>
<chapter id="fbdev">
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");
- 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
- 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
F: drivers/net/ethernet/realtek/r8169.c
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-serial@vger.kernel.org
W: http://serial.sourceforge.net
S: Maintained
CHAR and MISC DRIVERS
M: Arnd Bergmann <arnd@arndb.de>
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-S: Maintained
+S: Supported
F: drivers/char/*
F: drivers/misc/*
F: Documentation/blockdev/drbd/
DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
S: Supported
F: Documentation/kobject.txt
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
LogFS
M: Joern Engel <joern@logfs.org>
+M: Prasad Joshi <prasadjoshi.linux@gmail.com>
L: logfs@logfs.org
W: logfs.org
S: Maintained
F: drivers/video/matrox/matroxfb_*
F: include/linux/matroxfb.h
-MAX1668 TEMPERATURE SENSOR DRIVER
-M: "David George" <david.george@ska.ac.za>
-L: lm-sensors@lm-sensors.org
-S: Maintained
-F: Documentation/hwmon/max1668
-F: drivers/hwmon/max1668.c
-
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
M: "Hans J. Koch" <hjk@hansjkoch.de>
L: lm-sensors@lm-sensors.org
F: arch/alpha/kernel/srm_env.c
STABLE BRANCH
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: stable@vger.kernel.org
-S: Maintained
+S: Supported
STAGING SUBSYSTEM
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
L: devel@driverdev.osuosl.org
-S: Maintained
+S: Supported
F: drivers/staging/
STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
K: ^Subject:.*(?i)trivial
TTY LAYER
-M: Greg Kroah-Hartman <gregkh@suse.de>
-S: Maintained
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+S: Supported
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
F: drivers/usb/serial/digi_acceleport.c
USB SERIAL DRIVER
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
S: Supported
F: Documentation/usb/usb-serial.txt
F: drivers/usb/serial/empeg.c
USB SERIAL KEYSPAN DRIVER
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
-W: http://www.kroah.com/linux/
S: Maintained
F: drivers/usb/serial/*keyspan*
F: drivers/media/video/sn9c102/
USB SUBSYSTEM
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
USERSPACE I/O (UIO)
M: "Hans J. Koch" <hjk@hansjkoch.de>
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Maintained
F: Documentation/DocBook/uio-howto.tmpl
F: drivers/uio/
F: Documentation/hwmon/wm83??
F: arch/arm/mach-s3c64xx/mach-crag6410*
F: drivers/leds/leds-wm83*.c
+F: drivers/hwmon/wm83??-hwmon.c
F: drivers/input/misc/wm831x-on.c
F: drivers/input/touchscreen/wm831x-ts.c
F: drivers/input/touchscreen/wm97*.c
VERSION = 3
PATCHLEVEL = 3
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
NAME = Saber-toothed Squirrel
# *DOCUMENTATION*
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
#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;
*/
#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 SOC_IMX5
select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
select MXC_TZIC
select ARCH_MXC_IOMUX_V3
select ARCH_MXC_AUDMUX_V2
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),
return -ENOMEM;
iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
- if (!iomuxc_base)
+ if (!iomuxc_base) {
+ iounmap(weim_base);
return -ENOMEM;
+ }
/* CS1 timings for LAN9220 */
writel(0x20001, (weim_base + 0x18));
#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>
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.
*/
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>
/*
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.
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)
#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
config SPARC32
def_bool !64BIT
select GENERIC_ATOMIC64
+ select CLZ_TAB
config SPARC64
def_bool 64BIT
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
- .data
- .align 8
- .globl __clz_tab
-__clz_tab:
- .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
- .byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
- .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
- .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .size __clz_tab,256
- .global .udiv
-
.text
.align 4
+ .global .udiv
.globl __divdi3
__divdi3:
save %sp,-104,%sp
#ifdef __HAVE_ARCH_CMPXCHG
#define cmpxchg(ptr, old, new) \
- __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ __cmpxchg(ptr, old, new, sizeof(*(ptr)))
#define sync_cmpxchg(ptr, old, new) \
- __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ __sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))
#define cmpxchg_local(ptr, old, new) \
- __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+ __cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
#endif
/*
unsigned short ss;
unsigned long sp;
#endif
- printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ printk(KERN_DEFAULT
+ "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
#endif
unsigned char c;
u8 *ip;
- printk(KERN_EMERG "Stack:\n");
+ printk(KERN_DEFAULT "Stack:\n");
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
- 0, KERN_EMERG);
+ 0, KERN_DEFAULT);
- printk(KERN_EMERG "Code: ");
+ printk(KERN_DEFAULT "Code: ");
ip = (u8 *)regs->ip - code_prologue;
if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
enum reboot_type reboot_type = BOOT_ACPI;
int reboot_force;
+/* This variable is used privately to keep track of whether or not
+ * reboot_type is still set to its default value (i.e., reboot= hasn't
+ * been set on the command line). This is needed so that we can
+ * suppress DMI scanning for reboot quirks. Without it, it's
+ * impossible to override a faulty reboot quirk without recompiling.
+ */
+static int reboot_default = 1;
+
#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
static int reboot_cpu = -1;
#endif
static int __init reboot_setup(char *str)
{
for (;;) {
+ /* Having anything passed on the command line via
+ * reboot= will cause us to disable DMI checking
+ * below.
+ */
+ reboot_default = 0;
+
switch (*str) {
case 'w':
reboot_mode = 0x1234;
DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
},
},
- { /* Handle problems with rebooting on VersaLogic Menlow boards */
- .callback = set_bios_reboot,
- .ident = "VersaLogic Menlow based board",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
- },
- },
{ /* Handle reboot issue on Acer Aspire one */
.callback = set_kbd_reboot,
.ident = "Acer Aspire One A110",
static int __init reboot_init(void)
{
- dmi_check_system(reboot_dmi_table);
+ /* Only do the DMI check if reboot_type hasn't been overridden
+ * on the command line
+ */
+ if (reboot_default) {
+ dmi_check_system(reboot_dmi_table);
+ }
return 0;
}
core_initcall(reboot_init);
static int __init pci_reboot_init(void)
{
- dmi_check_system(pci_reboot_dmi_table);
+ /* Only do the DMI check if reboot_type hasn't been overridden
+ * on the command line
+ */
+ if (reboot_default) {
+ dmi_check_system(pci_reboot_dmi_table);
+ }
return 0;
}
core_initcall(pci_reboot_init);
stackend = end_of_stack(tsk);
if (tsk != &init_task && *stackend != STACK_END_MAGIC)
- printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
tsk->thread.cr2 = address;
tsk->thread.trap_no = 14;
sig = 0;
/* Executive summary in case the body of the oops scrolled away */
- printk(KERN_EMERG "CR2: %016lx\n", address);
+ printk(KERN_DEFAULT "CR2: %016lx\n", address);
oops_end(flags, regs, sig);
}
}
#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;
# 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 \
* 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.
+++ /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);
}
}
static char ohci_driver_name[] = KBUILD_MODNAME;
#define PCI_DEVICE_ID_AGERE_FW643 0x5901
+#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
QUIRK_NO_MSI},
+ {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+ QUIRK_RESET_PACKET},
+
{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
QUIRK_NO_MSI},
QUIRK_NO_MSI},
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
- QUIRK_CYCLE_TIMER},
+ QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
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);
}
/* 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,
},
};
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 ||
unsigned int *handle)
{
if (handle)
- handle = 0;
+ *handle = 0;
return 0;
}
static inline u8 temp_to_reg(long val)
{
- if (val < 0)
- val = 0;
- else if (val > 1000 * 0xff)
- val = 0xff;
- return ((val + 500) / 1000);
+ if (val <= 0)
+ return 0;
+ if (val >= 1000 * 0xff)
+ return 0xff;
+ return (val + 500) / 1000;
}
/*
static int __devinit sht15_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret;
struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
u8 status = 0;
init_waitqueue_head(&data->wait_queue);
if (pdev->dev.platform_data == NULL) {
+ ret = -EINVAL;
dev_err(&pdev->dev, "no platform data supplied\n");
goto err_free_data;
}
{
struct w83627ehf_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct w83627ehf_sio_data *sio_data = dev->platform_data;
int nr = sensor_attr->index;
unsigned long val;
int err;
if (val > 1)
return -EINVAL;
+
+ /* On NCT67766F, DC mode is only supported for pwm1 */
+ if (sio_data->kind == nct6776 && nr && val != 1)
+ return -EINVAL;
+
mutex_lock(&data->update_lock);
reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
data->pwm_mode[nr] = val;
return PTR_ERR(ctx);
if (cmd.conn_param.valid) {
- ctx->uid = cmd.uid;
ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+ mutex_lock(&file->mut);
ret = rdma_accept(ctx->cm_id, &conn_param);
+ if (!ret)
+ ctx->uid = cmd.uid;
+ mutex_unlock(&file->mut);
} else
ret = rdma_accept(ctx->cm_id, NULL);
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
+ atomic_set(&qp->usecnt, 0);
atomic_inc(&pd->usecnt);
atomic_inc(&attr.send_cq->usecnt);
if (attr.recv_cq)
qp->uobject = NULL;
qp->qp_type = qp_init_attr->qp_type;
+ atomic_set(&qp->usecnt, 0);
if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
qp->event_handler = __ib_shared_qp_event_handler;
qp->qp_context = qp;
qp->xrcd = qp_init_attr->xrcd;
atomic_inc(&qp_init_attr->xrcd->usecnt);
INIT_LIST_HEAD(&qp->open_list);
- atomic_set(&qp->usecnt, 0);
real_qp = qp;
qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
error = ipathfs_mknod(parent->d_inode, *dentry,
mode, fops, data);
else
- error = PTR_ERR(dentry);
+ error = PTR_ERR(*dentry);
mutex_unlock(&parent->d_inode->i_mutex);
return error;
return IB_MAD_RESULT_SUCCESS;
/*
- * Don't process SMInfo queries or vendor-specific
- * MADs -- the SMA can't handle them.
+ * Don't process SMInfo queries -- the SMA can't handle them.
*/
- if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
- ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
- IB_SMP_ATTR_VENDOR_MASK))
+ if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
return IB_MAD_RESULT_SUCCESS;
} else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 ||
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
u8 *start_ptr = &start_addr;
u8 **start_buff = &start_ptr;
u16 buff_len = 0;
+ struct ietf_mpa_v1 *mpa_frame;
skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
/* send an MPA reject frame */
cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+ mpa_frame = (struct ietf_mpa_v1 *)*start_buff;
+ mpa_frame->flags |= IETF_MPA_FLAGS_REJECT;
form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
cm_node->state = NES_CM_STATE_FIN_WAIT1;
if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
neigh->ha, ETH_ALEN)) {
/* Mac address same as in nes_arp_table */
- ip_rt_put(rt);
- return rc;
+ goto out;
}
nes_manage_arp_cache(nesvnic->netdev,
neigh_event_send(neigh, NULL);
}
}
+
+out:
rcu_read_unlock();
ip_rt_put(rt);
return rc;
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
-* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+* Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
-* Copyright (c) 2010 Intel-NE, Inc. All rights reserved.
+* Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
ib_wr->wr.fast_reg.length);
+ set_wqe_32bit_value(wqe->wqe_words,
+ NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
ib_wr->wr.fast_reg.rkey);
entry->opcode = IB_WC_SEND;
break;
case NES_IWARP_SQ_OP_LOCINV:
- entry->opcode = IB_WR_LOCAL_INV;
+ entry->opcode = IB_WC_LOCAL_INV;
break;
case NES_IWARP_SQ_OP_FAST_REG:
entry->opcode = IB_WC_FAST_REG_MR;
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,
dd->rcd[0]->rcvhdrq_size,
&dd->cspec->dummy_hdrq_phys,
- GFP_KERNEL | __GFP_COMP);
+ GFP_ATOMIC | __GFP_COMP);
if (!dd->cspec->dummy_hdrq) {
qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");
/* fallback to just 0'ing */
* BIOS may not set PCIe bus-utilization parameters for best performance.
* Check and optionally adjust them to maximize our throughput.
*/
-static int qib_pcie_caps = 0x51;
+static int qib_pcie_caps;
module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);
MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)");
#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)
}
#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;
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;
}
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;
};
module_usb_driver(go7007_usb_driver);
+MODULE_LICENSE("GPL v2");
--- /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
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
-/*
- * 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.
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
#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);
filler_t *filler = logfs_mtd_readpage;
struct mtd_info *mtd = super->s_mtd;
- if (!mtd_can_have_bb(mtd))
- return NULL;
-
*ofs = 0;
while (mtd_block_isbad(mtd, *ofs)) {
*ofs += mtd->erasesize;
filler_t *filler = logfs_mtd_readpage;
struct mtd_info *mtd = super->s_mtd;
- if (!mtd_can_have_bb(mtd))
- return NULL;
-
*ofs = mtd->size - mtd->erasesize;
while (mtd_block_isbad(mtd, *ofs)) {
*ofs -= mtd->erasesize;
static int write_inode(struct inode *inode)
{
- return __logfs_write_inode(inode, WF_LOCK);
+ return __logfs_write_inode(inode, NULL, WF_LOCK);
}
static s64 dir_seek_data(struct inode *inode, s64 pos)
return ret;
mutex_lock(&inode->i_mutex);
+ logfs_get_wblocks(sb, NULL, WF_LOCK);
logfs_write_anchor(sb);
+ logfs_put_wblocks(sb, NULL, WF_LOCK);
mutex_unlock(&inode->i_mutex);
return 0;
int i, max_dist;
struct gc_candidate *cand = NULL, *this;
- max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
+ max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
for (i = max_dist; i >= 0; i--) {
this = first_in_list(&super->s_low_list[i]);
if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
return 0;
- ret = __logfs_write_inode(inode, flags);
+ ret = __logfs_write_inode(inode, NULL, flags);
LOGFS_BUG_ON(ret, inode->i_sb);
return ret;
}
static int logfs_sync_fs(struct super_block *sb, int wait)
{
+ logfs_get_wblocks(sb, NULL, WF_LOCK);
logfs_write_anchor(sb);
+ logfs_put_wblocks(sb, NULL, WF_LOCK);
return 0;
}
if (len == 0)
return logfs_write_header(super, header, 0, type);
- BUG_ON(len > sb->s_blocksize);
compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
if (compr_len < 0 || type == JE_ANCHOR) {
memcpy(data, buf, len);
void logfs_set_blocks(struct inode *inode, u64 no);
/* these logically belong into inode.c but actually reside in readwrite.c */
int logfs_read_inode(struct inode *inode);
-int __logfs_write_inode(struct inode *inode, long flags);
+int __logfs_write_inode(struct inode *inode, struct page *, long flags);
void logfs_evict_inode(struct inode *inode);
/* journal.c */
__be64 *array, int page_is_empty);
int logfs_exist_block(struct inode *inode, u64 bix);
int get_page_reserve(struct inode *inode, struct page *page);
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
extern struct logfs_block_ops indirect_block_ops;
/* segment.c */
void logfs_sync_area(struct logfs_area *area);
void logfs_sync_segments(struct super_block *sb);
void freeseg(struct super_block *sb, u32 segno);
+void free_areas(struct super_block *sb);
/* area handling */
int logfs_init_areas(struct super_block *sb);
* is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked
* in addition to PG_locked.
*/
-static void logfs_get_wblocks(struct super_block *sb, struct page *page,
- int lock)
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
{
struct logfs_super *super = logfs_super(sb);
}
}
-static void logfs_put_wblocks(struct super_block *sb, struct page *page,
- int lock)
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
{
struct logfs_super *super = logfs_super(sb);
if (inode->i_ino == LOGFS_INO_MASTER)
logfs_write_anchor(inode->i_sb);
else {
- ret = __logfs_write_inode(inode, 0);
+ ret = __logfs_write_inode(inode, NULL, 0);
/* see indirect_write_block comment */
BUG_ON(ret);
}
static void indirect_free_block(struct super_block *sb,
struct logfs_block *block)
{
- ClearPagePrivate(block->page);
- block->page->private = 0;
+ struct page *page = block->page;
+
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ set_page_private(page, 0);
+ }
__free_block(sb, block);
}
logfs_unpack_index(page->index, &bix, &level);
block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
block->page = page;
+
SetPagePrivate(page);
- page->private = (unsigned long)block;
+ page_cache_get(page);
+ set_page_private(page, (unsigned long) block);
+
block->ops = &indirect_block_ops;
}
static int __logfs_delete(struct inode *inode, struct page *page)
{
long flags = WF_DELETE;
+ int err;
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
if (page->index < I0_BLOCKS)
return logfs_write_direct(inode, page, flags);
+ err = grow_inode(inode, page->index, 0);
+ if (err)
+ return err;
return logfs_write_rec(inode, page, page->index, 0, flags);
}
if (inode->i_ino == LOGFS_INO_MASTER)
logfs_write_anchor(inode->i_sb);
else {
- err = __logfs_write_inode(inode, flags);
+ err = __logfs_write_inode(inode, page, flags);
}
}
}
logfs_get_wblocks(sb, NULL, 1);
err = __logfs_truncate(inode, size);
if (!err)
- err = __logfs_write_inode(inode, 0);
+ err = __logfs_write_inode(inode, NULL, 0);
logfs_put_wblocks(sb, NULL, 1);
}
li->li_block = block;
block->page = NULL;
- page->private = 0;
- ClearPagePrivate(page);
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ set_page_private(page, 0);
+ }
}
static void move_inode_to_page(struct page *page, struct inode *inode)
BUG_ON(PagePrivate(page));
block->ops = &indirect_block_ops;
block->page = page;
- page->private = (unsigned long)block;
- SetPagePrivate(page);
+
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ set_page_private(page, (unsigned long) block);
+ }
block->inode = NULL;
li->li_block = NULL;
ec_level);
}
-int __logfs_write_inode(struct inode *inode, long flags)
+int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
{
struct super_block *sb = inode->i_sb;
int ret;
- logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
+ logfs_get_wblocks(sb, page, flags & WF_LOCK);
ret = do_write_inode(inode);
- logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
+ logfs_put_wblocks(sb, page, flags & WF_LOCK);
return ret;
}
BUG_ON(!page); /* FIXME: reserve a pool */
SetPageUptodate(page);
memcpy(page_address(page) + offset, buf, copylen);
- SetPagePrivate(page);
+
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ }
page_cache_release(page);
buf += copylen;
page = get_mapping_page(sb, index, 0);
BUG_ON(!page); /* FIXME: reserve a pool */
memset(page_address(page) + offset, 0xff, len);
- SetPagePrivate(page);
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ }
page_cache_release(page);
}
}
BUG_ON(!page); /* FIXME: reserve a pool */
SetPageUptodate(page);
memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
- SetPagePrivate(page);
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ }
page_cache_release(page);
index++;
no_indizes--;
mempool_free(item, super->s_alias_pool);
}
block->page = page;
- SetPagePrivate(page);
- page->private = (unsigned long)block;
+
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ set_page_private(page, (unsigned long) block);
+ }
block->ops = &indirect_block_ops;
initialize_block_counters(page, block, data, 0);
}
list_add(&item->list, &block->item_list);
}
block->page = NULL;
- ClearPagePrivate(page);
- page->private = 0;
+
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ set_page_private(page, 0);
+ }
block->ops = &btree_block_ops;
err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
block);
page = find_get_page(mapping, ofs >> PAGE_SHIFT);
if (!page)
continue;
- ClearPagePrivate(page);
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ }
page_cache_release(page);
}
}
kfree(area);
}
+void free_areas(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ for_each_area(i)
+ free_area(super->s_area[i]);
+ free_area(super->s_journal_area);
+}
+
static struct logfs_area *alloc_area(struct super_block *sb)
{
struct logfs_area *area;
void logfs_cleanup_areas(struct super_block *sb)
{
struct logfs_super *super = logfs_super(sb);
- int i;
btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
- for_each_area(i)
- free_area(super->s_area[i]);
- free_area(super->s_journal_area);
}
/* Alias entries slow down mount, so evict as many as possible */
sync_filesystem(sb);
logfs_write_anchor(sb);
+ free_areas(sb);
/*
* From this point on alias entries are simply dropped - and any
* writes to the object store are considered bugs.
*/
- super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
log_super("LogFS: Now in shutdown\n");
generic_shutdown_super(sb);
+ super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
if (IS_ERR(mm))
return PTR_ERR(mm);
+ if (mm) {
+ /* ensure this mm_struct can't be freed */
+ atomic_inc(&mm->mm_count);
+ /* but do not pin its memory */
+ mmput(mm);
+ }
+
/* OK to pass negative loff_t, we can catch out-of-range */
file->f_mode |= FMODE_UNSIGNED_OFFSET;
file->private_data = mm;
return 0;
}
-static ssize_t mem_read(struct file * file, char __user * buf,
- size_t count, loff_t *ppos)
+static ssize_t mem_rw(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos, int write)
{
- int ret;
- char *page;
- unsigned long src = *ppos;
struct mm_struct *mm = file->private_data;
-
- if (!mm)
- return 0;
-
- page = (char *)__get_free_page(GFP_TEMPORARY);
- if (!page)
- return -ENOMEM;
-
- ret = 0;
-
- while (count > 0) {
- int this_len, retval;
-
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- retval = access_remote_vm(mm, src, page, this_len, 0);
- if (!retval) {
- if (!ret)
- ret = -EIO;
- break;
- }
-
- if (copy_to_user(buf, page, retval)) {
- ret = -EFAULT;
- break;
- }
-
- ret += retval;
- src += retval;
- buf += retval;
- count -= retval;
- }
- *ppos = src;
-
- free_page((unsigned long) page);
- return ret;
-}
-
-static ssize_t mem_write(struct file * file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- int copied;
+ unsigned long addr = *ppos;
+ ssize_t copied;
char *page;
- unsigned long dst = *ppos;
- struct mm_struct *mm = file->private_data;
if (!mm)
return 0;
return -ENOMEM;
copied = 0;
+ if (!atomic_inc_not_zero(&mm->mm_users))
+ goto free;
+
while (count > 0) {
- int this_len, retval;
+ int this_len = min_t(int, count, PAGE_SIZE);
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- if (copy_from_user(page, buf, this_len)) {
+ if (write && copy_from_user(page, buf, this_len)) {
copied = -EFAULT;
break;
}
- retval = access_remote_vm(mm, dst, page, this_len, 1);
- if (!retval) {
+
+ this_len = access_remote_vm(mm, addr, page, this_len, write);
+ if (!this_len) {
if (!copied)
copied = -EIO;
break;
}
- copied += retval;
- buf += retval;
- dst += retval;
- count -= retval;
+
+ if (!write && copy_to_user(buf, page, this_len)) {
+ copied = -EFAULT;
+ break;
+ }
+
+ buf += this_len;
+ addr += this_len;
+ copied += this_len;
+ count -= this_len;
}
- *ppos = dst;
+ *ppos = addr;
+ mmput(mm);
+free:
free_page((unsigned long) page);
return copied;
}
+static ssize_t mem_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, buf, count, ppos, 0);
+}
+
+static ssize_t mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, (char __user*)buf, count, ppos, 1);
+}
+
loff_t mem_lseek(struct file *file, loff_t offset, int orig)
{
switch (orig) {
static int mem_release(struct inode *inode, struct file *file)
{
struct mm_struct *mm = file->private_data;
-
- mmput(mm);
+ if (mm)
+ mmdrop(mm);
return 0;
}
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);
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; }
#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;
__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,
typedef struct gcry_mpi *MPI;
-#define MPI_NULL NULL
-
#define mpi_get_nlimbs(a) ((a)->nlimbs)
#define mpi_is_neg(a) ((a)->sign)
static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
if (!mtd->block_isbad)
- return -EOPNOTSUPP;
+ return 0;
return mtd->block_isbad(mtd, ofs);
}
+++ /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_ */
+++ /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__ */
ptr = ng->ptr[id - 1];
rcu_read_unlock();
+ BUG_ON(!ptr);
return ptr;
}
#endif
#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>
#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 (tsk->nr_dirtied)
__this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
exit_rcu();
+
+ /*
+ * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+ * when the following two conditions become true.
+ * - There is race condition of mmap_sem (It is acquired by
+ * exit_mm()), and
+ * - SMI occurs before setting TASK_RUNINNG.
+ * (or hypervisor of virtual machine switches to other guest)
+ * As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+ *
+ * To avoid it, we have to wait for releasing tsk->pi_lock which
+ * is held by try_to_wake_up()
+ */
+ smp_mb();
+ raw_spin_unlock_wait(&tsk->pi_lock);
+
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;
tsk->flags |= PF_NOFREEZE; /* tell freezer to ignore us */
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");
+}
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:
#include <asm/tlb.h>
#include <asm/irq_regs.h>
+#include <asm/mutex.h>
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#endif
p->sched_class->dequeue_task(rq, p, flags);
}
-/*
- * activate_task - move a task to the runqueue.
- */
void activate_task(struct rq *rq, struct task_struct *p, int flags)
{
if (task_contributes_to_load(p))
enqueue_task(rq, p, flags);
}
-/*
- * deactivate_task - remove a task from the runqueue.
- */
void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
{
if (task_contributes_to_load(p))
on_rq = p->on_rq;
running = task_current(rq, p);
if (on_rq)
- deactivate_task(rq, p, 0);
+ dequeue_task(rq, p, 0);
if (running)
p->sched_class->put_prev_task(rq, p);
if (running)
p->sched_class->set_curr_task(rq);
if (on_rq)
- activate_task(rq, p, 0);
+ enqueue_task(rq, p, 0);
check_class_changed(rq, p, prev_class, oldprio);
task_rq_unlock(rq, p, &flags);
* placed properly.
*/
if (p->on_rq) {
- deactivate_task(rq_src, p, 0);
+ dequeue_task(rq_src, p, 0);
set_task_cpu(p, dest_cpu);
- activate_task(rq_dest, p, 0);
+ enqueue_task(rq_dest, p, 0);
check_preempt_curr(rq_dest, p, 0);
}
done:
on_rq = p->on_rq;
if (on_rq)
- deactivate_task(rq, p, 0);
+ dequeue_task(rq, p, 0);
__setscheduler(rq, p, SCHED_NORMAL, 0);
if (on_rq) {
- activate_task(rq, p, 0);
+ enqueue_task(rq, p, 0);
resched_task(rq->curr);
}
return;
}
+static inline void clear_nohz_tick_stopped(int cpu)
+{
+ if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
+ cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+ atomic_dec(&nohz.nr_cpus);
+ clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
+ }
+}
+
static inline void set_cpu_sd_state_busy(void)
{
struct sched_domain *sd;
{
int cpu = smp_processor_id();
+ /*
+ * If this cpu is going down, then nothing needs to be done.
+ */
+ if (!cpu_active(cpu))
+ return;
+
if (stop_tick) {
if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
return;
}
return;
}
+
+static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_DYING:
+ clear_nohz_tick_stopped(smp_processor_id());
+ return NOTIFY_OK;
+ default:
+ return NOTIFY_DONE;
+ }
+}
#endif
static DEFINE_SPINLOCK(balancing);
* busy tick after returning from idle, we will update the busy stats.
*/
set_cpu_sd_state_busy();
- if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
- clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
- cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
- atomic_dec(&nohz.nr_cpus);
- }
+ clear_nohz_tick_stopped(cpu);
/*
* None are in tickless mode and hence no need for NOHZ idle load
#ifdef CONFIG_NO_HZ
zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
+ cpu_notifier(sched_ilb_notifier, 0);
#endif
#endif /* SMP */
if (!next_task)
return 0;
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+ if (unlikely(task_running(rq, next_task)))
+ return 0;
+#endif
+
retry:
if (unlikely(next_task == rq->curr)) {
WARN_ON(1);
if (__this_cpu_read(soft_watchdog_warn) == true)
return HRTIMER_RESTART;
- printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
+ printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
smp_processor_id(), duration,
current->comm, task_pid_nr(current));
print_modules();
If unsure, say N.
+config CLZ_TAB
+ bool
+
config CORDIC
tristate "CORDIC algorithm"
help
config MPILIB
tristate
+ select CLZ_TAB
help
Multiprecision maths library from GnuPG.
It is used to implement RSA digital signature verification,
obj-$(CONFIG_MPILIB) += mpi/
obj-$(CONFIG_SIGNATURE) += digsig.o
+obj-$(CONFIG_CLZ_TAB) += clz_tab.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
return BUG_TRAP_TYPE_WARN;
}
- printk(KERN_EMERG "------------[ cut here ]------------\n");
+ printk(KERN_DEFAULT "------------[ cut here ]------------\n");
if (file)
printk(KERN_CRIT "kernel BUG at %s:%u!\n",
--- /dev/null
+const unsigned char __clz_tab[] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+};
unsigned long msglen,
unsigned long modulus_bitlen,
unsigned char *out,
- unsigned long *outlen,
- int *is_valid)
+ unsigned long *outlen)
{
unsigned long modulus_len, ps_len, i;
- int result;
-
- /* default to invalid packet */
- *is_valid = 0;
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
return -EINVAL;
/* separate encoded message */
- if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) {
- result = -EINVAL;
- goto bail;
- }
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
+ return -EINVAL;
for (i = 2; i < modulus_len - 1; i++)
if (msg[i] != 0xFF)
break;
/* separator check */
- if (msg[i] != 0) {
+ if (msg[i] != 0)
/* There was no octet with hexadecimal value 0x00
to separate ps from m. */
- result = -EINVAL;
- goto bail;
- }
+ return -EINVAL;
ps_len = i - 2;
if (*outlen < (msglen - (2 + ps_len + 1))) {
*outlen = msglen - (2 + ps_len + 1);
- result = -EOVERFLOW;
- goto bail;
+ return -EOVERFLOW;
}
*outlen = (msglen - (2 + ps_len + 1));
memcpy(out, &msg[2 + ps_len + 1], *outlen);
- /* valid packet */
- *is_valid = 1;
- result = 0;
-bail:
- return result;
+ return 0;
}
/*
unsigned long len;
unsigned long mlen, mblen;
unsigned nret, l;
- int valid, head, i;
+ int head, i;
unsigned char *out1 = NULL, *out2 = NULL;
MPI in = NULL, res = NULL, pkey[2];
uint8_t *p, *datap, *endp;
down_read(&key->sem);
ukp = key->payload.data;
+
+ if (ukp->datalen < sizeof(*pkh))
+ goto err1;
+
pkh = (struct pubkey_hdr *)ukp->data;
if (pkh->version != 1)
goto err1;
datap = pkh->mpi;
- endp = datap + ukp->datalen;
+ endp = ukp->data + ukp->datalen;
+
+ err = -ENOMEM;
for (i = 0; i < pkh->nmpi; i++) {
unsigned int remaining = endp - datap;
pkey[i] = mpi_read_from_buffer(datap, &remaining);
+ if (!pkey[i])
+ goto err;
datap += remaining;
}
mblen = mpi_get_nbits(pkey[0]);
mlen = (mblen + 7)/8;
- err = -ENOMEM;
+ if (mlen == 0)
+ goto err;
out1 = kzalloc(mlen, GFP_KERNEL);
if (!out1)
memset(out1, 0, head);
memcpy(out1 + head, p, l);
- err = -EINVAL;
- pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid);
+ err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
- if (valid && len == hlen)
+ if (!err && len == hlen)
err = memcmp(out2, h, hlen);
err:
mpi_free(res);
kfree(out1);
kfree(out2);
- mpi_free(pkey[0]);
- mpi_free(pkey[1]);
+ while (--i >= 0)
+ mpi_free(pkey[i]);
err1:
up_read(&key->sem);
"r" ((USItype)(v)) \
: "%g1", "%g2" __AND_CLOBBER_CC)
#define UMUL_TIME 39 /* 39 instructions */
-#endif
-#ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
+/* It's quite necessary to add this much assembler for the sparc.
+ The default udiv_qrnnd (in C) is more than 10 times slower! */
#define udiv_qrnnd(q, r, n1, n0, d) \
-do { USItype __r; \
- (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
- (r) = __r; \
-} while (0)
- extern USItype __udiv_qrnnd();
-#define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
-#endif /* udiv_qrnnd */
+ __asm__ ("! Inlined udiv_qrnnd\n\t" \
+ "mov 32,%%g1\n\t" \
+ "subcc %1,%2,%%g0\n\t" \
+ "1: bcs 5f\n\t" \
+ "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
+ "sub %1,%2,%1 ! this kills msb of n\n\t" \
+ "addx %1,%1,%1 ! so this can't give carry\n\t" \
+ "subcc %%g1,1,%%g1\n\t" \
+ "2: bne 1b\n\t" \
+ "subcc %1,%2,%%g0\n\t" \
+ "bcs 3f\n\t" \
+ "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
+ "b 3f\n\t" \
+ "sub %1,%2,%1 ! this kills msb of n\n\t" \
+ "4: sub %1,%2,%1\n\t" \
+ "5: addxcc %1,%1,%1\n\t" \
+ "bcc 2b\n\t" \
+ "subcc %%g1,1,%%g1\n\t" \
+ "! Got carry from n. Subtract next step to cancel this carry.\n\t" \
+ "bne 4b\n\t" \
+ "addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \
+ "sub %1,%2,%1\n\t" \
+ "3: xnor %0,0,%0\n\t" \
+ "! End of inline udiv_qrnnd\n" \
+ : "=&r" ((USItype)(q)), \
+ "=&r" ((USItype)(r)) \
+ : "r" ((USItype)(d)), \
+ "1" ((USItype)(n1)), \
+ "0" ((USItype)(n0)) : "%g1", "cc")
+#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
+#endif
#endif /* __sparc__ */
/***************************************
#include "mpi-internal.h"
#include "longlong.h"
-const unsigned char __clz_tab[] = {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
-};
-
#define A_LIMB_1 ((mpi_limb_t) 1)
/****************
mpi_ptr_t marker[5];
int markidx = 0;
+ if (!dsize)
+ return -EINVAL;
+
memset(marker, 0, sizeof(marker));
/* Ensure space is enough for quotient and remainder.
* numerator would be gradually overwritten by the quotient limbs. */
if (qp == np) { /* Copy NP object to temporary space. */
np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+ if (!np)
+ goto nomem;
MPN_COPY(np, qp, nsize);
}
} else /* Put quotient at top of remainder. */
ep = exp->d;
if (!msize)
- msize = 1 / msize; /* provoke a signal */
+ return -EINVAL;
if (!esize) {
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
#include "mpi-internal.h"
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define MAX_EXTERN_MPI_BITS 16384
-static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
- 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
-MPI do_encode_md(const void *sha_buffer, unsigned nbits)
-{
- int nframe = (nbits + 7) / 8;
- uint8_t *frame, *fr_pt;
- int i = 0, n;
- size_t asnlen = DIM(asn);
- MPI a = MPI_NULL;
-
- if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
- pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
- (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
-
- /* We encode the MD in this way:
- *
- * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
- frame = kmalloc(nframe, GFP_KERNEL);
- if (!frame)
- return MPI_NULL;
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
-
- if (i <= 1) {
- pr_info("MPI: message digest encoding failed\n");
- kfree(frame);
- return a;
- }
-
- memset(frame + n, 0xff, i);
- n += i;
- frame[n++] = 0;
- memcpy(frame + n, &asn, asnlen);
- n += asnlen;
- memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
- n += SHA1_DIGEST_LENGTH;
-
- i = nframe;
- fr_pt = frame;
-
- if (n != nframe) {
- printk
- ("MPI: message digest encoding failed, frame length is wrong\n");
- kfree(frame);
- return a;
- }
-
- a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
- mpi_set_buffer(a, frame, nframe, 0);
- kfree(frame);
-
- return a;
-}
-
MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
{
const uint8_t *buffer = xbuffer;
int i, j;
unsigned nbits, nbytes, nlimbs, nread = 0;
mpi_limb_t a;
- MPI val = MPI_NULL;
+ MPI val = NULL;
if (*ret_nread < 2)
goto leave;
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
val = mpi_alloc(nlimbs);
if (!val)
- return MPI_NULL;
+ return NULL;
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
}
EXPORT_SYMBOL_GPL(mpi_fromstr);
-/****************
- * Special function to get the low 8 bytes from an mpi.
- * This can be used as a keyid; KEYID is an 2 element array.
- * Return the low 4 bytes.
- */
-u32 mpi_get_keyid(const MPI a, u32 *keyid)
-{
-#if BYTES_PER_MPI_LIMB == 4
- if (keyid) {
- keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
- keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
- }
- return a->nlimbs >= 1 ? a->d[0] : 0;
-#elif BYTES_PER_MPI_LIMB == 8
- if (keyid) {
- keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
- keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
- }
- return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-#else
-#error Make this function work with other LIMB sizes
-#endif
-}
-
/****************
* Return an allocated buffer with the MPI (msb first).
* NBYTES receives the length of this buffer. Caller must free the
case 0:
/* We are asked to divide by zero, so go ahead and do it! (To make
the compiler not remove this statement, return the value.) */
+ /*
+ * existing clients of this function have been modified
+ * not to call it with dsize == 0, so this should not happen
+ */
return 1 / dsize;
case 1:
{
size_t len = nlimbs * sizeof(mpi_limb_t);
+ if (!len)
+ return NULL;
+
return kmalloc(len, GFP_KERNEL);
}
size_t i;
MPI b;
- *copied = MPI_NULL;
+ *copied = NULL;
if (a) {
b = mpi_alloc(a->nlimbs);
{
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);
#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) {
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;
}
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;
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;
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;
}
{
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)
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++;
}
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);
}
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;
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;
/* 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),
{}
};
/* 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))