From 016bfc449a88c833e949414a41748b359843dbb1 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 25 Jun 2015 18:44:04 +0200 Subject: x86/asm/tsc, input/joystick/analog: Switch from rdtscl() to native_read_tsc() This timing code is hideous, and this doesn't help. It gets rid of one of the last users of rdtscl(), though. Signed-off-by: Andy Lutomirski Signed-off-by: Borislav Petkov Acked-by: Dmitry Torokhov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Huang Rui Cc: John Stultz Cc: Len Brown Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Ralf Baechle Cc: Thomas Gleixner Cc: kvm ML Cc: linux-input@vger.kernel.org Link: http://lkml.kernel.org/r/90d19b3cea0e05ca6f333d1598daa38afb993260.1434501121.git.luto@kernel.org Signed-off-by: Ingo Molnar --- drivers/input/joystick/analog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 4284080e481d..f871b4f00056 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -143,7 +143,7 @@ struct analog_port { #include -#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0) +#define GET_TIME(x) do { if (cpu_has_tsc) x = (unsigned int)native_read_tsc(); else x = get_time_pit(); } while (0) #define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0))) #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") static unsigned int get_time_pit(void) @@ -160,7 +160,7 @@ static unsigned int get_time_pit(void) return count; } #elif defined(__x86_64__) -#define GET_TIME(x) rdtscl(x) +#define GET_TIME(x) do { x = (unsigned int)native_read_tsc(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "TSC" #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE) -- cgit v1.2.3 From 732f374ba50b64150bf954c2d4e9f6fae583cccf Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 25 Jun 2015 18:44:05 +0200 Subject: x86/asm/tsc, drivers/input/gameport: Replace rdtscl() with native_read_tsc() It's unclear to me why this code exists in the first place. Signed-off-by: Andy Lutomirski Signed-off-by: Borislav Petkov Acked-by: Dmitry Torokhov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Huang Rui Cc: John Stultz Cc: Len Brown Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Ralf Baechle Cc: Thomas Gleixner Cc: kvm ML Cc: linux-input@vger.kernel.org Link: http://lkml.kernel.org/r/9e058e72f4cf1f13c6483c1360b39c3d188a2c2a.1434501121.git.luto@kernel.org Signed-off-by: Ingo Molnar --- drivers/input/gameport/gameport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index e853a2134680..abc0cb22e750 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -149,9 +149,9 @@ static int old_gameport_measure_speed(struct gameport *gameport) for(i = 0; i < 50; i++) { local_irq_save(flags); - rdtscl(t1); + t1 = native_read_tsc(); for (t = 0; t < 50; t++) gameport_read(gameport); - rdtscl(t2); + t2 = native_read_tsc(); local_irq_restore(flags); udelay(i * 10); if (t2 - t1 < tx) tx = t2 - t1; -- cgit v1.2.3 From 4ea1636b04dbd66536fa387bae2eea463efc705b Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 25 Jun 2015 18:44:07 +0200 Subject: x86/asm/tsc: Rename native_read_tsc() to rdtsc() Now that there is no paravirt TSC, the "native" is inappropriate. The function does RDTSC, so give it the obvious name: rdtsc(). Suggested-by: Borislav Petkov Signed-off-by: Andy Lutomirski Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Huang Rui Cc: John Stultz Cc: Len Brown Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Ralf Baechle Cc: Thomas Gleixner Cc: kvm ML Link: http://lkml.kernel.org/r/fd43e16281991f096c1e4d21574d9e1402c62d39.1434501121.git.luto@kernel.org [ Ported it to v4.2-rc1. ] Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/aslr.c | 2 +- arch/x86/entry/vdso/vclock_gettime.c | 2 +- arch/x86/include/asm/msr.h | 11 ++++++++++- arch/x86/include/asm/pvclock.h | 2 +- arch/x86/include/asm/stackprotector.h | 2 +- arch/x86/include/asm/tsc.h | 2 +- arch/x86/kernel/apb_timer.c | 8 ++++---- arch/x86/kernel/apic/apic.c | 8 ++++---- arch/x86/kernel/cpu/amd.c | 4 ++-- arch/x86/kernel/cpu/mcheck/mce.c | 4 ++-- arch/x86/kernel/espfix_64.c | 2 +- arch/x86/kernel/hpet.c | 4 ++-- arch/x86/kernel/trace_clock.c | 2 +- arch/x86/kernel/tsc.c | 4 ++-- arch/x86/kvm/lapic.c | 4 ++-- arch/x86/kvm/svm.c | 4 ++-- arch/x86/kvm/vmx.c | 4 ++-- arch/x86/kvm/x86.c | 12 ++++++------ arch/x86/lib/delay.c | 8 ++++---- drivers/cpufreq/intel_pstate.c | 2 +- drivers/input/gameport/gameport.c | 4 ++-- drivers/input/joystick/analog.c | 4 ++-- drivers/net/hamradio/baycom_epp.c | 2 +- drivers/thermal/intel_powerclamp.c | 4 ++-- tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c | 4 ++-- 25 files changed, 59 insertions(+), 50 deletions(-) (limited to 'drivers/input') diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c index ea33236190b1..6a9b96b4624d 100644 --- a/arch/x86/boot/compressed/aslr.c +++ b/arch/x86/boot/compressed/aslr.c @@ -82,7 +82,7 @@ static unsigned long get_random_long(void) if (has_cpuflag(X86_FEATURE_TSC)) { debug_putstr(" RDTSC"); - raw = native_read_tsc(); + raw = rdtsc(); random ^= raw; use_i8254 = false; diff --git a/arch/x86/entry/vdso/vclock_gettime.c b/arch/x86/entry/vdso/vclock_gettime.c index 972b488ac16a..0340d93c18ca 100644 --- a/arch/x86/entry/vdso/vclock_gettime.c +++ b/arch/x86/entry/vdso/vclock_gettime.c @@ -186,7 +186,7 @@ notrace static cycle_t vread_tsc(void) * but no one has ever seen it happen. */ rdtsc_barrier(); - ret = (cycle_t)native_read_tsc(); + ret = (cycle_t)rdtsc(); last = gtod->cycle_last; diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index c89ed6ceed02..ff0c120dafe5 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -109,7 +109,16 @@ notrace static inline int native_write_msr_safe(unsigned int msr, extern int rdmsr_safe_regs(u32 regs[8]); extern int wrmsr_safe_regs(u32 regs[8]); -static __always_inline unsigned long long native_read_tsc(void) +/** + * rdtsc() - returns the current TSC without ordering constraints + * + * rdtsc() returns the result of RDTSC as a 64-bit integer. The + * only ordering constraint it supplies is the ordering implied by + * "asm volatile": it will put the RDTSC in the place you expect. The + * CPU can and will speculatively execute that RDTSC, though, so the + * results can be non-monotonic if compared on different CPUs. + */ +static __always_inline unsigned long long rdtsc(void) { DECLARE_ARGS(val, low, high); diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 2bd69d62c623..5c490db62e32 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -62,7 +62,7 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) static __always_inline u64 pvclock_get_nsec_offset(const struct pvclock_vcpu_time_info *src) { - u64 delta = native_read_tsc() - src->tsc_timestamp; + u64 delta = rdtsc() - src->tsc_timestamp; return pvclock_scale_delta(delta, src->tsc_to_system_mul, src->tsc_shift); } diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index bc5fa2af112e..58505f01962f 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -72,7 +72,7 @@ static __always_inline void boot_init_stack_canary(void) * on during the bootup the random pool has true entropy too. */ get_random_bytes(&canary, sizeof(canary)); - tsc = native_read_tsc(); + tsc = rdtsc(); canary += tsc + (tsc << 32UL); current->stack_canary = canary; diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index b4883902948b..3df7675debcf 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -26,7 +26,7 @@ static inline cycles_t get_cycles(void) return 0; #endif - return native_read_tsc(); + return rdtsc(); } extern void tsc_init(void); diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 25efa534c4e4..222a57076039 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c @@ -263,7 +263,7 @@ static int apbt_clocksource_register(void) /* Verify whether apbt counter works */ t1 = dw_apb_clocksource_read(clocksource_apbt); - start = native_read_tsc(); + start = rdtsc(); /* * We don't know the TSC frequency yet, but waiting for @@ -273,7 +273,7 @@ static int apbt_clocksource_register(void) */ do { rep_nop(); - now = native_read_tsc(); + now = rdtsc(); } while ((now - start) < 200000UL); /* APBT is the only always on clocksource, it has to work! */ @@ -390,13 +390,13 @@ unsigned long apbt_quick_calibrate(void) old = dw_apb_clocksource_read(clocksource_apbt); old += loop; - t1 = native_read_tsc(); + t1 = rdtsc(); do { new = dw_apb_clocksource_read(clocksource_apbt); } while (new < old); - t2 = native_read_tsc(); + t2 = rdtsc(); shift = 5; if (unlikely(loop >> shift == 0)) { diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 51af1ed1ae2e..0d71cd9b4a50 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -457,7 +457,7 @@ static int lapic_next_deadline(unsigned long delta, { u64 tsc; - tsc = native_read_tsc(); + tsc = rdtsc(); wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR)); return 0; } @@ -592,7 +592,7 @@ static void __init lapic_cal_handler(struct clock_event_device *dev) unsigned long pm = acpi_pm_read_early(); if (cpu_has_tsc) - tsc = native_read_tsc(); + tsc = rdtsc(); switch (lapic_cal_loops++) { case 0: @@ -1209,7 +1209,7 @@ void setup_local_APIC(void) long long max_loops = cpu_khz ? cpu_khz : 1000000; if (cpu_has_tsc) - tsc = native_read_tsc(); + tsc = rdtsc(); if (disable_apic) { disable_ioapic_support(); @@ -1293,7 +1293,7 @@ void setup_local_APIC(void) } if (queued) { if (cpu_has_tsc && cpu_khz) { - ntsc = native_read_tsc(); + ntsc = rdtsc(); max_loops = (cpu_khz << 10) - (ntsc - tsc); } else max_loops--; diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index a69710db6112..51ad2af84a72 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -125,10 +125,10 @@ static void init_amd_k6(struct cpuinfo_x86 *c) n = K6_BUG_LOOP; f_vide = vide; - d = native_read_tsc(); + d = rdtsc(); while (n--) f_vide(); - d2 = native_read_tsc(); + d2 = rdtsc(); d = d2-d; if (d > 20*K6_BUG_LOOP) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index a5283d2d0094..96cceccd11b4 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -125,7 +125,7 @@ void mce_setup(struct mce *m) { memset(m, 0, sizeof(struct mce)); m->cpu = m->extcpu = smp_processor_id(); - m->tsc = native_read_tsc(); + m->tsc = rdtsc(); /* We hope get_seconds stays lockless */ m->time = get_seconds(); m->cpuvendor = boot_cpu_data.x86_vendor; @@ -1784,7 +1784,7 @@ static void collect_tscs(void *data) { unsigned long *cpu_tsc = (unsigned long *)data; - cpu_tsc[smp_processor_id()] = native_read_tsc(); + cpu_tsc[smp_processor_id()] = rdtsc(); } static int mce_apei_read_done; diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c index 334a2a9c034d..67315cd0132c 100644 --- a/arch/x86/kernel/espfix_64.c +++ b/arch/x86/kernel/espfix_64.c @@ -110,7 +110,7 @@ static void init_espfix_random(void) */ if (!arch_get_random_long(&rand)) { /* The constant is an arbitrary large prime */ - rand = native_read_tsc(); + rand = rdtsc(); rand *= 0xc345c6b72fd16123UL; } diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index cc390fe69b71..f75c5908c7a6 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -735,7 +735,7 @@ static int hpet_clocksource_register(void) /* Verify whether hpet counter works */ t1 = hpet_readl(HPET_COUNTER); - start = native_read_tsc(); + start = rdtsc(); /* * We don't know the TSC frequency yet, but waiting for @@ -745,7 +745,7 @@ static int hpet_clocksource_register(void) */ do { rep_nop(); - now = native_read_tsc(); + now = rdtsc(); } while ((now - start) < 200000UL); if (t1 == hpet_readl(HPET_COUNTER)) { diff --git a/arch/x86/kernel/trace_clock.c b/arch/x86/kernel/trace_clock.c index bd8f4d41bd56..67efb8c96fc4 100644 --- a/arch/x86/kernel/trace_clock.c +++ b/arch/x86/kernel/trace_clock.c @@ -15,7 +15,7 @@ u64 notrace trace_clock_x86_tsc(void) u64 ret; rdtsc_barrier(); - ret = native_read_tsc(); + ret = rdtsc(); return ret; } diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index e66f5dcaeb63..21d6e04e3e82 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -248,7 +248,7 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) data = cyc2ns_write_begin(cpu); - tsc_now = native_read_tsc(); + tsc_now = rdtsc(); ns_now = cycles_2_ns(tsc_now); /* @@ -290,7 +290,7 @@ u64 native_sched_clock(void) } /* read the Time Stamp Counter: */ - tsc_now = native_read_tsc(); + tsc_now = rdtsc(); /* return the value in ns */ return cycles_2_ns(tsc_now); diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 954e98a8c2e3..2f0ade48614f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1172,7 +1172,7 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu) tsc_deadline = apic->lapic_timer.expired_tscdeadline; apic->lapic_timer.expired_tscdeadline = 0; - guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, native_read_tsc()); + guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, rdtsc()); trace_kvm_wait_lapic_expire(vcpu->vcpu_id, guest_tsc - tsc_deadline); /* __delay is delay_tsc whenever the hardware has TSC, thus always. */ @@ -1240,7 +1240,7 @@ static void start_apic_timer(struct kvm_lapic *apic) local_irq_save(flags); now = apic->lapic_timer.timer.base->get_time(); - guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, native_read_tsc()); + guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, rdtsc()); if (likely(tscdeadline > guest_tsc)) { ns = (tscdeadline - guest_tsc) * 1000000ULL; do_div(ns, this_tsc_khz); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 602b974a60a6..8dfbad7a2c44 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1080,7 +1080,7 @@ static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc) { u64 tsc; - tsc = svm_scale_tsc(vcpu, native_read_tsc()); + tsc = svm_scale_tsc(vcpu, rdtsc()); return target_tsc - tsc; } @@ -3079,7 +3079,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) switch (msr_info->index) { case MSR_IA32_TSC: { msr_info->data = svm->vmcb->control.tsc_offset + - svm_scale_tsc(vcpu, native_read_tsc()); + svm_scale_tsc(vcpu, rdtsc()); break; } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4fa1ccad7beb..10d69a6df14f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2236,7 +2236,7 @@ static u64 guest_read_tsc(void) { u64 host_tsc, tsc_offset; - host_tsc = native_read_tsc(); + host_tsc = rdtsc(); tsc_offset = vmcs_read64(TSC_OFFSET); return host_tsc + tsc_offset; } @@ -2317,7 +2317,7 @@ static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc) { - return target_tsc - native_read_tsc(); + return target_tsc - rdtsc(); } static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f771058cfb5c..dfa97139282d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1455,7 +1455,7 @@ static cycle_t read_tsc(void) * but no one has ever seen it happen. */ rdtsc_barrier(); - ret = (cycle_t)native_read_tsc(); + ret = (cycle_t)rdtsc(); last = pvclock_gtod_data.clock.cycle_last; @@ -1646,7 +1646,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) return 1; } if (!use_master_clock) { - host_tsc = native_read_tsc(); + host_tsc = rdtsc(); kernel_ns = get_kernel_ns(); } @@ -2810,7 +2810,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (unlikely(vcpu->cpu != cpu) || check_tsc_unstable()) { s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 : - native_read_tsc() - vcpu->arch.last_host_tsc; + rdtsc() - vcpu->arch.last_host_tsc; if (tsc_delta < 0) mark_tsc_unstable("KVM discovered backwards TSC"); if (check_tsc_unstable()) { @@ -2838,7 +2838,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) { kvm_x86_ops->vcpu_put(vcpu); kvm_put_guest_fpu(vcpu); - vcpu->arch.last_host_tsc = native_read_tsc(); + vcpu->arch.last_host_tsc = rdtsc(); } static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu, @@ -6623,7 +6623,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) hw_breakpoint_restore(); vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, - native_read_tsc()); + rdtsc()); vcpu->mode = OUTSIDE_GUEST_MODE; smp_wmb(); @@ -7437,7 +7437,7 @@ int kvm_arch_hardware_enable(void) if (ret != 0) return ret; - local_tsc = native_read_tsc(); + local_tsc = rdtsc(); stable = !check_tsc_unstable(); list_for_each_entry(kvm, &vm_list, vm_list) { kvm_for_each_vcpu(i, vcpu, kvm) { diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index 35115f3786a9..f24bc59ab0a0 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c @@ -55,10 +55,10 @@ static void delay_tsc(unsigned long __loops) preempt_disable(); cpu = smp_processor_id(); rdtsc_barrier(); - bclock = native_read_tsc(); + bclock = rdtsc(); for (;;) { rdtsc_barrier(); - now = native_read_tsc(); + now = rdtsc(); if ((now - bclock) >= loops) break; @@ -80,7 +80,7 @@ static void delay_tsc(unsigned long __loops) loops -= (now - bclock); cpu = smp_processor_id(); rdtsc_barrier(); - bclock = native_read_tsc(); + bclock = rdtsc(); } } preempt_enable(); @@ -100,7 +100,7 @@ void use_tsc_delay(void) int read_current_timer(unsigned long *timer_val) { if (delay_fn == delay_tsc) { - *timer_val = native_read_tsc(); + *timer_val = rdtsc(); return 0; } return -1; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 15ada47bb720..7c56d7eaa671 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -765,7 +765,7 @@ static inline void intel_pstate_sample(struct cpudata *cpu) local_irq_save(flags); rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_MPERF, mperf); - tsc = native_read_tsc(); + tsc = rdtsc(); local_irq_restore(flags); cpu->last_sample_time = cpu->sample.time; diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index abc0cb22e750..4a2a9e370be7 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -149,9 +149,9 @@ static int old_gameport_measure_speed(struct gameport *gameport) for(i = 0; i < 50; i++) { local_irq_save(flags); - t1 = native_read_tsc(); + t1 = rdtsc(); for (t = 0; t < 50; t++) gameport_read(gameport); - t2 = native_read_tsc(); + t2 = rdtsc(); local_irq_restore(flags); udelay(i * 10); if (t2 - t1 < tx) tx = t2 - t1; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index f871b4f00056..6f8b084e13d0 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -143,7 +143,7 @@ struct analog_port { #include -#define GET_TIME(x) do { if (cpu_has_tsc) x = (unsigned int)native_read_tsc(); else x = get_time_pit(); } while (0) +#define GET_TIME(x) do { if (cpu_has_tsc) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0) #define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0))) #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") static unsigned int get_time_pit(void) @@ -160,7 +160,7 @@ static unsigned int get_time_pit(void) return count; } #elif defined(__x86_64__) -#define GET_TIME(x) do { x = (unsigned int)native_read_tsc(); } while (0) +#define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "TSC" #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE) diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 44e5c3b5e0af..72c9f1f352b4 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -638,7 +638,7 @@ static int receive(struct net_device *dev, int cnt) #define GETTICK(x) \ ({ \ if (cpu_has_tsc) \ - x = (unsigned int)native_read_tsc(); \ + x = (unsigned int)rdtsc(); \ }) #else /* __i386__ */ #define GETTICK(x) diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index ab13448defcf..2ac0c704bcb8 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c @@ -340,7 +340,7 @@ static bool powerclamp_adjust_controls(unsigned int target_ratio, /* check result for the last window */ msr_now = pkg_state_counter(); - tsc_now = native_read_tsc(); + tsc_now = rdtsc(); /* calculate pkg cstate vs tsc ratio */ if (!msr_last || !tsc_last) @@ -482,7 +482,7 @@ static void poll_pkg_cstate(struct work_struct *dummy) u64 val64; msr_now = pkg_state_counter(); - tsc_now = native_read_tsc(); + tsc_now = rdtsc(); jiffies_now = jiffies; /* calculate pkg cstate vs tsc ratio */ diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c index f02b0c0bff9b..6ff8383f2941 100644 --- a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c +++ b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c @@ -81,11 +81,11 @@ static int __init cpufreq_test_tsc(void) printk(KERN_DEBUG "start--> \n"); then = read_pmtmr(); - then_tsc = native_read_tsc(); + then_tsc = rdtsc(); for (i=0;i<20;i++) { mdelay(100); now = read_pmtmr(); - now_tsc = native_read_tsc(); + now_tsc = rdtsc(); diff = (now - then) & 0xFFFFFF; diff_tsc = now_tsc - then_tsc; printk(KERN_DEBUG "t1: %08u t2: %08u diff_pmtmr: %08u diff_tsc: %016llu\n", then, now, diff, diff_tsc); -- cgit v1.2.3 From d3dc6e2322155087c19a1d6a71818be534de0602 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Wed, 27 May 2015 00:26:00 +0800 Subject: input: keyboard: imx: add snvs power key driver add snvs power key driver. It work in imx chips after i.mx6sx ON/OFF key used power on/off whole system. This driver make it wakeup from suspend state when short press ON/OFF key. Long time press will trig SNVS power off chip without software intervention. Signed-off-by: Robin Gong Signed-off-by: Frank Li Acked-by: Dmitry Torokhov Signed-off-by: Shawn Guo --- drivers/input/keyboard/Kconfig | 11 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/snvs_pwrkey.c | 227 +++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/input/keyboard/snvs_pwrkey.c (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4cd94fd6cbad..82a8fb50afac 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -401,6 +401,17 @@ config KEYBOARD_MPR121 To compile this driver as a module, choose M here: the module will be called mpr121_touchkey. +config KEYBOARD_SNVS_PWRKEY + tristate "IMX SNVS Power Key Driver" + depends on SOC_IMX6SX + depends on OF + help + This is the snvs powerkey driver for the Freescale i.MX application + processors that are newer than i.MX6 SX. + + To compile this driver as a module, choose M here; the + module will be called snvs_pwrkey. + config KEYBOARD_IMX tristate "IMX keypad support" depends on ARCH_MXC diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index df28d5553c05..1d416ddf84e4 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o +obj-$(CONFIG_KEYBOARD_SNVS_PWRKEY) += snvs_pwrkey.o obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c new file mode 100644 index 000000000000..512a1fc2a864 --- /dev/null +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -0,0 +1,227 @@ +/* + * Driver for the IMX SNVS ON/OFF Power Key + * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SNVS_LPSR_REG 0x4C /* LP Status Register */ +#define SNVS_LPCR_REG 0x38 /* LP Control Register */ +#define SNVS_HPSR_REG 0x14 +#define SNVS_HPSR_BTN BIT(6) +#define SNVS_LPSR_SPO BIT(18) +#define SNVS_LPCR_DEP_EN BIT(5) + +#define DEBOUNCE_TIME 30 +#define REPEAT_INTERVAL 60 + +struct pwrkey_drv_data { + struct regmap *snvs; + int irq; + int keycode; + int keystate; /* 1:pressed */ + int wakeup; + struct timer_list check_timer; + struct input_dev *input; +}; + +static void imx_imx_snvs_check_for_events(unsigned long data) +{ + struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data; + struct input_dev *input = pdata->input; + u32 state; + + regmap_read(pdata->snvs, SNVS_HPSR_REG, &state); + state = state & SNVS_HPSR_BTN ? 1 : 0; + + /* only report new event if status changed */ + if (state ^ pdata->keystate) { + pdata->keystate = state; + input_event(input, EV_KEY, pdata->keycode, state); + input_sync(input); + pm_relax(pdata->input->dev.parent); + } + + /* repeat check if pressed long */ + if (state) { + mod_timer(&pdata->check_timer, + jiffies + msecs_to_jiffies(REPEAT_INTERVAL)); + } +} + +static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id) +{ + struct platform_device *pdev = dev_id; + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev); + u32 lp_status; + + pm_wakeup_event(pdata->input->dev.parent, 0); + + regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status); + if (lp_status & SNVS_LPSR_SPO) + mod_timer(&pdata->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME)); + + /* clear SPO status */ + regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO); + + return IRQ_HANDLED; +} + +static void imx_snvs_pwrkey_act(void *pdata) +{ + struct pwrkey_drv_data *pd = pdata; + + del_timer_sync(&pd->check_timer); +} + +static int imx_snvs_pwrkey_probe(struct platform_device *pdev) +{ + struct pwrkey_drv_data *pdata = NULL; + struct input_dev *input = NULL; + struct device_node *np; + int error; + + /* Get SNVS register Page */ + np = pdev->dev.of_node; + if (!np) + return -ENODEV; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");; + + if (!pdata->snvs) { + dev_err(&pdev->dev, "Can't get snvs syscon\n"); + return -ENODEV; + } + + if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) { + pdata->keycode = KEY_POWER; + dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n"); + } + + pdata->wakeup = of_property_read_bool(np, "wakeup"); + + pdata->irq = platform_get_irq(pdev, 0); + if (pdata->irq < 0) { + dev_err(&pdev->dev, "no irq defined in platform data\n"); + return -EINVAL; + } + + regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN); + + /* clear the unexpected interrupt before driver ready */ + regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO); + + setup_timer(&pdata->check_timer, + imx_imx_snvs_check_for_events, (unsigned long) pdata); + + input = devm_input_allocate_device(&pdev->dev); + if (!input) { + dev_err(&pdev->dev, "failed to allocate the input device\n"); + return -ENOMEM; + } + + input->name = pdev->name; + input->phys = "snvs-pwrkey/input0"; + input->id.bustype = BUS_HOST; + + input_set_capability(input, EV_KEY, pdata->keycode); + + /* input customer action to cancel release timer */ + error = devm_add_action(&pdev->dev, imx_snvs_pwrkey_act, pdata); + if (error) { + dev_err(&pdev->dev, "failed to register remove action\n"); + return error; + } + + error = devm_request_irq(&pdev->dev, pdata->irq, + imx_snvs_pwrkey_interrupt, + 0, pdev->name, pdev); + + if (error) { + dev_err(&pdev->dev, "interrupt not available.\n"); + return error; + } + + error = input_register_device(input); + if (error < 0) { + dev_err(&pdev->dev, "failed to register input device\n"); + input_free_device(input); + return error; + } + + pdata->input = input; + platform_set_drvdata(pdev, pdata); + + device_init_wakeup(&pdev->dev, pdata->wakeup); + + return 0; +} + +static int imx_snvs_pwrkey_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(pdata->irq); + + return 0; +} + +static int imx_snvs_pwrkey_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev); + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(pdata->irq); + + return 0; +} + +static const struct of_device_id imx_snvs_pwrkey_ids[] = { + { .compatible = "fsl,sec-v4.0-pwrkey" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids); + +static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops, imx_snvs_pwrkey_suspend, + imx_snvs_pwrkey_resume); + +static struct platform_driver imx_snvs_pwrkey_driver = { + .driver = { + .name = "snvs_pwrkey", + .pm = &imx_snvs_pwrkey_pm_ops, + .of_match_table = imx_snvs_pwrkey_ids, + }, + .probe = imx_snvs_pwrkey_probe, +}; +module_platform_driver(imx_snvs_pwrkey_driver); + +MODULE_AUTHOR("Freescale Semiconductor"); +MODULE_DESCRIPTION("i.MX snvs power key Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 61b305cd2ae747b8c9a2e4467dea2575a390162c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 15 Jul 2015 21:59:50 +0900 Subject: drivers: max77693: Move state container to common header This prepares for merging some of the drivers between max77693 and max77843 so the child MFD driver can be attached to any parent MFD main driver. Move the state container to common header file. Additionally add consistent 'i2c' prefixes to its members (of 'struct i2c_client' type). Signed-off-by: Krzysztof Kozlowski Acked-by: Sebastian Reichel Acked-by: Dmitry Torokhov Acked-by: Lee Jones Acked-by: Chanwoo Choi Acked-by: Jacek Anaszewski Signed-off-by: Mark Brown --- drivers/extcon/extcon-max77693.c | 3 ++- drivers/input/misc/max77693-haptic.c | 1 + drivers/leds/leds-max77693.c | 1 + drivers/mfd/max77693.c | 31 +++++++++++++------------ drivers/power/max77693_charger.c | 1 + drivers/regulator/max77693.c | 1 + include/linux/mfd/max77693-common.h | 44 ++++++++++++++++++++++++++++++++++++ include/linux/mfd/max77693-private.h | 25 -------------------- 8 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 include/linux/mfd/max77693-common.h (limited to 'drivers/input') diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 770db3a72a6a..c7bb180cfff4 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1077,7 +1078,7 @@ static int max77693_muic_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "allocate register map\n"); } else { info->max77693->regmap_muic = devm_regmap_init_i2c( - info->max77693->muic, + info->max77693->i2c_muic, &max77693_muic_regmap_config); if (IS_ERR(info->max77693->regmap_muic)) { ret = PTR_ERR(info->max77693->regmap_muic); diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 39e930c10ebb..4524499ea72f 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define MAX_MAGNITUDE_SHIFT 16 diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c index b8b0eec7b540..df348a06d8c7 100644 --- a/drivers/leds/leds-max77693.c +++ b/drivers/leds/leds-max77693.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index cb14afa97e6f..67bc53fdc389 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -193,22 +194,22 @@ static int max77693_i2c_probe(struct i2c_client *i2c, } else dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); - max77693->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); - if (!max77693->muic) { + max77693->i2c_muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); + if (!max77693->i2c_muic) { dev_err(max77693->dev, "Failed to allocate I2C device for MUIC\n"); return -ENODEV; } - i2c_set_clientdata(max77693->muic, max77693); + i2c_set_clientdata(max77693->i2c_muic, max77693); - max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); - if (!max77693->haptic) { + max77693->i2c_haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); + if (!max77693->i2c_haptic) { dev_err(max77693->dev, "Failed to allocate I2C device for Haptic\n"); ret = -ENODEV; goto err_i2c_haptic; } - i2c_set_clientdata(max77693->haptic, max77693); + i2c_set_clientdata(max77693->i2c_haptic, max77693); - max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic, + max77693->regmap_haptic = devm_regmap_init_i2c(max77693->i2c_haptic, &max77693_regmap_haptic_config); if (IS_ERR(max77693->regmap_haptic)) { ret = PTR_ERR(max77693->regmap_haptic); @@ -222,7 +223,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, * instance of MUIC device when irq of max77693 is initialized * before call max77693-muic probe() function. */ - max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, + max77693->regmap_muic = devm_regmap_init_i2c(max77693->i2c_muic, &max77693_regmap_muic_config); if (IS_ERR(max77693->regmap_muic)) { ret = PTR_ERR(max77693->regmap_muic); @@ -255,7 +256,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING, 0, &max77693_charger_irq_chip, - &max77693->irq_data_charger); + &max77693->irq_data_chg); if (ret) { dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); goto err_irq_charger; @@ -296,15 +297,15 @@ err_mfd: err_intsrc: regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic); err_irq_muic: - regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger); + regmap_del_irq_chip(max77693->irq, max77693->irq_data_chg); err_irq_charger: regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys); err_irq_topsys: regmap_del_irq_chip(max77693->irq, max77693->irq_data_led); err_regmap: - i2c_unregister_device(max77693->haptic); + i2c_unregister_device(max77693->i2c_haptic); err_i2c_haptic: - i2c_unregister_device(max77693->muic); + i2c_unregister_device(max77693->i2c_muic); return ret; } @@ -315,12 +316,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c) mfd_remove_devices(max77693->dev); regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic); - regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger); + regmap_del_irq_chip(max77693->irq, max77693->irq_data_chg); regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys); regmap_del_irq_chip(max77693->irq, max77693->irq_data_led); - i2c_unregister_device(max77693->muic); - i2c_unregister_device(max77693->haptic); + i2c_unregister_device(max77693->i2c_muic); + i2c_unregister_device(max77693->i2c_haptic); return 0; } diff --git a/drivers/power/max77693_charger.c b/drivers/power/max77693_charger.c index 754879eb59f6..060cab5ae3aa 100644 --- a/drivers/power/max77693_charger.c +++ b/drivers/power/max77693_charger.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #define MAX77693_CHARGER_NAME "max77693-charger" diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c index 236851ab575a..c6ab440a74b7 100644 --- a/drivers/regulator/max77693.c +++ b/drivers/regulator/max77693.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/mfd/max77693-common.h b/include/linux/mfd/max77693-common.h new file mode 100644 index 000000000000..7da4cc38e982 --- /dev/null +++ b/include/linux/mfd/max77693-common.h @@ -0,0 +1,44 @@ +/* + * Common data shared between Maxim 77693 and 77843 drivers + * + * Copyright (C) 2015 Samsung Electronics + * + * 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 __LINUX_MFD_MAX77693_COMMON_H +#define __LINUX_MFD_MAX77693_COMMON_H + +enum max77693_types { + TYPE_MAX77693_UNKNOWN, + TYPE_MAX77693, +}; + +/* + * Shared also with max77843. + */ +struct max77693_dev { + struct device *dev; + struct i2c_client *i2c; /* 0xCC , PMIC, Charger, Flash LED */ + struct i2c_client *i2c_muic; /* 0x4A , MUIC */ + struct i2c_client *i2c_haptic; /* MAX77693: 0x90 , Haptic */ + + enum max77693_types type; + + struct regmap *regmap; + struct regmap *regmap_muic; + struct regmap *regmap_haptic; /* Only MAX77693 */ + + struct regmap_irq_chip_data *irq_data_led; + struct regmap_irq_chip_data *irq_data_topsys; + struct regmap_irq_chip_data *irq_data_chg; /* Only MAX77693 */ + struct regmap_irq_chip_data *irq_data_muic; + + int irq; +}; + + +#endif /* __LINUX_MFD_MAX77693_COMMON_H */ diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index e3c0afff38d3..8c4143c0c651 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -529,29 +529,4 @@ enum max77693_irq_muic { MAX77693_MUIC_IRQ_NR, }; -enum max77693_types { - TYPE_MAX77693_UNKNOWN, - TYPE_MAX77693, -}; - -struct max77693_dev { - struct device *dev; - struct i2c_client *i2c; /* 0xCC , PMIC, Charger, Flash LED */ - struct i2c_client *muic; /* 0x4A , MUIC */ - struct i2c_client *haptic; /* 0x90 , Haptic */ - - enum max77693_types type; - - struct regmap *regmap; - struct regmap *regmap_muic; - struct regmap *regmap_haptic; - - struct regmap_irq_chip_data *irq_data_led; - struct regmap_irq_chip_data *irq_data_topsys; - struct regmap_irq_chip_data *irq_data_charger; - struct regmap_irq_chip_data *irq_data_muic; - - int irq; -}; - #endif /* __LINUX_MFD_MAX77693_PRIV_H */ -- cgit v1.2.3 From bc1aadc18621ccf93fb33ecbb847b422c354899d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 15 Jul 2015 21:59:51 +0900 Subject: drivers: max77843: Switch to common max77693 state container Switch to the same definition of state container as in MAX77693 drivers. This will allow usage of one regulator driver in both devices: MAX77693 and MAX77843. Signed-off-by: Krzysztof Kozlowski Acked-by: Dmitry Torokhov Acked-by: Lee Jones Acked-by: Chanwoo Choi Signed-off-by: Mark Brown --- drivers/extcon/extcon-max77843.c | 17 +++++++++-------- drivers/input/misc/max77843-haptic.c | 3 ++- drivers/mfd/max77843.c | 20 +++++++++++--------- drivers/regulator/max77843.c | 6 ++++-- include/linux/mfd/max77693-common.h | 5 +++++ include/linux/mfd/max77843-private.h | 20 -------------------- 6 files changed, 31 insertions(+), 40 deletions(-) (limited to 'drivers/input') diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index fac2f1417a79..4dfe0a6337d8 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ enum max77843_muic_status { struct max77843_muic_info { struct device *dev; - struct max77843 *max77843; + struct max77693_dev *max77843; struct extcon_dev *edev; struct mutex mutex; @@ -198,7 +199,7 @@ static const struct regmap_irq_chip max77843_muic_irq_chip = { static int max77843_muic_set_path(struct max77843_muic_info *info, u8 val, bool attached) { - struct max77843 *max77843 = info->max77843; + struct max77693_dev *max77843 = info->max77843; int ret = 0; unsigned int ctrl1, ctrl2; @@ -539,7 +540,7 @@ static void max77843_muic_irq_work(struct work_struct *work) { struct max77843_muic_info *info = container_of(work, struct max77843_muic_info, irq_work); - struct max77843 *max77843 = info->max77843; + struct max77693_dev *max77843 = info->max77843; int ret = 0; mutex_lock(&info->mutex); @@ -615,7 +616,7 @@ static void max77843_muic_detect_cable_wq(struct work_struct *work) { struct max77843_muic_info *info = container_of(to_delayed_work(work), struct max77843_muic_info, wq_detcable); - struct max77843 *max77843 = info->max77843; + struct max77693_dev *max77843 = info->max77843; int chg_type, adc, ret; bool attached; @@ -656,7 +657,7 @@ err_cable_wq: static int max77843_muic_set_debounce_time(struct max77843_muic_info *info, enum max77843_muic_adc_debounce_time time) { - struct max77843 *max77843 = info->max77843; + struct max77693_dev *max77843 = info->max77843; int ret; switch (time) { @@ -681,7 +682,7 @@ static int max77843_muic_set_debounce_time(struct max77843_muic_info *info, return 0; } -static int max77843_init_muic_regmap(struct max77843 *max77843) +static int max77843_init_muic_regmap(struct max77693_dev *max77843) { int ret; @@ -720,7 +721,7 @@ err_muic_i2c: static int max77843_muic_probe(struct platform_device *pdev) { - struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); + struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent); struct max77843_muic_info *info; unsigned int id; int i, ret; @@ -821,7 +822,7 @@ err_muic_irq: static int max77843_muic_remove(struct platform_device *pdev) { struct max77843_muic_info *info = platform_get_drvdata(pdev); - struct max77843 *max77843 = info->max77843; + struct max77693_dev *max77843 = info->max77843; cancel_work_sync(&info->irq_work); regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic); diff --git a/drivers/input/misc/max77843-haptic.c b/drivers/input/misc/max77843-haptic.c index dccbb465a055..30da81ab5a21 100644 --- a/drivers/input/misc/max77843-haptic.c +++ b/drivers/input/misc/max77843-haptic.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -243,7 +244,7 @@ static void max77843_haptic_close(struct input_dev *dev) static int max77843_haptic_probe(struct platform_device *pdev) { - struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); + struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent); struct max77843_haptic *haptic; int error; diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index a354ac677ec7..c52162ea3d0a 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,7 @@ static const struct regmap_irq_chip max77843_irq_chip = { }; /* Charger and Charger regulator use same regmap. */ -static int max77843_chg_init(struct max77843 *max77843) +static int max77843_chg_init(struct max77693_dev *max77843) { int ret; @@ -101,7 +102,7 @@ err_chg_i2c: static int max77843_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct max77843 *max77843; + struct max77693_dev *max77843; unsigned int reg_data; int ret; @@ -113,6 +114,7 @@ static int max77843_probe(struct i2c_client *i2c, max77843->dev = &i2c->dev; max77843->i2c = i2c; max77843->irq = i2c->irq; + max77843->type = id->driver_data; max77843->regmap = devm_regmap_init_i2c(i2c, &max77843_regmap_config); @@ -123,7 +125,7 @@ static int max77843_probe(struct i2c_client *i2c, ret = regmap_add_irq_chip(max77843->regmap, max77843->irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, - 0, &max77843_irq_chip, &max77843->irq_data); + 0, &max77843_irq_chip, &max77843->irq_data_topsys); if (ret) { dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n"); return ret; @@ -164,18 +166,18 @@ static int max77843_probe(struct i2c_client *i2c, return 0; err_pmic_id: - regmap_del_irq_chip(max77843->irq, max77843->irq_data); + regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys); return ret; } static int max77843_remove(struct i2c_client *i2c) { - struct max77843 *max77843 = i2c_get_clientdata(i2c); + struct max77693_dev *max77843 = i2c_get_clientdata(i2c); mfd_remove_devices(max77843->dev); - regmap_del_irq_chip(max77843->irq, max77843->irq_data); + regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys); i2c_unregister_device(max77843->i2c_chg); @@ -188,7 +190,7 @@ static const struct of_device_id max77843_dt_match[] = { }; static const struct i2c_device_id max77843_id[] = { - { "max77843", }, + { "max77843", TYPE_MAX77843, }, { }, }; MODULE_DEVICE_TABLE(i2c, max77843_id); @@ -196,7 +198,7 @@ MODULE_DEVICE_TABLE(i2c, max77843_id); static int __maybe_unused max77843_suspend(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); - struct max77843 *max77843 = i2c_get_clientdata(i2c); + struct max77693_dev *max77843 = i2c_get_clientdata(i2c); disable_irq(max77843->irq); if (device_may_wakeup(dev)) @@ -208,7 +210,7 @@ static int __maybe_unused max77843_suspend(struct device *dev) static int __maybe_unused max77843_resume(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); - struct max77843 *max77843 = i2c_get_clientdata(i2c); + struct max77693_dev *max77843 = i2c_get_clientdata(i2c); if (device_may_wakeup(dev)) disable_irq_wake(max77843->irq); diff --git a/drivers/regulator/max77843.c b/drivers/regulator/max77843.c index f4fd0d3cfa6e..9926247aae6b 100644 --- a/drivers/regulator/max77843.c +++ b/drivers/regulator/max77843.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -130,7 +131,8 @@ static const struct regulator_desc max77843_supported_regulators[] = { }, }; -static struct regmap *max77843_get_regmap(struct max77843 *max77843, int reg_id) +static struct regmap *max77843_get_regmap(struct max77693_dev *max77843, + int reg_id) { switch (reg_id) { case MAX77843_SAFEOUT1: @@ -145,7 +147,7 @@ static struct regmap *max77843_get_regmap(struct max77843 *max77843, int reg_id) static int max77843_regulator_probe(struct platform_device *pdev) { - struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); + struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = {}; int i; diff --git a/include/linux/mfd/max77693-common.h b/include/linux/mfd/max77693-common.h index 7da4cc38e982..095b121aa725 100644 --- a/include/linux/mfd/max77693-common.h +++ b/include/linux/mfd/max77693-common.h @@ -15,6 +15,9 @@ enum max77693_types { TYPE_MAX77693_UNKNOWN, TYPE_MAX77693, + TYPE_MAX77843, + + TYPE_MAX77693_NUM, }; /* @@ -25,12 +28,14 @@ struct max77693_dev { struct i2c_client *i2c; /* 0xCC , PMIC, Charger, Flash LED */ struct i2c_client *i2c_muic; /* 0x4A , MUIC */ struct i2c_client *i2c_haptic; /* MAX77693: 0x90 , Haptic */ + struct i2c_client *i2c_chg; /* MAX77843: 0xD2, Charger */ enum max77693_types type; struct regmap *regmap; struct regmap *regmap_muic; struct regmap *regmap_haptic; /* Only MAX77693 */ + struct regmap *regmap_chg; /* Only MAX77843 */ struct regmap_irq_chip_data *irq_data_led; struct regmap_irq_chip_data *irq_data_topsys; diff --git a/include/linux/mfd/max77843-private.h b/include/linux/mfd/max77843-private.h index 7178ace8379e..0121d9440340 100644 --- a/include/linux/mfd/max77843-private.h +++ b/include/linux/mfd/max77843-private.h @@ -431,24 +431,4 @@ enum max77843_irq_muic { #define MAX77843_REG_SAFEOUTCTRL_SAFEOUT2_MASK \ (0x3 << SAFEOUTCTRL_SAFEOUT2_SHIFT) -struct max77843 { - struct device *dev; - - struct i2c_client *i2c; - struct i2c_client *i2c_chg; - struct i2c_client *i2c_fuel; - struct i2c_client *i2c_muic; - - struct regmap *regmap; - struct regmap *regmap_chg; - struct regmap *regmap_fuel; - struct regmap *regmap_muic; - - struct regmap_irq_chip_data *irq_data; - struct regmap_irq_chip_data *irq_data_chg; - struct regmap_irq_chip_data *irq_data_fuel; - struct regmap_irq_chip_data *irq_data_muic; - - int irq; -}; #endif /* __MAX77843_H__ */ -- cgit v1.2.3 From 8019ff6cfc0440415fcfb6352c58c3951e6ab053 Mon Sep 17 00:00:00 2001 From: Nariman Poushin Date: Thu, 16 Jul 2015 16:36:21 +0100 Subject: regmap: Use reg_sequence for multi_reg_write / register_patch Separate the functionality using sequences of register writes from the functions that take register defaults. This change renames the arguments in order to support the extension of reg_sequence to take an optional delay to be applied after any given register in a sequence is written. This avoids adding an int to all register defaults, which could substantially increase memory usage for regmaps with large default tables. This also updates all the clients of multi_reg_write/register_patch. Signed-off-by: Nariman Poushin Signed-off-by: Mark Brown --- drivers/base/regmap/internal.h | 2 +- drivers/base/regmap/regmap.c | 22 +++++++++++----------- drivers/gpu/drm/i2c/adv7511.c | 2 +- drivers/input/misc/drv260x.c | 6 +++--- drivers/input/misc/drv2665.c | 2 +- drivers/input/misc/drv2667.c | 4 ++-- drivers/mfd/arizona-core.c | 2 +- drivers/mfd/twl6040.c | 2 +- drivers/mfd/wm5102-tables.c | 6 +++--- drivers/mfd/wm5110-tables.c | 6 +++--- drivers/mfd/wm8994-core.c | 8 ++++---- drivers/mfd/wm8997-tables.c | 2 +- include/linux/regmap.h | 17 ++++++++++++++--- sound/soc/codecs/arizona.c | 2 +- sound/soc/codecs/cs35l32.c | 2 +- sound/soc/codecs/cs42l52.c | 2 +- sound/soc/codecs/da7210.c | 4 ++-- sound/soc/codecs/rt5640.c | 2 +- sound/soc/codecs/rt5645.c | 4 ++-- sound/soc/codecs/rt5651.c | 2 +- sound/soc/codecs/rt5670.c | 2 +- sound/soc/codecs/rt5677.c | 2 +- sound/soc/codecs/tlv320aic3x.c | 2 +- sound/soc/codecs/wm2200.c | 2 +- sound/soc/codecs/wm5100.c | 2 +- sound/soc/codecs/wm8962.c | 2 +- sound/soc/codecs/wm8993.c | 2 +- 27 files changed, 62 insertions(+), 51 deletions(-) (limited to 'drivers/input') diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index b2b2849fc6d3..873ddf91c9d3 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -136,7 +136,7 @@ struct regmap { /* if set, the HW registers are known to match map->reg_defaults */ bool no_sync_defaults; - struct reg_default *patch; + struct reg_sequence *patch; int patch_regs; /* if set, converts bulk rw to single rw */ diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7111d04f2621..2cbb4502747d 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1743,7 +1743,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write); * relative. The page register has been written if that was neccessary. */ static int _regmap_raw_multi_reg_write(struct regmap *map, - const struct reg_default *regs, + const struct reg_sequence *regs, size_t num_regs) { int ret; @@ -1800,12 +1800,12 @@ static unsigned int _regmap_register_page(struct regmap *map, } static int _regmap_range_multi_paged_reg_write(struct regmap *map, - struct reg_default *regs, + struct reg_sequence *regs, size_t num_regs) { int ret; int i, n; - struct reg_default *base; + struct reg_sequence *base; unsigned int this_page = 0; /* * the set of registers are not neccessarily in order, but @@ -1843,7 +1843,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map, } static int _regmap_multi_reg_write(struct regmap *map, - const struct reg_default *regs, + const struct reg_sequence *regs, size_t num_regs) { int i; @@ -1895,8 +1895,8 @@ static int _regmap_multi_reg_write(struct regmap *map, struct regmap_range_node *range; range = _regmap_range_lookup(map, reg); if (range) { - size_t len = sizeof(struct reg_default)*num_regs; - struct reg_default *base = kmemdup(regs, len, + size_t len = sizeof(struct reg_sequence)*num_regs; + struct reg_sequence *base = kmemdup(regs, len, GFP_KERNEL); if (!base) return -ENOMEM; @@ -1929,7 +1929,7 @@ static int _regmap_multi_reg_write(struct regmap *map, * A value of zero will be returned on success, a negative errno will be * returned in error cases. */ -int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, +int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs, int num_regs) { int ret; @@ -1962,7 +1962,7 @@ EXPORT_SYMBOL_GPL(regmap_multi_reg_write); * be returned in error cases. */ int regmap_multi_reg_write_bypassed(struct regmap *map, - const struct reg_default *regs, + const struct reg_sequence *regs, int num_regs) { int ret; @@ -2552,10 +2552,10 @@ EXPORT_SYMBOL_GPL(regmap_async_complete); * The caller must ensure that this function cannot be called * concurrently with either itself or regcache_sync(). */ -int regmap_register_patch(struct regmap *map, const struct reg_default *regs, +int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs, int num_regs) { - struct reg_default *p; + struct reg_sequence *p; int ret; bool bypass; @@ -2564,7 +2564,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, return 0; p = krealloc(map->patch, - sizeof(struct reg_default) * (map->patch_regs + num_regs), + sizeof(struct reg_sequence) * (map->patch_regs + num_regs), GFP_KERNEL); if (p) { memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs)); diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index 2aaa3c88999e..00416f23b5cb 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -54,7 +54,7 @@ static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder) } /* ADI recommended values for proper operation. */ -static const struct reg_default adv7511_fixed_registers[] = { +static const struct reg_sequence adv7511_fixed_registers[] = { { 0x98, 0x03 }, { 0x9a, 0xe0 }, { 0x9c, 0x30 }, diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index e5d60ecd29a4..f5c9cf2f4073 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -313,14 +313,14 @@ static void drv260x_close(struct input_dev *input) gpiod_set_value(haptics->enable_gpio, 0); } -static const struct reg_default drv260x_lra_cal_regs[] = { +static const struct reg_sequence drv260x_lra_cal_regs[] = { { DRV260X_MODE, DRV260X_AUTO_CAL }, { DRV260X_CTRL3, DRV260X_NG_THRESH_2 }, { DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE | DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH }, }; -static const struct reg_default drv260x_lra_init_regs[] = { +static const struct reg_sequence drv260x_lra_init_regs[] = { { DRV260X_MODE, DRV260X_RT_PLAYBACK }, { DRV260X_A_TO_V_CTRL, DRV260X_AUDIO_HAPTICS_PEAK_20MS | DRV260X_AUDIO_HAPTICS_FILTER_125HZ }, @@ -337,7 +337,7 @@ static const struct reg_default drv260x_lra_init_regs[] = { { DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS }, }; -static const struct reg_default drv260x_erm_cal_regs[] = { +static const struct reg_sequence drv260x_erm_cal_regs[] = { { DRV260X_MODE, DRV260X_AUTO_CAL }, { DRV260X_A_TO_V_MIN_INPUT, DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT }, { DRV260X_A_TO_V_MAX_INPUT, DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT }, diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c index 0afaa33de07d..924456e3ca75 100644 --- a/drivers/input/misc/drv2665.c +++ b/drivers/input/misc/drv2665.c @@ -132,7 +132,7 @@ static void drv2665_close(struct input_dev *input) "Failed to enter standby mode: %d\n", error); } -static const struct reg_default drv2665_init_regs[] = { +static const struct reg_sequence drv2665_init_regs[] = { { DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT }, { DRV2665_CTRL_1, DRV2665_25_VPP_GAIN }, }; diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c index fc0fddf0896a..047136aa646f 100644 --- a/drivers/input/misc/drv2667.c +++ b/drivers/input/misc/drv2667.c @@ -262,14 +262,14 @@ static void drv2667_close(struct input_dev *input) "Failed to enter standby mode: %d\n", error); } -static const struct reg_default drv2667_init_regs[] = { +static const struct reg_sequence drv2667_init_regs[] = { { DRV2667_CTRL_2, 0 }, { DRV2667_CTRL_1, DRV2667_25_VPP_GAIN }, { DRV2667_WV_SEQ_0, 1 }, { DRV2667_WV_SEQ_1, 0 } }; -static const struct reg_default drv2667_page1_init[] = { +static const struct reg_sequence drv2667_page1_init[] = { { DRV2667_RAM_HDR_SZ, 0x05 }, { DRV2667_RAM_START_HI, 0x80 }, { DRV2667_RAM_START_LO, 0x06 }, diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index bebf58a06a6b..66d50be11960 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -392,7 +392,7 @@ err: * Register patch to some of the CODECs internal write sequences * to ensure a clean exit from the low power sleep state. */ -static const struct reg_default wm5110_sleep_patch[] = { +static const struct reg_sequence wm5110_sleep_patch[] = { { 0x337A, 0xC100 }, { 0x337B, 0x0041 }, { 0x3300, 0xA210 }, diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index c5265c1262c5..583dc33432f3 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -86,7 +86,7 @@ static const struct reg_default twl6040_defaults[] = { { 0x2E, 0x00 }, /* REG_STATUS (ro) */ }; -static struct reg_default twl6040_patch[] = { +static struct reg_sequence twl6040_patch[] = { /* * Select I2C bus access to dual access registers * Interrupt register is cleared on read diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index aeae6ec123b3..423fb3730dc7 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -21,7 +21,7 @@ #define WM5102_NUM_AOD_ISR 2 #define WM5102_NUM_ISR 5 -static const struct reg_default wm5102_reva_patch[] = { +static const struct reg_sequence wm5102_reva_patch[] = { { 0x80, 0x0003 }, { 0x221, 0x0090 }, { 0x211, 0x0014 }, @@ -57,7 +57,7 @@ static const struct reg_default wm5102_reva_patch[] = { { 0x80, 0x0000 }, }; -static const struct reg_default wm5102_revb_patch[] = { +static const struct reg_sequence wm5102_revb_patch[] = { { 0x19, 0x0001 }, { 0x80, 0x0003 }, { 0x081, 0xE022 }, @@ -80,7 +80,7 @@ static const struct reg_default wm5102_revb_patch[] = { /* We use a function so we can use ARRAY_SIZE() */ int wm5102_patch(struct arizona *arizona) { - const struct reg_default *wm5102_patch; + const struct reg_sequence *wm5102_patch; int patch_size; switch (arizona->rev) { diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 12cad94b4035..26ce14f903fe 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -21,7 +21,7 @@ #define WM5110_NUM_AOD_ISR 2 #define WM5110_NUM_ISR 5 -static const struct reg_default wm5110_reva_patch[] = { +static const struct reg_sequence wm5110_reva_patch[] = { { 0x80, 0x3 }, { 0x44, 0x20 }, { 0x45, 0x40 }, @@ -134,7 +134,7 @@ static const struct reg_default wm5110_reva_patch[] = { { 0x209, 0x002A }, }; -static const struct reg_default wm5110_revb_patch[] = { +static const struct reg_sequence wm5110_revb_patch[] = { { 0x80, 0x3 }, { 0x36e, 0x0210 }, { 0x370, 0x0210 }, @@ -224,7 +224,7 @@ static const struct reg_default wm5110_revb_patch[] = { { 0x80, 0x0 }, }; -static const struct reg_default wm5110_revd_patch[] = { +static const struct reg_sequence wm5110_revd_patch[] = { { 0x80, 0x3 }, { 0x80, 0x3 }, { 0x393, 0x27 }, diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 53ae5af5d6e4..0f4169a3a5d4 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -243,21 +243,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) } #endif -static const struct reg_default wm8994_revc_patch[] = { +static const struct reg_sequence wm8994_revc_patch[] = { { 0x102, 0x3 }, { 0x56, 0x3 }, { 0x817, 0x0 }, { 0x102, 0x0 }, }; -static const struct reg_default wm8958_reva_patch[] = { +static const struct reg_sequence wm8958_reva_patch[] = { { 0x102, 0x3 }, { 0xcb, 0x81 }, { 0x817, 0x0 }, { 0x102, 0x0 }, }; -static const struct reg_default wm1811_reva_patch[] = { +static const struct reg_sequence wm1811_reva_patch[] = { { 0x102, 0x3 }, { 0x56, 0xc07 }, { 0x5d, 0x7e }, @@ -326,7 +326,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) { struct wm8994_pdata *pdata; struct regmap_config *regmap_config; - const struct reg_default *regmap_patch = NULL; + const struct reg_sequence *regmap_patch = NULL; const char *devname; int ret, i, patch_regs = 0; int pulls = 0; diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c index c0c25d75aacc..cab2c68f1737 100644 --- a/drivers/mfd/wm8997-tables.c +++ b/drivers/mfd/wm8997-tables.c @@ -17,7 +17,7 @@ #include "arizona.h" -static const struct reg_default wm8997_reva_patch[] = { +static const struct reg_sequence wm8997_reva_patch[] = { { 0x80, 0x0003 }, { 0x214, 0x0008 }, { 0x458, 0x0000 }, diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 59c55ea0f0b5..c9ef2ec69142 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -50,6 +50,17 @@ struct reg_default { unsigned int def; }; +/** + * Register/value pairs for sequences of writes + * + * @reg: Register address. + * @def: Register value. + */ +struct reg_sequence { + unsigned int reg; + unsigned int def; +}; + #ifdef CONFIG_REGMAP enum regmap_endian { @@ -410,10 +421,10 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, const void *val, size_t val_len); int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_count); -int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, +int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs, int num_regs); int regmap_multi_reg_write_bypassed(struct regmap *map, - const struct reg_default *regs, + const struct reg_sequence *regs, int num_regs); int regmap_raw_write_async(struct regmap *map, unsigned int reg, const void *val, size_t val_len); @@ -450,7 +461,7 @@ void regcache_mark_dirty(struct regmap *map); bool regmap_check_range_table(struct regmap *map, unsigned int reg, const struct regmap_access_table *table); -int regmap_register_patch(struct regmap *map, const struct reg_default *regs, +int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs, int num_regs); int regmap_parse_val(struct regmap *map, const void *buf, unsigned int *val); diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 802e05eae3e9..5edd33fcd68c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1366,7 +1366,7 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, { struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona *arizona = priv->arizona; - struct reg_default dac_comp[] = { + struct reg_sequence dac_comp[] = { { 0x80, 0x3 }, { ARIZONA_DAC_COMP_1, 0 }, { ARIZONA_DAC_COMP_2, 0 }, diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 8f40025b7e7c..2813a1b0c949 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -276,7 +276,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { }; /* Current and threshold powerup sequence Pg37 in datasheet */ -static const struct reg_default cs35l32_monitor_patch[] = { +static const struct reg_sequence cs35l32_monitor_patch[] = { { 0x00, 0x99 }, { 0x48, 0x17 }, diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 4de52c9957ac..8b2d05933594 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1118,7 +1118,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { }; /* Current and threshold powerup sequence Pg37 */ -static const struct reg_default cs42l52_threshold_patch[] = { +static const struct reg_sequence cs42l52_threshold_patch[] = { { 0x00, 0x99 }, { 0x3E, 0xBA }, diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 21810e5f3321..bf0fb3d4df22 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1182,7 +1182,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = { #if IS_ENABLED(CONFIG_I2C) -static struct reg_default da7210_regmap_i2c_patch[] = { +static struct reg_sequence da7210_regmap_i2c_patch[] = { /* System controller master disable */ { DA7210_STARTUP1, 0x00 }, @@ -1269,7 +1269,7 @@ static struct i2c_driver da7210_i2c_driver = { #if defined(CONFIG_SPI_MASTER) -static struct reg_default da7210_regmap_spi_patch[] = { +static struct reg_sequence da7210_regmap_spi_patch[] = { /* Dummy read to give two pulses over nCS for SPI */ { DA7210_AUX2, 0x00 }, { DA7210_AUX2, 0x00 }, diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 9bc78e57513d..1ed1f8895e12 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5640_ranges[] = { .window_len = 0x1, }, }; -static const struct reg_default init_list[] = { +static const struct reg_sequence init_list[] = { {RT5640_PR_BASE + 0x3d, 0x3600}, {RT5640_PR_BASE + 0x12, 0x0aa8}, {RT5640_PR_BASE + 0x14, 0x0aaa}, diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 9ce311e088fc..c0f4be430e70 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -54,7 +54,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = { }, }; -static const struct reg_default init_list[] = { +static const struct reg_sequence init_list[] = { {RT5645_PR_BASE + 0x3d, 0x3600}, {RT5645_PR_BASE + 0x1c, 0xfd20}, {RT5645_PR_BASE + 0x20, 0x611f}, @@ -63,7 +63,7 @@ static const struct reg_default init_list[] = { }; #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) -static const struct reg_default rt5650_init_list[] = { +static const struct reg_sequence rt5650_init_list[] = { {0xf6, 0x0100}, }; diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index a3506e193abc..db9b8667f136 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -46,7 +46,7 @@ static const struct regmap_range_cfg rt5651_ranges[] = { .window_len = 0x1, }, }; -static struct reg_default init_list[] = { +static struct reg_sequence init_list[] = { {RT5651_PR_BASE + 0x3d, 0x3e00}, }; diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index a9123d414178..462a91f7cf68 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5670_ranges[] = { .window_len = 0x1, }, }; -static const struct reg_default init_list[] = { +static const struct reg_sequence init_list[] = { { RT5670_PR_BASE + 0x14, 0x9a8a }, { RT5670_PR_BASE + 0x38, 0x3ba1 }, { RT5670_PR_BASE + 0x3d, 0x3640 }, diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 31d969ac1192..b89775251470 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -54,7 +54,7 @@ static const struct regmap_range_cfg rt5677_ranges[] = { }, }; -static const struct reg_default init_list[] = { +static const struct reg_sequence init_list[] = { {RT5677_ASRC_12, 0x0018}, {RT5677_PR_BASE + 0x3d, 0x364d}, {RT5677_PR_BASE + 0x17, 0x4fc0}, diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index a7cf19b53fb2..83ae1eb44d4f 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1668,7 +1668,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); -static const struct reg_default aic3007_class_d[] = { +static const struct reg_sequence aic3007_class_d[] = { /* Class-D speaker driver init; datasheet p. 46 */ { AIC3X_PAGE_SELECT, 0x0D }, { 0xD, 0x0D }, diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index c83083285e53..6c607928fb9b 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -897,7 +897,7 @@ static bool wm2200_readable_register(struct device *dev, unsigned int reg) } } -static const struct reg_default wm2200_reva_patch[] = { +static const struct reg_sequence wm2200_reva_patch[] = { { 0x07, 0x0003 }, { 0x102, 0x0200 }, { 0x203, 0x0084 }, diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4c10cd88c1af..26d79bbb7599 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1247,7 +1247,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { { "PWM2", NULL, "PWM2 Driver" }, }; -static const struct reg_default wm5100_reva_patches[] = { +static const struct reg_sequence wm5100_reva_patches[] = { { WM5100_AUDIO_IF_1_10, 0 }, { WM5100_AUDIO_IF_1_11, 1 }, { WM5100_AUDIO_IF_1_12, 2 }, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index c5748fd4f296..05492e826aea 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3495,7 +3495,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { }; /* Improve power consumption for IN4 DC measurement mode */ -static const struct reg_default wm8962_dc_measure[] = { +static const struct reg_sequence wm8962_dc_measure[] = { { 0xfd, 0x1 }, { 0xcc, 0x40 }, { 0xfd, 0 }, diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 8a8db8605dc2..52ec64d8502d 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1595,7 +1595,7 @@ static int wm8993_resume(struct snd_soc_codec *codec) #endif /* Tune DC servo configuration */ -static struct reg_default wm8993_regmap_patch[] = { +static struct reg_sequence wm8993_regmap_patch[] = { { 0x44, 3 }, { 0x56, 3 }, { 0x44, 0 }, -- cgit v1.2.3 From def56bba7a5c623fd887d1f4b4c864521d615a76 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 15 Jul 2015 10:36:37 +0800 Subject: input: snvs_pwrkey: use "wakeup-source" as deivce tree property name Instead of inventing a new property name, let's use "wakeup-source" to be consistent with other driver and subsystem bindings. Signed-off-by: Shawn Guo Acked-by: Dmitry Torokhov --- Documentation/devicetree/bindings/crypto/fsl-sec4.txt | 2 +- drivers/input/keyboard/snvs_pwrkey.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt index 71a39c5bd486..f16bbd6644b8 100644 --- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt +++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt @@ -408,7 +408,7 @@ System ON/OFF key driver Value type: Definition: Keycode to emit, KEY_POWER by default. - - wakeup: + - wakeup-source: Usage: option Value type: Definition: Button can wake-up the system. diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index 512a1fc2a864..78fd24ca3813 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -122,7 +122,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n"); } - pdata->wakeup = of_property_read_bool(np, "wakeup"); + pdata->wakeup = of_property_read_bool(np, "wakeup-source"); pdata->irq = platform_get_irq(pdev, 0); if (pdata->irq < 0) { -- cgit v1.2.3 From 17e8351a77397e8a83727eb17e3a3e9b8ab5257a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 24 Jul 2015 08:12:54 +0200 Subject: thermal: consistently use int for temperatures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The thermal code uses int, long and unsigned long for temperatures in different places. Using an unsigned type limits the thermal framework to positive temperatures without need. Also several drivers currently will report temperatures near UINT_MAX for temperatures below 0°C. This will probably immediately shut the machine down due to overtemperature if started below 0°C. 'long' is 64bit on several architectures. This is not needed since INT_MAX °mC is above the melting point of all known materials. Consistently use a plain 'int' for temperatures throughout the thermal code and the drivers. This only changes the places in the drivers where the temperature is passed around as pointer, when drivers internally use another type this is not changed. Signed-off-by: Sascha Hauer Acked-by: Geert Uytterhoeven Reviewed-by: Jean Delvare Reviewed-by: Lukasz Majewski Reviewed-by: Darren Hart Reviewed-by: Heiko Stuebner Reviewed-by: Peter Feuerer Cc: Punit Agrawal Cc: Zhang Rui Cc: Eduardo Valentin Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Jean Delvare Cc: Peter Feuerer Cc: Heiko Stuebner Cc: Lukasz Majewski Cc: Stephen Warren Cc: Thierry Reding Cc: linux-acpi@vger.kernel.org Cc: platform-driver-x86@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-omap@vger.kernel.org Cc: linux-samsung-soc@vger.kernel.org Cc: Guenter Roeck Cc: Rafael J. Wysocki Cc: Maxime Ripard Cc: Darren Hart Cc: lm-sensors@lm-sensors.org Signed-off-by: Zhang Rui --- drivers/acpi/thermal.c | 12 +++++----- drivers/hwmon/lm75.c | 2 +- drivers/hwmon/ntc_thermistor.c | 2 +- drivers/hwmon/tmp102.c | 2 +- drivers/input/touchscreen/sun4i-ts.c | 8 +++---- drivers/platform/x86/acerhdf.c | 9 ++++---- drivers/platform/x86/intel_mid_thermal.c | 9 ++++---- drivers/power/charger-manager.c | 2 +- drivers/power/power_supply_core.c | 2 +- drivers/thermal/armada_thermal.c | 2 +- drivers/thermal/db8500_thermal.c | 7 +++--- drivers/thermal/dove_thermal.c | 2 +- drivers/thermal/fair_share.c | 2 +- drivers/thermal/gov_bang_bang.c | 5 ++-- drivers/thermal/hisi_thermal.c | 4 ++-- drivers/thermal/imx_thermal.c | 27 +++++++++++----------- drivers/thermal/int340x_thermal/int3400_thermal.c | 2 +- .../thermal/int340x_thermal/int340x_thermal_zone.c | 10 ++++---- .../thermal/int340x_thermal/int340x_thermal_zone.h | 8 +++---- .../int340x_thermal/processor_thermal_device.c | 4 ++-- drivers/thermal/intel_quark_dts_thermal.c | 13 +++++------ drivers/thermal/intel_soc_dts_iosf.c | 8 +++---- drivers/thermal/kirkwood_thermal.c | 2 +- drivers/thermal/of-thermal.c | 14 +++++------ drivers/thermal/power_allocator.c | 16 ++++++------- drivers/thermal/qcom-spmi-temp-alarm.c | 2 +- drivers/thermal/rcar_thermal.c | 7 +++--- drivers/thermal/rockchip_thermal.c | 10 ++++---- drivers/thermal/samsung/exynos_tmu.c | 23 +++++++++--------- drivers/thermal/spear_thermal.c | 2 +- drivers/thermal/st/st_thermal.c | 5 ++-- drivers/thermal/step_wise.c | 4 ++-- drivers/thermal/tegra_soctherm.c | 4 ++-- drivers/thermal/thermal_core.c | 26 ++++++++++----------- drivers/thermal/thermal_hwmon.c | 10 ++++---- drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 10 ++++---- drivers/thermal/x86_pkg_temp_thermal.c | 10 ++++---- include/linux/thermal.h | 26 +++++++++------------ include/trace/events/thermal_power_allocator.h | 6 ++--- 39 files changed, 152 insertions(+), 167 deletions(-) (limited to 'drivers/input') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 6d4e44ea74ac..e66ad25d112f 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -529,8 +529,7 @@ static void acpi_thermal_check(void *data) /* sys I/F for generic thermal sysfs support */ -static int thermal_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) +static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) { struct acpi_thermal *tz = thermal->devdata; int result; @@ -637,7 +636,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, } static int thermal_get_trip_temp(struct thermal_zone_device *thermal, - int trip, unsigned long *temp) + int trip, int *temp) { struct acpi_thermal *tz = thermal->devdata; int i; @@ -690,7 +689,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, } static int thermal_get_crit_temp(struct thermal_zone_device *thermal, - unsigned long *temperature) { + int *temperature) +{ struct acpi_thermal *tz = thermal->devdata; if (tz->trips.critical.flags.valid) { @@ -713,8 +713,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, return -EINVAL; if (type == THERMAL_TRIP_ACTIVE) { - unsigned long trip_temp; - unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( + int trip_temp; + int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( tz->temperature, tz->kelvin_offset); if (thermal_get_trip_temp(thermal, trip, &trip_temp)) return -EINVAL; diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index fe41d5ae7cb2..e4e57bbafb10 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -104,7 +104,7 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution) /* sysfs attributes for hwmon */ -static int lm75_read_temp(void *dev, long *temp) +static int lm75_read_temp(void *dev, int *temp) { struct lm75_data *data = lm75_update_device(dev); diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index dc0b76c5e302..feed30646d91 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -477,7 +477,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data) return -EINVAL; } -static int ntc_read_temp(void *dev, long *temp) +static int ntc_read_temp(void *dev, int *temp) { struct ntc_data *data = dev_get_drvdata(dev); int ohm; diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 9da2735f1424..65482624ea2c 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -98,7 +98,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev) return tmp102; } -static int tmp102_read_temp(void *dev, long *temp) +static int tmp102_read_temp(void *dev, int *temp) { struct tmp102 *tmp102 = tmp102_update_device(dev); diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index c0116994067d..485794376ee5 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -191,7 +191,7 @@ static void sun4i_ts_close(struct input_dev *dev) writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); } -static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp) +static int sun4i_get_temp(const struct sun4i_ts_data *ts, int *temp) { /* No temp_data until the first irq */ if (ts->temp_data == -1) @@ -202,7 +202,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp) return 0; } -static int sun4i_get_tz_temp(void *data, long *temp) +static int sun4i_get_tz_temp(void *data, int *temp) { return sun4i_get_temp(data, temp); } @@ -215,14 +215,14 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { struct sun4i_ts_data *ts = dev_get_drvdata(dev); - long temp; + int temp; int error; error = sun4i_get_temp(ts, &temp); if (error) return error; - return sprintf(buf, "%ld\n", temp); + return sprintf(buf, "%d\n", temp); } static ssize_t show_temp_label(struct device *dev, diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 1ef02daddb60..460fa6708bfc 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -346,8 +346,7 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal) * as late as the polling interval is since we can't do that in the respective * accessors of the module parameters. */ -static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, - unsigned long *t) +static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, int *t) { int temp, err = 0; @@ -453,7 +452,7 @@ static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip, } static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip, - unsigned long *temp) + int *temp) { if (trip != 0) return -EINVAL; @@ -464,7 +463,7 @@ static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip, } static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip, - unsigned long *temp) + int *temp) { if (trip == 0) *temp = fanon; @@ -477,7 +476,7 @@ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip, } static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, - unsigned long *temperature) + int *temperature) { *temperature = ACERHDF_TEMP_CRIT; return 0; diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c index 0944e834af8d..9f713b832ba3 100644 --- a/drivers/platform/x86/intel_mid_thermal.c +++ b/drivers/platform/x86/intel_mid_thermal.c @@ -132,7 +132,7 @@ static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max) * to achieve very close approximate temp value with less than * 0.5C error */ -static int adc_to_temp(int direct, uint16_t adc_val, unsigned long *tp) +static int adc_to_temp(int direct, uint16_t adc_val, int *tp) { int temp; @@ -174,14 +174,13 @@ static int adc_to_temp(int direct, uint16_t adc_val, unsigned long *tp) * * Can sleep */ -static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp) +static int mid_read_temp(struct thermal_zone_device *tzd, int *temp) { struct thermal_device_info *td_info = tzd->devdata; uint16_t adc_val, addr; uint8_t data = 0; int ret; - unsigned long curr_temp; - + int curr_temp; addr = td_info->chnl_addr; @@ -453,7 +452,7 @@ static SIMPLE_DEV_PM_OPS(mid_thermal_pm, * * Can sleep */ -static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp) +static int read_curr_temp(struct thermal_zone_device *tzd, int *temp) { WARN_ON(tzd == NULL); return mid_read_temp(tzd, temp); diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 1c202ccbd2a6..907293e6f2a4 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -619,7 +619,7 @@ static int cm_get_battery_temperature(struct charger_manager *cm, #ifdef CONFIG_THERMAL if (cm->tzd_batt) { - ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); + ret = thermal_zone_get_temp(cm->tzd_batt, temp); if (!ret) /* Calibrate temperature unit */ *temp /= 100; diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 869284c2e1e8..456987c88baa 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -557,7 +557,7 @@ EXPORT_SYMBOL_GPL(power_supply_unreg_notifier); #ifdef CONFIG_THERMAL static int power_supply_read_temp(struct thermal_zone_device *tzd, - unsigned long *temp) + int *temp) { struct power_supply *psy; union power_supply_propval val; diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 01255fd65135..26b8d326546a 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -155,7 +155,7 @@ static bool armada_is_valid(struct armada_thermal_priv *priv) } static int armada_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { struct armada_thermal_priv *priv = thermal->devdata; unsigned long reg; diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c index 2fb273c4baa9..652acd8fbe48 100644 --- a/drivers/thermal/db8500_thermal.c +++ b/drivers/thermal/db8500_thermal.c @@ -107,8 +107,7 @@ static int db8500_cdev_unbind(struct thermal_zone_device *thermal, } /* Callback to get current temperature */ -static int db8500_sys_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) +static int db8500_sys_get_temp(struct thermal_zone_device *thermal, int *temp) { struct db8500_thermal_zone *pzone = thermal->devdata; @@ -180,7 +179,7 @@ static int db8500_sys_get_trip_type(struct thermal_zone_device *thermal, /* Callback to get trip point temperature */ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal, - int trip, unsigned long *temp) + int trip, int *temp) { struct db8500_thermal_zone *pzone = thermal->devdata; struct db8500_thsens_platform_data *ptrips = pzone->trip_tab; @@ -195,7 +194,7 @@ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal, /* Callback to get critical trip point temperature */ static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { struct db8500_thermal_zone *pzone = thermal->devdata; struct db8500_thsens_platform_data *ptrips = pzone->trip_tab; diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 09f6e304c274..a0bc9de42553 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -93,7 +93,7 @@ static int dove_init_sensor(const struct dove_thermal_priv *priv) } static int dove_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { unsigned long reg; struct dove_thermal_priv *priv = thermal->devdata; diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c index c2c10bbe24d6..34fe36504a55 100644 --- a/drivers/thermal/fair_share.c +++ b/drivers/thermal/fair_share.c @@ -34,7 +34,7 @@ static int get_trip_level(struct thermal_zone_device *tz) { int count = 0; - unsigned long trip_temp; + int trip_temp; enum thermal_trip_type trip_type; if (tz->trips == 0 || !tz->ops->get_trip_temp) diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index c5dd76b2ee74..70836c5b89bc 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -25,14 +25,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) { - long trip_temp; - unsigned long trip_hyst; + int trip_temp, trip_hyst; struct thermal_instance *instance; tz->ops->get_trip_temp(tz, trip, &trip_temp); tz->ops->get_trip_hyst(tz, trip, &trip_hyst); - dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n", + dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", trip, trip_temp, tz->temperature, trip_hyst); diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index d5dd357ba57c..49aa068d1603 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -155,7 +155,7 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) mutex_unlock(&data->thermal_lock); } -static int hisi_thermal_get_temp(void *_sensor, long *temp) +static int hisi_thermal_get_temp(void *_sensor, int *temp) { struct hisi_thermal_sensor *sensor = _sensor; struct hisi_thermal_data *data = sensor->thermal; @@ -178,7 +178,7 @@ static int hisi_thermal_get_temp(void *_sensor, long *temp) data->irq_bind_sensor = sensor_id; mutex_unlock(&data->thermal_lock); - dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%ld, thres=%d\n", + dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%d, thres=%d\n", sensor->id, data->irq_enabled, *temp, sensor->thres_temp); /* * Bind irq to sensor for two cases: diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index fde4c2876d14..4bec1d3c3d27 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -98,10 +98,10 @@ struct imx_thermal_data { enum thermal_device_mode mode; struct regmap *tempmon; u32 c1, c2; /* See formula in imx_get_sensor_data() */ - unsigned long temp_passive; - unsigned long temp_critical; - unsigned long alarm_temp; - unsigned long last_temp; + int temp_passive; + int temp_critical; + int alarm_temp; + int last_temp; bool irq_enabled; int irq; struct clk *thermal_clk; @@ -109,7 +109,7 @@ struct imx_thermal_data { }; static void imx_set_panic_temp(struct imx_thermal_data *data, - signed long panic_temp) + int panic_temp) { struct regmap *map = data->tempmon; int critical_value; @@ -121,7 +121,7 @@ static void imx_set_panic_temp(struct imx_thermal_data *data, } static void imx_set_alarm_temp(struct imx_thermal_data *data, - signed long alarm_temp) + int alarm_temp) { struct regmap *map = data->tempmon; int alarm_value; @@ -133,7 +133,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data, TEMPSENSE0_ALARM_VALUE_SHIFT); } -static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp) +static int imx_get_temp(struct thermal_zone_device *tz, int *temp) { struct imx_thermal_data *data = tz->devdata; struct regmap *map = data->tempmon; @@ -189,13 +189,13 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp) if (data->alarm_temp == data->temp_critical && *temp < data->temp_passive) { imx_set_alarm_temp(data, data->temp_passive); - dev_dbg(&tz->device, "thermal alarm off: T < %lu\n", + dev_dbg(&tz->device, "thermal alarm off: T < %d\n", data->alarm_temp / 1000); } } if (*temp != data->last_temp) { - dev_dbg(&tz->device, "millicelsius: %ld\n", *temp); + dev_dbg(&tz->device, "millicelsius: %d\n", *temp); data->last_temp = *temp; } @@ -262,8 +262,7 @@ static int imx_get_trip_type(struct thermal_zone_device *tz, int trip, return 0; } -static int imx_get_crit_temp(struct thermal_zone_device *tz, - unsigned long *temp) +static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp) { struct imx_thermal_data *data = tz->devdata; @@ -272,7 +271,7 @@ static int imx_get_crit_temp(struct thermal_zone_device *tz, } static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip, - unsigned long *temp) + int *temp) { struct imx_thermal_data *data = tz->devdata; @@ -282,7 +281,7 @@ static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip, } static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip, - unsigned long temp) + int temp) { struct imx_thermal_data *data = tz->devdata; @@ -434,7 +433,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev) { struct imx_thermal_data *data = dev; - dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n", + dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n", data->alarm_temp / 1000); thermal_zone_device_update(data->tz); diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index 031018e7a65b..5836e5554433 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c @@ -186,7 +186,7 @@ static int int3400_thermal_run_osc(acpi_handle handle, } static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { *temp = 20 * 1000; /* faked temp sensor with 20C */ return 0; diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c index 1e25133d35e2..b9b2666aa94c 100644 --- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c +++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c @@ -20,7 +20,7 @@ #include "int340x_thermal_zone.h" static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, - unsigned long *temp) + int *temp) { struct int34x_thermal_zone *d = zone->devdata; unsigned long long tmp; @@ -49,7 +49,7 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, } static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone, - int trip, unsigned long *temp) + int trip, int *temp) { struct int34x_thermal_zone *d = zone->devdata; int i; @@ -114,7 +114,7 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone, } static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone, - int trip, unsigned long temp) + int trip, int temp) { struct int34x_thermal_zone *d = zone->devdata; acpi_status status; @@ -136,7 +136,7 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone, static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone, - int trip, unsigned long *temp) + int trip, int *temp) { struct int34x_thermal_zone *d = zone->devdata; acpi_status status; @@ -163,7 +163,7 @@ static struct thermal_zone_device_ops int340x_thermal_zone_ops = { }; static int int340x_thermal_get_trip_config(acpi_handle handle, char *name, - unsigned long *temp) + int *temp) { unsigned long long r; acpi_status status; diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h index 9f38ab72c4bf..aaadf724ff2e 100644 --- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h +++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h @@ -21,7 +21,7 @@ #define INT340X_THERMAL_MAX_ACT_TRIP_COUNT 10 struct active_trip { - unsigned long temp; + int temp; int id; bool valid; }; @@ -31,11 +31,11 @@ struct int34x_thermal_zone { struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT]; unsigned long *aux_trips; int aux_trip_nr; - unsigned long psv_temp; + int psv_temp; int psv_trip_id; - unsigned long crt_temp; + int crt_temp; int crt_trip_id; - unsigned long hot_temp; + int hot_temp; int hot_trip_id; struct thermal_zone_device *zone; struct thermal_zone_device_ops *override_ops; diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index 3df3dc34b124..ccc0ad02d066 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c @@ -145,7 +145,7 @@ static int get_tjmax(void) return -EINVAL; } -static int read_temp_msr(unsigned long *temp) +static int read_temp_msr(int *temp) { int cpu; u32 eax, edx; @@ -177,7 +177,7 @@ err_ret: } static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone, - unsigned long *temp) + int *temp) { int ret; diff --git a/drivers/thermal/intel_quark_dts_thermal.c b/drivers/thermal/intel_quark_dts_thermal.c index 4434ec812cb7..5ed90e6c8a64 100644 --- a/drivers/thermal/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel_quark_dts_thermal.c @@ -186,7 +186,7 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) return ret; } -static int _get_trip_temp(int trip, unsigned long *temp) +static int _get_trip_temp(int trip, int *temp) { int status; u32 out; @@ -212,19 +212,18 @@ static int _get_trip_temp(int trip, unsigned long *temp) } static inline int sys_get_trip_temp(struct thermal_zone_device *tzd, - int trip, unsigned long *temp) + int trip, int *temp) { return _get_trip_temp(trip, temp); } -static inline int sys_get_crit_temp(struct thermal_zone_device *tzd, - unsigned long *temp) +static inline int sys_get_crit_temp(struct thermal_zone_device *tzd, int *temp) { return _get_trip_temp(QRK_DTS_ID_TP_CRITICAL, temp); } static int update_trip_temp(struct soc_sensor_entry *aux_entry, - int trip, unsigned long temp) + int trip, int temp) { u32 out; u32 temp_out; @@ -272,7 +271,7 @@ failed: } static inline int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, - unsigned long temp) + int temp) { return update_trip_temp(tzd->devdata, trip, temp); } @@ -289,7 +288,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal, } static int sys_get_curr_temp(struct thermal_zone_device *tzd, - unsigned long *temp) + int *temp) { u32 out; int ret; diff --git a/drivers/thermal/intel_soc_dts_iosf.c b/drivers/thermal/intel_soc_dts_iosf.c index 42e4b6ac3875..5841d1d72996 100644 --- a/drivers/thermal/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel_soc_dts_iosf.c @@ -80,7 +80,7 @@ err_ret: } static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, - unsigned long *temp) + int *temp) { int status; u32 out; @@ -106,7 +106,7 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, } static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, - int thres_index, unsigned long temp, + int thres_index, int temp, enum thermal_trip_type trip_type) { int status; @@ -196,7 +196,7 @@ err_restore_ptps: } static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, - unsigned long temp) + int temp) { struct intel_soc_dts_sensor_entry *dts = tzd->devdata; struct intel_soc_dts_sensors *sensors = dts->sensors; @@ -226,7 +226,7 @@ static int sys_get_trip_type(struct thermal_zone_device *tzd, } static int sys_get_curr_temp(struct thermal_zone_device *tzd, - unsigned long *temp) + int *temp) { int status; u32 out; diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index 11041fe63dc2..892236621767 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -33,7 +33,7 @@ struct kirkwood_thermal_priv { }; static int kirkwood_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { unsigned long reg; struct kirkwood_thermal_priv *priv = thermal->devdata; diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index b295b2b6c191..42b7d4253b94 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -91,7 +91,7 @@ struct __thermal_zone { /*** DT thermal zone device callbacks ***/ static int of_thermal_get_temp(struct thermal_zone_device *tz, - unsigned long *temp) + int *temp) { struct __thermal_zone *data = tz->devdata; @@ -177,7 +177,7 @@ EXPORT_SYMBOL_GPL(of_thermal_get_trip_points); * Return: zero on success, error code otherwise */ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, - unsigned long temp) + int temp) { struct __thermal_zone *data = tz->devdata; @@ -311,7 +311,7 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, } static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, - unsigned long *temp) + int *temp) { struct __thermal_zone *data = tz->devdata; @@ -324,7 +324,7 @@ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, } static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, - unsigned long temp) + int temp) { struct __thermal_zone *data = tz->devdata; @@ -338,7 +338,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, } static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip, - unsigned long *hyst) + int *hyst) { struct __thermal_zone *data = tz->devdata; @@ -351,7 +351,7 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip, } static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip, - unsigned long hyst) + int hyst) { struct __thermal_zone *data = tz->devdata; @@ -365,7 +365,7 @@ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip, } static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, - unsigned long *temp) + int *temp) { struct __thermal_zone *data = tz->devdata; int i; diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c index 4672250b329f..045aea59ce9d 100644 --- a/drivers/thermal/power_allocator.c +++ b/drivers/thermal/power_allocator.c @@ -92,8 +92,8 @@ struct power_allocator_params { * Return: The power budget for the next period. */ static u32 pid_controller(struct thermal_zone_device *tz, - unsigned long current_temp, - unsigned long control_temp, + int current_temp, + int control_temp, u32 max_allocatable_power) { s64 p, i, d, power_range; @@ -102,7 +102,7 @@ static u32 pid_controller(struct thermal_zone_device *tz, max_power_frac = int_to_frac(max_allocatable_power); - err = ((s32)control_temp - (s32)current_temp); + err = control_temp - current_temp; err = int_to_frac(err); /* Calculate the proportional term */ @@ -223,8 +223,8 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors, } static int allocate_power(struct thermal_zone_device *tz, - unsigned long current_temp, - unsigned long control_temp) + int current_temp, + int control_temp) { struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; @@ -326,7 +326,7 @@ static int allocate_power(struct thermal_zone_device *tz, granted_power, total_granted_power, num_actors, power_range, max_allocatable_power, current_temp, - (s32)control_temp - (s32)current_temp); + control_temp - current_temp); devm_kfree(&tz->device, req_power); unlock: @@ -411,7 +411,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz) { int ret; struct power_allocator_params *params; - unsigned long switch_on_temp, control_temp; + int switch_on_temp, control_temp; u32 temperature_threshold; if (!tz->tzp || !tz->tzp->sustainable_power) { @@ -476,7 +476,7 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) { int ret; - unsigned long switch_on_temp, control_temp, current_temp; + int switch_on_temp, control_temp, current_temp; struct power_allocator_params *params = tz->governor_data; /* diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c index c8d27b8fb9ec..b677aada5b52 100644 --- a/drivers/thermal/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom-spmi-temp-alarm.c @@ -117,7 +117,7 @@ static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip) return 0; } -static int qpnp_tm_get_temp(void *data, long *temp) +static int qpnp_tm_get_temp(void *data, int *temp) { struct qpnp_tm_chip *chip = data; int ret, mili_celsius; diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index fe4e767018c4..5d4ae7d705e0 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -200,8 +200,7 @@ err_out_unlock: return ret; } -static int rcar_thermal_get_temp(struct thermal_zone_device *zone, - unsigned long *temp) +static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) { struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); @@ -235,7 +234,7 @@ static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone, } static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone, - int trip, unsigned long *temp) + int trip, int *temp) { struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); struct device *dev = rcar_priv_to_dev(priv); @@ -299,7 +298,7 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable) static void rcar_thermal_work(struct work_struct *work) { struct rcar_thermal_priv *priv; - unsigned long cctemp, nctemp; + int cctemp, nctemp; priv = container_of(work, struct rcar_thermal_priv, work.work); diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index cd8f5f93b42c..c89ffb26a354 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -64,7 +64,7 @@ struct rockchip_tsadc_chip { void (*control)(void __iomem *reg, bool on); /* Per-sensor methods */ - int (*get_temp)(int chn, void __iomem *reg, long *temp); + int (*get_temp)(int chn, void __iomem *reg, int *temp); void (*set_tshut_temp)(int chn, void __iomem *reg, long temp); void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); }; @@ -191,7 +191,7 @@ static u32 rk_tsadcv2_temp_to_code(long temp) return 0; } -static long rk_tsadcv2_code_to_temp(u32 code) +static int rk_tsadcv2_code_to_temp(u32 code) { unsigned int low = 0; unsigned int high = ARRAY_SIZE(v2_code_table) - 1; @@ -277,7 +277,7 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable) writel_relaxed(val, regs + TSADCV2_AUTO_CON); } -static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, long *temp) +static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, int *temp) { u32 val; @@ -366,7 +366,7 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev) return IRQ_HANDLED; } -static int rockchip_thermal_get_temp(void *_sensor, long *out_temp) +static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) { struct rockchip_thermal_sensor *sensor = _sensor; struct rockchip_thermal_data *thermal = sensor->thermal; @@ -374,7 +374,7 @@ static int rockchip_thermal_get_temp(void *_sensor, long *out_temp) int retval; retval = tsadc->get_temp(sensor->id, thermal->regs, out_temp); - dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %ld, retval: %d\n", + dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n", sensor->id, *out_temp, retval); return retval; diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 531f4b179871..9ec29a33aeea 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -207,8 +207,7 @@ struct exynos_tmu_data { int (*tmu_initialize)(struct platform_device *pdev); void (*tmu_control)(struct platform_device *pdev, bool on); int (*tmu_read)(struct exynos_tmu_data *data); - void (*tmu_set_emulation)(struct exynos_tmu_data *data, - unsigned long temp); + void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp); void (*tmu_clear_irqs)(struct exynos_tmu_data *data); }; @@ -216,7 +215,7 @@ static void exynos_report_trigger(struct exynos_tmu_data *p) { char data[10], *envp[] = { data, NULL }; struct thermal_zone_device *tz = p->tzd; - unsigned long temp; + int temp; unsigned int i; if (!tz) { @@ -517,7 +516,7 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) struct thermal_zone_device *tz = data->tzd; unsigned int status, trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; - unsigned long temp, temp_hist; + int temp, temp_hist; int ret = 0, threshold_code, i, sensor_id, cal_type; status = readb(data->base + EXYNOS_TMU_REG_STATUS); @@ -610,7 +609,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev) struct exynos_tmu_data *data = platform_get_drvdata(pdev); unsigned int trim_info = 0, con, rising_threshold; int ret = 0, threshold_code; - unsigned long crit_temp = 0; + int crit_temp = 0; /* * For exynos5440 soc triminfo value is swapped between TMU0 and @@ -663,7 +662,7 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) unsigned int status, trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; int ret = 0, threshold_code, i; - unsigned long temp, temp_hist; + int temp, temp_hist; unsigned int reg_off, bit_off; status = readb(data->base + EXYNOS_TMU_REG_STATUS); @@ -876,7 +875,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on) writel(con, data->base + EXYNOS_TMU_REG_CONTROL); } -static int exynos_get_temp(void *p, long *temp) +static int exynos_get_temp(void *p, int *temp) { struct exynos_tmu_data *data = p; @@ -896,7 +895,7 @@ static int exynos_get_temp(void *p, long *temp) #ifdef CONFIG_THERMAL_EMULATION static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val, - unsigned long temp) + int temp) { if (temp) { temp /= MCELSIUS; @@ -926,7 +925,7 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val, } static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, - unsigned long temp) + int temp) { unsigned int val; u32 emul_con; @@ -946,7 +945,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, } static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data, - unsigned long temp) + int temp) { unsigned int val; @@ -955,7 +954,7 @@ static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data, writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG); } -static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp) +static int exynos_tmu_set_emulation(void *drv_data, int temp) { struct exynos_tmu_data *data = drv_data; int ret = -EINVAL; @@ -978,7 +977,7 @@ out: #else #define exynos4412_tmu_set_emulation NULL #define exynos5440_tmu_set_emulation NULL -static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp) +static int exynos_tmu_set_emulation(void *drv_data, int temp) { return -EINVAL; } #endif /* CONFIG_THERMAL_EMULATION */ diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index bddb71744a6c..534dd9136662 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -38,7 +38,7 @@ struct spear_thermal_dev { }; static inline int thermal_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { struct spear_thermal_dev *stdev = thermal->devdata; diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c index 76c515dd802b..44cbba99716a 100644 --- a/drivers/thermal/st/st_thermal.c +++ b/drivers/thermal/st/st_thermal.c @@ -111,8 +111,7 @@ static int st_thermal_calibration(struct st_thermal_sensor *sensor) } /* Callback to get temperature from HW*/ -static int st_thermal_get_temp(struct thermal_zone_device *th, - unsigned long *temperature) +static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature) { struct st_thermal_sensor *sensor = th->devdata; struct device *dev = sensor->dev; @@ -159,7 +158,7 @@ static int st_thermal_get_trip_type(struct thermal_zone_device *th, } static int st_thermal_get_trip_temp(struct thermal_zone_device *th, - int trip, unsigned long *temp) + int trip, int *temp) { struct st_thermal_sensor *sensor = th->devdata; struct device *dev = sensor->dev; diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index 5a0f12d08e8b..2f9f7086ac3d 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c @@ -113,7 +113,7 @@ static void update_passive_instance(struct thermal_zone_device *tz, static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) { - long trip_temp; + int trip_temp; enum thermal_trip_type trip_type; enum thermal_trend trend; struct thermal_instance *instance; @@ -135,7 +135,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) trace_thermal_zone_trip(tz, trip, trip_type); } - dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n", + dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip, trip_type, trip_temp, trend, throttle); mutex_lock(&tz->lock); diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c index 9197fc05c5cc..74ea5765938b 100644 --- a/drivers/thermal/tegra_soctherm.c +++ b/drivers/thermal/tegra_soctherm.c @@ -293,7 +293,7 @@ static int enable_tsensor(struct tegra_soctherm *tegra, * H denotes an addition of 0.5 Celsius and N denotes negation * of the final value. */ -static long translate_temp(u16 val) +static int translate_temp(u16 val) { long t; @@ -306,7 +306,7 @@ static long translate_temp(u16 val) return t; } -static int tegra_thermctl_get_temp(void *data, long *out_temp) +static int tegra_thermctl_get_temp(void *data, int *out_temp) { struct tegra_thermctl_zone *zone = data; u32 val; diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index c4700950e42e..387c4287fc74 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -426,7 +426,7 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz, static void handle_critical_trips(struct thermal_zone_device *tz, int trip, enum thermal_trip_type trip_type) { - long trip_temp; + int trip_temp; tz->ops->get_trip_temp(tz, trip, &trip_temp); @@ -474,12 +474,12 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) * * Return: On success returns 0, an error code otherwise */ -int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp) +int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) { int ret = -EINVAL; #ifdef CONFIG_THERMAL_EMULATION int count; - unsigned long crit_temp = -1UL; + int crit_temp = INT_MAX; enum thermal_trip_type type; #endif @@ -516,8 +516,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp); static void update_temperature(struct thermal_zone_device *tz) { - long temp; - int ret; + int temp, ret; ret = thermal_zone_get_temp(tz, &temp); if (ret) { @@ -577,15 +576,14 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); - long temperature; - int ret; + int temperature, ret; ret = thermal_zone_get_temp(tz, &temperature); if (ret) return ret; - return sprintf(buf, "%ld\n", temperature); + return sprintf(buf, "%d\n", temperature); } static ssize_t @@ -689,7 +687,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, { struct thermal_zone_device *tz = to_thermal_zone(dev); int trip, ret; - long temperature; + int temperature; if (!tz->ops->get_trip_temp) return -EPERM; @@ -702,7 +700,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, if (ret) return ret; - return sprintf(buf, "%ld\n", temperature); + return sprintf(buf, "%d\n", temperature); } static ssize_t @@ -711,7 +709,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, { struct thermal_zone_device *tz = to_thermal_zone(dev); int trip, ret; - unsigned long temperature; + int temperature; if (!tz->ops->set_trip_hyst) return -EPERM; @@ -719,7 +717,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip)) return -EINVAL; - if (kstrtoul(buf, 10, &temperature)) + if (kstrtoint(buf, 10, &temperature)) return -EINVAL; /* @@ -738,7 +736,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr, { struct thermal_zone_device *tz = to_thermal_zone(dev); int trip, ret; - unsigned long temperature; + int temperature; if (!tz->ops->get_trip_hyst) return -EPERM; @@ -748,7 +746,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr, ret = tz->ops->get_trip_hyst(tz, trip, &temperature); - return ret ? ret : sprintf(buf, "%ld\n", temperature); + return ret ? ret : sprintf(buf, "%d\n", temperature); } static ssize_t diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index 1967bee4f076..06fd2ed9ef9d 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -69,7 +69,7 @@ static DEVICE_ATTR(name, 0444, name_show, NULL); static ssize_t temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) { - long temperature; + int temperature; int ret; struct thermal_hwmon_attr *hwmon_attr = container_of(attr, struct thermal_hwmon_attr, attr); @@ -83,7 +83,7 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) if (ret) return ret; - return sprintf(buf, "%ld\n", temperature); + return sprintf(buf, "%d\n", temperature); } static ssize_t @@ -95,14 +95,14 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf) = container_of(hwmon_attr, struct thermal_hwmon_temp, temp_crit); struct thermal_zone_device *tz = temp->tz; - long temperature; + int temperature; int ret; ret = tz->ops->get_trip_temp(tz, 0, &temperature); if (ret) return ret; - return sprintf(buf, "%ld\n", temperature); + return sprintf(buf, "%d\n", temperature); } @@ -142,7 +142,7 @@ thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon, static bool thermal_zone_crit_temp_valid(struct thermal_zone_device *tz) { - unsigned long temp; + int temp; return tz->ops->get_crit_temp && !tz->ops->get_crit_temp(tz, &temp); } diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index c7c5b3779dac..b213a1222295 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -76,14 +76,14 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c) /* thermal zone ops */ /* Get temperature callback function for thermal zone */ -static inline int __ti_thermal_get_temp(void *devdata, long *temp) +static inline int __ti_thermal_get_temp(void *devdata, int *temp) { struct thermal_zone_device *pcb_tz = NULL; struct ti_thermal_data *data = devdata; struct ti_bandgap *bgp; const struct ti_temp_sensor *s; int ret, tmp, slope, constant; - unsigned long pcb_temp; + int pcb_temp; if (!data) return 0; @@ -119,7 +119,7 @@ static inline int __ti_thermal_get_temp(void *devdata, long *temp) } static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { struct ti_thermal_data *data = thermal->devdata; @@ -229,7 +229,7 @@ static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal, /* Get trip temperature callback functions for thermal zone */ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal, - int trip, unsigned long *temp) + int trip, int *temp) { if (!ti_thermal_is_valid_trip(trip)) return -EINVAL; @@ -280,7 +280,7 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal, /* Get critical temperature callback functions for thermal zone */ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal, - unsigned long *temp) + int *temp) { /* shutdown zone */ return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp); diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index 50d1d2cb091a..7fc919f7da4d 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -164,7 +164,7 @@ err_ret: return err; } -static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp) +static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) { u32 eax, edx; struct phy_dev_entry *phy_dev_entry; @@ -175,7 +175,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem if (eax & 0x80000000) { *temp = phy_dev_entry->tj_max - ((eax >> 16) & 0x7f) * 1000; - pr_debug("sys_get_curr_temp %ld\n", *temp); + pr_debug("sys_get_curr_temp %d\n", *temp); return 0; } @@ -183,7 +183,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem } static int sys_get_trip_temp(struct thermal_zone_device *tzd, - int trip, unsigned long *temp) + int trip, int *temp) { u32 eax, edx; struct phy_dev_entry *phy_dev_entry; @@ -214,13 +214,13 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd, *temp = phy_dev_entry->tj_max - thres_reg_value * 1000; else *temp = 0; - pr_debug("sys_get_trip_temp %ld\n", *temp); + pr_debug("sys_get_trip_temp %d\n", *temp); return 0; } static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, - unsigned long temp) + int temp) { u32 l, h; struct phy_dev_entry *phy_dev_entry; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 037e9df2f610..17292fee8686 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -92,23 +92,19 @@ struct thermal_zone_device_ops { struct thermal_cooling_device *); int (*unbind) (struct thermal_zone_device *, struct thermal_cooling_device *); - int (*get_temp) (struct thermal_zone_device *, unsigned long *); + int (*get_temp) (struct thermal_zone_device *, int *); int (*get_mode) (struct thermal_zone_device *, enum thermal_device_mode *); int (*set_mode) (struct thermal_zone_device *, enum thermal_device_mode); int (*get_trip_type) (struct thermal_zone_device *, int, enum thermal_trip_type *); - int (*get_trip_temp) (struct thermal_zone_device *, int, - unsigned long *); - int (*set_trip_temp) (struct thermal_zone_device *, int, - unsigned long); - int (*get_trip_hyst) (struct thermal_zone_device *, int, - unsigned long *); - int (*set_trip_hyst) (struct thermal_zone_device *, int, - unsigned long); - int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); - int (*set_emul_temp) (struct thermal_zone_device *, unsigned long); + int (*get_trip_temp) (struct thermal_zone_device *, int, int *); + int (*set_trip_temp) (struct thermal_zone_device *, int, int); + int (*get_trip_hyst) (struct thermal_zone_device *, int, int *); + int (*set_trip_hyst) (struct thermal_zone_device *, int, int); + int (*get_crit_temp) (struct thermal_zone_device *, int *); + int (*set_emul_temp) (struct thermal_zone_device *, int); int (*get_trend) (struct thermal_zone_device *, int, enum thermal_trend *); int (*notify) (struct thermal_zone_device *, int, @@ -332,9 +328,9 @@ struct thermal_genl_event { * temperature. */ struct thermal_zone_of_device_ops { - int (*get_temp)(void *, long *); + int (*get_temp)(void *, int *); int (*get_trend)(void *, long *); - int (*set_emul_temp)(void *, unsigned long); + int (*set_emul_temp)(void *, int); }; /** @@ -406,7 +402,7 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *, const struct thermal_cooling_device_ops *); void thermal_cooling_device_unregister(struct thermal_cooling_device *); struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name); -int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp); +int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); int get_tz_trend(struct thermal_zone_device *, int); struct thermal_instance *get_thermal_instance(struct thermal_zone_device *, @@ -457,7 +453,7 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name( const char *name) { return ERR_PTR(-ENODEV); } static inline int thermal_zone_get_temp( - struct thermal_zone_device *tz, unsigned long *temp) + struct thermal_zone_device *tz, int *temp) { return -ENODEV; } static inline int get_tz_trend(struct thermal_zone_device *tz, int trip) { return -ENODEV; } diff --git a/include/trace/events/thermal_power_allocator.h b/include/trace/events/thermal_power_allocator.h index 12e1321c4e0c..5afae8fe3795 100644 --- a/include/trace/events/thermal_power_allocator.h +++ b/include/trace/events/thermal_power_allocator.h @@ -11,7 +11,7 @@ TRACE_EVENT(thermal_power_allocator, u32 total_req_power, u32 *granted_power, u32 total_granted_power, size_t num_actors, u32 power_range, u32 max_allocatable_power, - unsigned long current_temp, s32 delta_temp), + int current_temp, s32 delta_temp), TP_ARGS(tz, req_power, total_req_power, granted_power, total_granted_power, num_actors, power_range, max_allocatable_power, current_temp, delta_temp), @@ -24,7 +24,7 @@ TRACE_EVENT(thermal_power_allocator, __field(size_t, num_actors ) __field(u32, power_range ) __field(u32, max_allocatable_power ) - __field(unsigned long, current_temp ) + __field(int, current_temp ) __field(s32, delta_temp ) ), TP_fast_assign( @@ -42,7 +42,7 @@ TRACE_EVENT(thermal_power_allocator, __entry->delta_temp = delta_temp; ), - TP_printk("thermal_zone_id=%d req_power={%s} total_req_power=%u granted_power={%s} total_granted_power=%u power_range=%u max_allocatable_power=%u current_temperature=%lu delta_temperature=%d", + TP_printk("thermal_zone_id=%d req_power={%s} total_req_power=%u granted_power={%s} total_granted_power=%u power_range=%u max_allocatable_power=%u current_temperature=%d delta_temperature=%d", __entry->tz_id, __print_array(__get_dynamic_array(req_power), __entry->num_actors, 4), -- cgit v1.2.3 From 971bd8fa369a37b047c26e9a47d4c1f5d2dce4d3 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 20 May 2015 23:54:02 +0900 Subject: treewide: Fix typo in printk This patch fix spelling typo inv various part of sources. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina --- arch/powerpc/sysdev/fsl_pci.c | 2 +- drivers/crypto/img-hash.c | 2 +- drivers/input/touchscreen/ili210x.c | 4 ++-- drivers/isdn/mISDN/dsp_cmx.c | 2 +- drivers/mailbox/arm_mhu.c | 2 +- drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 2 +- drivers/regulator/max77843.c | 2 +- drivers/usb/dwc2/core.c | 2 +- fs/ecryptfs/mmap.c | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/input') diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 9a8fcf0d79d7..ebc1f412cf49 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1113,7 +1113,7 @@ static int fsl_pci_pme_probe(struct pci_controller *hose) IRQF_SHARED, "[PCI] PME", hose); if (res < 0) { - dev_err(&dev->dev, "Unable to requiest irq %d for PME\n", pme_irq); + dev_err(&dev->dev, "Unable to request irq %d for PME\n", pme_irq); irq_dispose_mapping(pme_irq); return -ENODEV; diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c index ad47d0d61098..68e8aa90fe01 100644 --- a/drivers/crypto/img-hash.c +++ b/drivers/crypto/img-hash.c @@ -334,7 +334,7 @@ static int img_hash_dma_init(struct img_hash_dev *hdev) hdev->dma_lch = dma_request_slave_channel(hdev->dev, "tx"); if (!hdev->dma_lch) { - dev_err(hdev->dev, "Couldn't aquire a slave DMA channel.\n"); + dev_err(hdev->dev, "Couldn't acquire a slave DMA channel.\n"); return -EBUSY; } dma_conf.direction = DMA_MEM_TO_DEV; diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index da6dc819c846..586bee407d9a 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -216,7 +216,7 @@ static int ili210x_i2c_probe(struct i2c_client *client, /* get panel info */ error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel)); if (error) { - dev_err(dev, "Failed to get panel informations, err: %d\n", + dev_err(dev, "Failed to get panel information, err: %d\n", error); return error; } @@ -276,7 +276,7 @@ static int ili210x_i2c_probe(struct i2c_client *client, error = input_register_device(priv->input); if (error) { - dev_err(dev, "Cannot regiser input device, err: %d\n", error); + dev_err(dev, "Cannot register input device, err: %d\n", error); goto err_remove_sysfs; } diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 52c43821f746..8e3aa002767b 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c @@ -506,7 +506,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) __func__, conf->id); if (list_empty(&conf->mlist)) { - printk(KERN_ERR "%s: conference whithout members\n", + printk(KERN_ERR "%s: conference without members\n", __func__); return; } diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c index d9e99f981aa9..d0d0b0305345 100644 --- a/drivers/mailbox/arm_mhu.c +++ b/drivers/mailbox/arm_mhu.c @@ -96,7 +96,7 @@ static int mhu_startup(struct mbox_chan *chan) IRQF_SHARED, "mhu_link", chan); if (ret) { dev_err(chan->mbox->dev, - "Unable to aquire IRQ %d\n", mlink->irq); + "Unable to acquire IRQ %d\n", mlink->irq); return ret; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 12497f5ed8e9..906c83c7e8e7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -1734,7 +1734,7 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) mfc_debug(1, "New context: %d\n", new_ctx); ctx = dev->ctx[new_ctx]; - mfc_debug(1, "Seting new context to %p\n", ctx); + mfc_debug(1, "Setting new context to %p\n", ctx); /* Got context to run in ctx */ mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n", ctx->dst_queue_cnt, ctx->pb_count, ctx->src_queue_cnt); diff --git a/drivers/regulator/max77843.c b/drivers/regulator/max77843.c index f4fd0d3cfa6e..3941fdb27ee2 100644 --- a/drivers/regulator/max77843.c +++ b/drivers/regulator/max77843.c @@ -162,7 +162,7 @@ static int max77843_regulator_probe(struct platform_device *pdev) &max77843_supported_regulators[i], &config); if (IS_ERR(regulator)) { dev_err(&pdev->dev, - "Failed to regiser regulator-%d\n", i); + "Failed to register regulator-%d\n", i); return PTR_ERR(regulator); } } diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index c3cc1a78d1e2..b00fe9539184 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -3175,7 +3175,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hw->hs_phy_type); dev_dbg(hsotg->dev, " fs_phy_type=%d\n", hw->fs_phy_type); - dev_dbg(hsotg->dev, " utmi_phy_data_wdith=%d\n", + dev_dbg(hsotg->dev, " utmi_phy_data_width=%d\n", hw->utmi_phy_data_width); dev_dbg(hsotg->dev, " num_dev_ep=%d\n", hw->num_dev_ep); diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index cf208522998e..caba848ac763 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -299,7 +299,7 @@ static int ecryptfs_write_begin(struct file *file, rc = ecryptfs_read_lower_page_segment( page, index, 0, PAGE_CACHE_SIZE, mapping->host); if (rc) { - printk(KERN_ERR "%s: Error attemping to read " + printk(KERN_ERR "%s: Error attempting to read " "lower page segment; rc = [%d]\n", __func__, rc); ClearPageUptodate(page); -- cgit v1.2.3 From b3d8ba746b5109dc890e7480db5d014d19ae6a05 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Jul 2015 10:36:41 +0900 Subject: Input: max77693: Remove a read-only pwm_divisor field Storing a predefined PWM divisor in state container structure is meaningless. The field, after initialization, is only read so this only obfuscates the code. Remove the field and use directly enum value. Signed-off-by: Krzysztof Kozlowski Acked-by: Dmitry Torokhov Signed-off-by: Mark Brown --- drivers/input/misc/max77693-haptic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 4524499ea72f..8dc43c1ebf0e 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c @@ -60,7 +60,6 @@ struct max77693_haptic { unsigned int pwm_duty; enum max77693_haptic_motor_type type; enum max77693_haptic_pulse_mode mode; - enum max77693_haptic_pwm_divisor pwm_divisor; struct work_struct work; }; @@ -88,7 +87,7 @@ static int max77693_haptic_configure(struct max77693_haptic *haptic, value = ((haptic->type << MAX77693_CONFIG2_MODE) | (enable << MAX77693_CONFIG2_MEN) | (haptic->mode << MAX77693_CONFIG2_HTYP) | - (haptic->pwm_divisor)); + MAX77693_HAPTIC_PWM_DIVISOR_128); error = regmap_write(haptic->regmap_haptic, MAX77693_HAPTIC_REG_CONFIG2, value); @@ -259,7 +258,6 @@ static int max77693_haptic_probe(struct platform_device *pdev) haptic->dev = &pdev->dev; haptic->type = MAX77693_HAPTIC_LRA; haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE; - haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128; haptic->suspend_state = false; INIT_WORK(&haptic->work, max77693_haptic_play_work); -- cgit v1.2.3 From 6eaa247a5bab775e45a74b52c17bf8bc37fd5f6f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Jul 2015 10:36:42 +0900 Subject: Input: max77693: Prepare for adding support for Maxim 77843 Prepare the driver for supporting two devices: Maxim 77693 and 77843: 1. Add table of device ids and store current device type for later usage. 2. Differentiate the haptic device configuration. Signed-off-by: Krzysztof Kozlowski Acked-by: Dmitry Torokhov Signed-off-by: Mark Brown --- drivers/input/misc/max77693-haptic.c | 41 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 8dc43c1ebf0e..4c0f67ab66d9 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c @@ -47,6 +47,8 @@ enum max77693_haptic_pwm_divisor { }; struct max77693_haptic { + enum max77693_types dev_type; + struct regmap *regmap_pmic; struct regmap *regmap_haptic; struct device *dev; @@ -81,16 +83,23 @@ static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic) static int max77693_haptic_configure(struct max77693_haptic *haptic, bool enable) { - unsigned int value; + unsigned int value, config_reg; int error; - value = ((haptic->type << MAX77693_CONFIG2_MODE) | - (enable << MAX77693_CONFIG2_MEN) | - (haptic->mode << MAX77693_CONFIG2_HTYP) | - MAX77693_HAPTIC_PWM_DIVISOR_128); + switch (haptic->dev_type) { + case TYPE_MAX77693: + value = ((haptic->type << MAX77693_CONFIG2_MODE) | + (enable << MAX77693_CONFIG2_MEN) | + (haptic->mode << MAX77693_CONFIG2_HTYP) | + MAX77693_HAPTIC_PWM_DIVISOR_128); + config_reg = MAX77693_HAPTIC_REG_CONFIG2; + break; + default: + return -EINVAL; + } error = regmap_write(haptic->regmap_haptic, - MAX77693_HAPTIC_REG_CONFIG2, value); + config_reg, value); if (error) { dev_err(haptic->dev, "failed to update haptic config: %d\n", error); @@ -254,12 +263,23 @@ static int max77693_haptic_probe(struct platform_device *pdev) return -ENOMEM; haptic->regmap_pmic = max77693->regmap; - haptic->regmap_haptic = max77693->regmap_haptic; haptic->dev = &pdev->dev; haptic->type = MAX77693_HAPTIC_LRA; haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE; haptic->suspend_state = false; + /* Variant-specific init */ + haptic->dev_type = platform_get_device_id(pdev)->driver_data; + switch (haptic->dev_type) { + case TYPE_MAX77693: + haptic->regmap_haptic = max77693->regmap_haptic; + break; + default: + dev_err(&pdev->dev, "unsupported device type: %u\n", + haptic->dev_type); + return -EINVAL; + } + INIT_WORK(&haptic->work, max77693_haptic_play_work); /* Get pwm and regulatot for haptic device */ @@ -337,12 +357,19 @@ static int __maybe_unused max77693_haptic_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops, max77693_haptic_suspend, max77693_haptic_resume); +static const struct platform_device_id max77693_haptic_id[] = { + { "max77693-haptic", TYPE_MAX77693 }, + {}, +}; +MODULE_DEVICE_TABLE(platform, max77693_haptic_id); + static struct platform_driver max77693_haptic_driver = { .driver = { .name = "max77693-haptic", .pm = &max77693_haptic_pm_ops, }, .probe = max77693_haptic_probe, + .id_table = max77693_haptic_id, }; module_platform_driver(max77693_haptic_driver); -- cgit v1.2.3 From 56bbc99e6914eb183fb083f737178a1757083d41 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Jul 2015 10:36:43 +0900 Subject: Input: max77693: Add support for Maxim 77843 The Maxim 77843 haptic driver differs from 77693 by: 1. Setting the bias. 2. Different configuration register. 3. Not enabling the low-sys DAC. 4. Using same regmap for PMIC and haptic blocks. Incorporate all differences into max77693 haptic driver so both devices can be supported. Signed-off-by: Krzysztof Kozlowski Acked-by: Dmitry Torokhov Signed-off-by: Mark Brown --- drivers/input/misc/Kconfig | 6 ++--- drivers/input/misc/max77693-haptic.c | 48 +++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index d4f0a817e858..f5d7a98a329d 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -167,12 +167,12 @@ config INPUT_M68K_BEEP depends on M68K config INPUT_MAX77693_HAPTIC - tristate "MAXIM MAX77693 haptic controller support" - depends on MFD_MAX77693 && PWM + tristate "MAXIM MAX77693/MAX77843 haptic controller support" + depends on (MFD_MAX77693 || MFD_MAX77843) && PWM select INPUT_FF_MEMLESS help This option enables support for the haptic controller on - MAXIM MAX77693 chip. + MAXIM MAX77693 and MAX77843 chips. To compile this driver as module, choose M here: the module will be called max77693-haptic. diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 4c0f67ab66d9..6d96bff32a0e 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c @@ -1,8 +1,9 @@ /* - * MAXIM MAX77693 Haptic device driver + * MAXIM MAX77693/MAX77843 Haptic device driver * - * Copyright (C) 2014 Samsung Electronics + * Copyright (C) 2014,2015 Samsung Electronics * Jaewon Kim + * Krzysztof Kozlowski * * This program is not provided / owned by Maxim Integrated Products. * @@ -26,6 +27,7 @@ #include #include #include +#include #define MAX_MAGNITUDE_SHIFT 16 @@ -80,6 +82,26 @@ static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic) return 0; } +static int max77843_haptic_bias(struct max77693_haptic *haptic, bool on) +{ + int error; + + if (haptic->dev_type != TYPE_MAX77843) + return 0; + + error = regmap_update_bits(haptic->regmap_haptic, + MAX77843_SYS_REG_MAINCTRL1, + MAX77843_MAINCTRL1_BIASEN_MASK, + on << MAINCTRL1_BIASEN_SHIFT); + if (error) { + dev_err(haptic->dev, "failed to %s bias: %d\n", + on ? "enable" : "disable", error); + return error; + } + + return 0; +} + static int max77693_haptic_configure(struct max77693_haptic *haptic, bool enable) { @@ -94,6 +116,12 @@ static int max77693_haptic_configure(struct max77693_haptic *haptic, MAX77693_HAPTIC_PWM_DIVISOR_128); config_reg = MAX77693_HAPTIC_REG_CONFIG2; break; + case TYPE_MAX77843: + value = (haptic->type << MCONFIG_MODE_SHIFT) | + (enable << MCONFIG_MEN_SHIFT) | + MAX77693_HAPTIC_PWM_DIVISOR_128; + config_reg = MAX77843_HAP_REG_MCONFIG; + break; default: return -EINVAL; } @@ -113,6 +141,9 @@ static int max77693_haptic_lowsys(struct max77693_haptic *haptic, bool enable) { int error; + if (haptic->dev_type != TYPE_MAX77693) + return 0; + error = regmap_update_bits(haptic->regmap_pmic, MAX77693_PMIC_REG_LSCNFG, MAX77693_PMIC_LOW_SYS_MASK, @@ -228,6 +259,10 @@ static int max77693_haptic_open(struct input_dev *dev) struct max77693_haptic *haptic = input_get_drvdata(dev); int error; + error = max77843_haptic_bias(haptic, true); + if (error) + return error; + error = regulator_enable(haptic->motor_reg); if (error) { dev_err(haptic->dev, @@ -250,6 +285,8 @@ static void max77693_haptic_close(struct input_dev *dev) if (error) dev_err(haptic->dev, "failed to disable regulator: %d\n", error); + + max77843_haptic_bias(haptic, false); } static int max77693_haptic_probe(struct platform_device *pdev) @@ -274,6 +311,9 @@ static int max77693_haptic_probe(struct platform_device *pdev) case TYPE_MAX77693: haptic->regmap_haptic = max77693->regmap_haptic; break; + case TYPE_MAX77843: + haptic->regmap_haptic = max77693->regmap; + break; default: dev_err(&pdev->dev, "unsupported device type: %u\n", haptic->dev_type); @@ -359,6 +399,7 @@ static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops, static const struct platform_device_id max77693_haptic_id[] = { { "max77693-haptic", TYPE_MAX77693 }, + { "max77843-haptic", TYPE_MAX77843 }, {}, }; MODULE_DEVICE_TABLE(platform, max77693_haptic_id); @@ -374,6 +415,7 @@ static struct platform_driver max77693_haptic_driver = { module_platform_driver(max77693_haptic_driver); MODULE_AUTHOR("Jaewon Kim "); -MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver"); +MODULE_AUTHOR("Krzysztof Kozlowski "); +MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver"); MODULE_ALIAS("platform:max77693-haptic"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 38a986c0750db23aeb5968f8b6d37298b9be4b11 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Jul 2015 10:36:44 +0900 Subject: Input: Remove the max77843 haptic driver The max77693 haptic driver supports Maxim 77843 device so remove the max77843 driver. Signed-off-by: Krzysztof Kozlowski Acked-by: Dmitry Torokhov Signed-off-by: Mark Brown --- drivers/input/misc/Kconfig | 12 -- drivers/input/misc/Makefile | 1 - drivers/input/misc/max77843-haptic.c | 359 ----------------------------------- 3 files changed, 372 deletions(-) delete mode 100644 drivers/input/misc/max77843-haptic.c (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index f5d7a98a329d..c41dec819cdf 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -177,18 +177,6 @@ config INPUT_MAX77693_HAPTIC To compile this driver as module, choose M here: the module will be called max77693-haptic. -config INPUT_MAX77843_HAPTIC - tristate "MAXIM MAX77843 haptic controller support" - depends on MFD_MAX77843 && REGULATOR - select INPUT_FF_MEMLESS - help - This option enables support for the haptic controller on - MAXIM MAX77843 chip. The driver supports ff-memless interface - from input framework. - - To compile this driver as module, choose M here: the - module will be called max77843-haptic. - config INPUT_MAX8925_ONKEY tristate "MAX8925 ONKEY support" depends on MFD_MAX8925 diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 53df07dcc23c..0357a088c6a9 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o -obj-$(CONFIG_INPUT_MAX77843_HAPTIC) += max77843-haptic.o obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o diff --git a/drivers/input/misc/max77843-haptic.c b/drivers/input/misc/max77843-haptic.c deleted file mode 100644 index 30da81ab5a21..000000000000 --- a/drivers/input/misc/max77843-haptic.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * MAXIM MAX77693 Haptic device driver - * - * Copyright (C) 2015 Samsung Electronics - * Author: Jaewon Kim - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_MAGNITUDE_SHIFT 16 - -enum max77843_haptic_motor_type { - MAX77843_HAPTIC_ERM = 0, - MAX77843_HAPTIC_LRA, -}; - -enum max77843_haptic_pwm_divisor { - MAX77843_HAPTIC_PWM_DIVISOR_32 = 0, - MAX77843_HAPTIC_PWM_DIVISOR_64, - MAX77843_HAPTIC_PWM_DIVISOR_128, - MAX77843_HAPTIC_PWM_DIVISOR_256, -}; - -struct max77843_haptic { - struct regmap *regmap_haptic; - struct device *dev; - struct input_dev *input_dev; - struct pwm_device *pwm_dev; - struct regulator *motor_reg; - struct work_struct work; - struct mutex mutex; - - unsigned int magnitude; - unsigned int pwm_duty; - - bool active; - bool suspended; - - enum max77843_haptic_motor_type type; - enum max77843_haptic_pwm_divisor pwm_divisor; -}; - -static int max77843_haptic_set_duty_cycle(struct max77843_haptic *haptic) -{ - int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2; - int error; - - error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period); - if (error) { - dev_err(haptic->dev, "failed to configure pwm: %d\n", error); - return error; - } - - return 0; -} - -static int max77843_haptic_bias(struct max77843_haptic *haptic, bool on) -{ - int error; - - error = regmap_update_bits(haptic->regmap_haptic, - MAX77843_SYS_REG_MAINCTRL1, - MAX77843_MAINCTRL1_BIASEN_MASK, - on << MAINCTRL1_BIASEN_SHIFT); - if (error) { - dev_err(haptic->dev, "failed to %s bias: %d\n", - on ? "enable" : "disable", error); - return error; - } - - return 0; -} - -static int max77843_haptic_config(struct max77843_haptic *haptic, bool enable) -{ - unsigned int value; - int error; - - value = (haptic->type << MCONFIG_MODE_SHIFT) | - (enable << MCONFIG_MEN_SHIFT) | - (haptic->pwm_divisor << MCONFIG_PDIV_SHIFT); - - error = regmap_write(haptic->regmap_haptic, - MAX77843_HAP_REG_MCONFIG, value); - if (error) { - dev_err(haptic->dev, - "failed to update haptic config: %d\n", error); - return error; - } - - return 0; -} - -static int max77843_haptic_enable(struct max77843_haptic *haptic) -{ - int error; - - if (haptic->active) - return 0; - - error = pwm_enable(haptic->pwm_dev); - if (error) { - dev_err(haptic->dev, - "failed to enable pwm device: %d\n", error); - return error; - } - - error = max77843_haptic_config(haptic, true); - if (error) - goto err_config; - - haptic->active = true; - - return 0; - -err_config: - pwm_disable(haptic->pwm_dev); - - return error; -} - -static int max77843_haptic_disable(struct max77843_haptic *haptic) -{ - int error; - - if (!haptic->active) - return 0; - - error = max77843_haptic_config(haptic, false); - if (error) - return error; - - pwm_disable(haptic->pwm_dev); - - haptic->active = false; - - return 0; -} - -static void max77843_haptic_play_work(struct work_struct *work) -{ - struct max77843_haptic *haptic = - container_of(work, struct max77843_haptic, work); - int error; - - mutex_lock(&haptic->mutex); - - if (haptic->suspended) - goto out_unlock; - - if (haptic->magnitude) { - error = max77843_haptic_set_duty_cycle(haptic); - if (error) { - dev_err(haptic->dev, - "failed to set duty cycle: %d\n", error); - goto out_unlock; - } - - error = max77843_haptic_enable(haptic); - if (error) - dev_err(haptic->dev, - "cannot enable haptic: %d\n", error); - } else { - error = max77843_haptic_disable(haptic); - if (error) - dev_err(haptic->dev, - "cannot disable haptic: %d\n", error); - } - -out_unlock: - mutex_unlock(&haptic->mutex); -} - -static int max77843_haptic_play_effect(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct max77843_haptic *haptic = input_get_drvdata(dev); - u64 period_mag_multi; - - haptic->magnitude = effect->u.rumble.strong_magnitude; - if (!haptic->magnitude) - haptic->magnitude = effect->u.rumble.weak_magnitude; - - period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude; - haptic->pwm_duty = (unsigned int)(period_mag_multi >> - MAX_MAGNITUDE_SHIFT); - - schedule_work(&haptic->work); - - return 0; -} - -static int max77843_haptic_open(struct input_dev *dev) -{ - struct max77843_haptic *haptic = input_get_drvdata(dev); - int error; - - error = max77843_haptic_bias(haptic, true); - if (error) - return error; - - error = regulator_enable(haptic->motor_reg); - if (error) { - dev_err(haptic->dev, - "failed to enable regulator: %d\n", error); - return error; - } - - return 0; -} - -static void max77843_haptic_close(struct input_dev *dev) -{ - struct max77843_haptic *haptic = input_get_drvdata(dev); - int error; - - cancel_work_sync(&haptic->work); - max77843_haptic_disable(haptic); - - error = regulator_disable(haptic->motor_reg); - if (error) - dev_err(haptic->dev, - "failed to disable regulator: %d\n", error); - - max77843_haptic_bias(haptic, false); -} - -static int max77843_haptic_probe(struct platform_device *pdev) -{ - struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent); - struct max77843_haptic *haptic; - int error; - - haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL); - if (!haptic) - return -ENOMEM; - - haptic->regmap_haptic = max77843->regmap; - haptic->dev = &pdev->dev; - haptic->type = MAX77843_HAPTIC_LRA; - haptic->pwm_divisor = MAX77843_HAPTIC_PWM_DIVISOR_128; - - INIT_WORK(&haptic->work, max77843_haptic_play_work); - mutex_init(&haptic->mutex); - - haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL); - if (IS_ERR(haptic->pwm_dev)) { - dev_err(&pdev->dev, "failed to get pwm device\n"); - return PTR_ERR(haptic->pwm_dev); - } - - haptic->motor_reg = devm_regulator_get_exclusive(&pdev->dev, "haptic"); - if (IS_ERR(haptic->motor_reg)) { - dev_err(&pdev->dev, "failed to get regulator\n"); - return PTR_ERR(haptic->motor_reg); - } - - haptic->input_dev = devm_input_allocate_device(&pdev->dev); - if (!haptic->input_dev) { - dev_err(&pdev->dev, "failed to allocate input device\n"); - return -ENOMEM; - } - - haptic->input_dev->name = "max77843-haptic"; - haptic->input_dev->id.version = 1; - haptic->input_dev->dev.parent = &pdev->dev; - haptic->input_dev->open = max77843_haptic_open; - haptic->input_dev->close = max77843_haptic_close; - input_set_drvdata(haptic->input_dev, haptic); - input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE); - - error = input_ff_create_memless(haptic->input_dev, NULL, - max77843_haptic_play_effect); - if (error) { - dev_err(&pdev->dev, "failed to create force-feedback\n"); - return error; - } - - error = input_register_device(haptic->input_dev); - if (error) { - dev_err(&pdev->dev, "failed to register input device\n"); - return error; - } - - platform_set_drvdata(pdev, haptic); - - return 0; -} - -static int __maybe_unused max77843_haptic_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct max77843_haptic *haptic = platform_get_drvdata(pdev); - int error; - - error = mutex_lock_interruptible(&haptic->mutex); - if (error) - return error; - - max77843_haptic_disable(haptic); - - haptic->suspended = true; - - mutex_unlock(&haptic->mutex); - - return 0; -} - -static int __maybe_unused max77843_haptic_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct max77843_haptic *haptic = platform_get_drvdata(pdev); - unsigned int magnitude; - - mutex_lock(&haptic->mutex); - - haptic->suspended = false; - - magnitude = ACCESS_ONCE(haptic->magnitude); - if (magnitude) - max77843_haptic_enable(haptic); - - mutex_unlock(&haptic->mutex); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(max77843_haptic_pm_ops, - max77843_haptic_suspend, max77843_haptic_resume); - -static struct platform_driver max77843_haptic_driver = { - .driver = { - .name = "max77843-haptic", - .pm = &max77843_haptic_pm_ops, - }, - .probe = max77843_haptic_probe, -}; -module_platform_driver(max77843_haptic_driver); - -MODULE_AUTHOR("Jaewon Kim "); -MODULE_DESCRIPTION("MAXIM MAX77843 Haptic driver"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9bc07dfbcde5b6f3aefa06b902b47eef9769d260 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 21 Aug 2015 09:48:33 +0200 Subject: ALSA: ac97: Switch to dev_pm_ops Convert the ac97_bus from legacy suspend/resume callbacks to dev_pm_ops. Since there isn't anything special to do at the bus level the bus driver does not have to implement any callbacks. The device driver core will automatically pick up and execute the device's PM ops. As there is only a single AC'97 driver implementing suspend and resume, update both the core and driver at the same time to avoid unnecessary code churn. While we are at it also drop the ifdefs around the suspend/resume functions to increase compile test coverage. Signed-off-by: Lars-Peter Clausen Acked-by: Dmitry Torokhov Signed-off-by: Takashi Iwai --- drivers/input/touchscreen/wm97xx-core.c | 13 ++++--------- sound/ac97_bus.c | 26 -------------------------- 2 files changed, 4 insertions(+), 35 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index b1ae77995968..1534e9b0788c 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -732,8 +732,7 @@ static int wm97xx_remove(struct device *dev) return 0; } -#ifdef CONFIG_PM -static int wm97xx_suspend(struct device *dev, pm_message_t state) +static int __maybe_unused wm97xx_suspend(struct device *dev) { struct wm97xx *wm = dev_get_drvdata(dev); u16 reg; @@ -765,7 +764,7 @@ static int wm97xx_suspend(struct device *dev, pm_message_t state) return 0; } -static int wm97xx_resume(struct device *dev) +static int __maybe_unused wm97xx_resume(struct device *dev) { struct wm97xx *wm = dev_get_drvdata(dev); @@ -799,10 +798,7 @@ static int wm97xx_resume(struct device *dev) return 0; } -#else -#define wm97xx_suspend NULL -#define wm97xx_resume NULL -#endif +static SIMPLE_DEV_PM_OPS(wm97xx_pm_ops, wm97xx_suspend, wm97xx_resume); /* * Machine specific operations @@ -836,8 +832,7 @@ static struct device_driver wm97xx_driver = { .owner = THIS_MODULE, .probe = wm97xx_probe, .remove = wm97xx_remove, - .suspend = wm97xx_suspend, - .resume = wm97xx_resume, + .pm = &wm97xx_pm_ops, }; static int __init wm97xx_init(void) diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c index 2b50cbe6aca9..57a6dfc4b694 100644 --- a/sound/ac97_bus.c +++ b/sound/ac97_bus.c @@ -27,35 +27,9 @@ static int ac97_bus_match(struct device *dev, struct device_driver *drv) return 1; } -#ifdef CONFIG_PM -static int ac97_bus_suspend(struct device *dev, pm_message_t state) -{ - int ret = 0; - - if (dev->driver && dev->driver->suspend) - ret = dev->driver->suspend(dev, state); - - return ret; -} - -static int ac97_bus_resume(struct device *dev) -{ - int ret = 0; - - if (dev->driver && dev->driver->resume) - ret = dev->driver->resume(dev); - - return ret; -} -#endif /* CONFIG_PM */ - struct bus_type ac97_bus_type = { .name = "ac97", .match = ac97_bus_match, -#ifdef CONFIG_PM - .suspend = ac97_bus_suspend, - .resume = ac97_bus_resume, -#endif /* CONFIG_PM */ }; static int __init ac97_bus_init(void) -- cgit v1.2.3 From 832f5dacfa0bb081a3b3b979a36a132b28ffacf3 Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Sun, 2 Aug 2015 18:30:11 +0200 Subject: MIPS: Remove all the uses of custom gpio.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently CONFIG_ARCH_HAVE_CUSTOM_GPIO_H is defined for all MIPS machines, and each machine type provides its own gpio.h. However only a handful really implement the GPIO API, most just forward everythings to gpiolib. The Alchemy machine is notable as it provides a system to allow implementing the GPIO API at the board level. But it is not used by any board currently supported, so it can also be removed. For most machine types we can just remove the custom gpio.h, as well as the custom wrappers if some exists. Some of the code found in the wrappers must be moved to the respective GPIO driver. A few more fixes are need in some drivers as they rely on linux/gpio.h to provides some machine specific definitions, or used asm/gpio.h instead of linux/gpio.h for the gpio API. Signed-off-by: Alban Bedel Reviewed-by: Linus Walleij Cc: linux-mips@linux-mips.org Cc: Hauke Mehrtens Cc: Rafał Miłecki Cc: Bartlomiej Zolnierkiewicz Cc: Tejun Heo Cc: Alexandre Courbot Cc: Dmitry Torokhov Cc: Florian Fainelli Cc: Manuel Lauss Cc: Joe Perches Cc: Daniel Walter Cc: Sergey Ryazanov Cc: Huacai Chen Cc: James Hartley Cc: Andrew Bresticker Cc: Paul Burton Cc: Jiri Kosina Cc: Bjorn Helgaas Cc: Wolfram Sang Cc: Randy Dunlap Cc: Varka Bhadram Cc: Masanari Iida Cc: Tomi Valkeinen Cc: Michael Buesch Cc: abdoulaye berthe Cc: linux-kernel@vger.kernel.org Cc: linux-ide@vger.kernel.org Cc: linux-gpio@vger.kernel.org Cc: linux-input@vger.kernel.org Cc: netdev@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/10828/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 - arch/mips/alchemy/Kconfig | 7 -- arch/mips/alchemy/board-gpr.c | 1 + arch/mips/alchemy/board-mtx1.c | 1 + arch/mips/alchemy/common/Makefile | 7 +- arch/mips/alchemy/devboards/db1000.c | 1 + arch/mips/alchemy/devboards/db1300.c | 1 + arch/mips/alchemy/devboards/db1550.c | 1 + arch/mips/alchemy/devboards/pm.c | 2 +- arch/mips/ar7/gpio.c | 5 +- arch/mips/ar7/platform.c | 1 - arch/mips/ar7/setup.c | 1 - arch/mips/include/asm/gpio.h | 6 - arch/mips/include/asm/mach-ar7/ar7.h | 4 + arch/mips/include/asm/mach-ar7/gpio.h | 41 ------- arch/mips/include/asm/mach-ath25/gpio.h | 16 --- arch/mips/include/asm/mach-ath79/gpio.h | 26 ----- arch/mips/include/asm/mach-au1x00/gpio-au1000.h | 148 ++---------------------- arch/mips/include/asm/mach-au1x00/gpio.h | 86 -------------- arch/mips/include/asm/mach-bcm47xx/gpio.h | 17 --- arch/mips/include/asm/mach-bcm63xx/gpio.h | 15 --- arch/mips/include/asm/mach-cavium-octeon/gpio.h | 21 ---- arch/mips/include/asm/mach-generic/gpio.h | 21 ---- arch/mips/include/asm/mach-jz4740/gpio.h | 2 - arch/mips/include/asm/mach-lantiq/gpio.h | 13 --- arch/mips/include/asm/mach-loongson64/gpio.h | 36 ------ arch/mips/include/asm/mach-pistachio/gpio.h | 21 ---- arch/mips/include/asm/mach-rc32434/gpio.h | 12 -- arch/mips/jz4740/gpio.c | 20 ++-- arch/mips/pci/pci-lantiq.c | 1 - arch/mips/rb532/devices.c | 1 + arch/mips/rb532/gpio.c | 6 + arch/mips/txx9/generic/setup.c | 16 --- drivers/ata/pata_rb532_cf.c | 3 +- drivers/gpio/gpio-ath79.c | 32 ----- drivers/input/misc/rb532_button.c | 1 + drivers/net/ethernet/ti/cpmac.c | 2 + 37 files changed, 45 insertions(+), 551 deletions(-) delete mode 100644 arch/mips/include/asm/gpio.h delete mode 100644 arch/mips/include/asm/mach-ar7/gpio.h delete mode 100644 arch/mips/include/asm/mach-ath25/gpio.h delete mode 100644 arch/mips/include/asm/mach-ath79/gpio.h delete mode 100644 arch/mips/include/asm/mach-au1x00/gpio.h delete mode 100644 arch/mips/include/asm/mach-bcm47xx/gpio.h delete mode 100644 arch/mips/include/asm/mach-bcm63xx/gpio.h delete mode 100644 arch/mips/include/asm/mach-cavium-octeon/gpio.h delete mode 100644 arch/mips/include/asm/mach-generic/gpio.h delete mode 100644 arch/mips/include/asm/mach-lantiq/gpio.h delete mode 100644 arch/mips/include/asm/mach-loongson64/gpio.h delete mode 100644 arch/mips/include/asm/mach-pistachio/gpio.h (limited to 'drivers/input') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 449f840d5a7f..06c5957917d3 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -14,7 +14,6 @@ config MIPS select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_BPF_JIT if !CPU_MICROMIPS - select ARCH_HAVE_CUSTOM_GPIO_H select HAVE_FUNCTION_TRACER select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index b9628983d620..7fa24881b708 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -6,13 +6,6 @@ config ALCHEMY_GPIOINT_AU1000 config ALCHEMY_GPIOINT_AU1300 bool -# select this in your board config if you don't want to use the gpio -# namespace as documented in the manuals. In this case however you need -# to create the necessary gpio_* functions in your board code/headers! -# see arch/mips/include/asm/mach-au1x00/gpio.h for more information. -config ALCHEMY_GPIO_INDIRECT - def_bool n - choice prompt "Machine type" depends on MIPS_ALCHEMY diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c index acf9a2a37f5a..79efe4c6e636 100644 --- a/arch/mips/alchemy/board-gpr.c +++ b/arch/mips/alchemy/board-gpr.c @@ -34,6 +34,7 @@ #include #include #include +#include #include const char *get_system_type(void) diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c index 1e3b102389ef..85bb75669b0d 100644 --- a/arch/mips/alchemy/board-mtx1.c +++ b/arch/mips/alchemy/board-mtx1.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile index f64744f3b59f..23800b8e67e5 100644 --- a/arch/mips/alchemy/common/Makefile +++ b/arch/mips/alchemy/common/Makefile @@ -5,10 +5,5 @@ # Makefile for the Alchemy Au1xx0 CPUs, generic files. # -obj-y += prom.o time.o clock.o platform.o power.o \ +obj-y += prom.o time.o clock.o platform.o power.o gpiolib.o \ setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o - -# optional gpiolib support -ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) - obj-$(CONFIG_GPIOLIB) += gpiolib.o -endif diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c index 001102e197f1..bdeed9d13c6f 100644 --- a/arch/mips/alchemy/devboards/db1000.c +++ b/arch/mips/alchemy/devboards/db1000.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c index 1c64fdbe4c81..b58077008a53 100644 --- a/arch/mips/alchemy/devboards/db1300.c +++ b/arch/mips/alchemy/devboards/db1300.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c index 0fd5177e35ab..5740bcfdfc7f 100644 --- a/arch/mips/alchemy/devboards/db1550.c +++ b/arch/mips/alchemy/devboards/db1550.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c index bfeb8f3c0be6..93024dc6b314 100644 --- a/arch/mips/alchemy/devboards/pm.c +++ b/arch/mips/alchemy/devboards/pm.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c index d8dbd8f0c1d2..f4930456eb8e 100644 --- a/arch/mips/ar7/gpio.c +++ b/arch/mips/ar7/gpio.c @@ -21,7 +21,10 @@ #include #include -#include +#include + +#define AR7_GPIO_MAX 32 +#define TITAN_GPIO_MAX 51 struct ar7_gpio_chip { void __iomem *regs; diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index be9ff1673ded..462a252ea6e6 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -39,7 +39,6 @@ #include #include -#include #include /***************************************************************************** diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c index 820b7a313d9b..7bb9a670bb73 100644 --- a/arch/mips/ar7/setup.c +++ b/arch/mips/ar7/setup.c @@ -23,7 +23,6 @@ #include #include #include -#include static void ar7_machine_restart(char *command) { diff --git a/arch/mips/include/asm/gpio.h b/arch/mips/include/asm/gpio.h deleted file mode 100644 index 06e46faf862d..000000000000 --- a/arch/mips/include/asm/gpio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_MIPS_GPIO_H -#define __ASM_MIPS_GPIO_H - -#include - -#endif /* __ASM_MIPS_GPIO_H */ diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index a47ea0c85248..468cbd61b906 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -203,4 +203,8 @@ static inline void ar7_device_off(u32 bit) int __init ar7_gpio_init(void); void __init ar7_init_clocks(void); +/* Board specific GPIO functions */ +int ar7_gpio_enable(unsigned gpio); +int ar7_gpio_disable(unsigned gpio); + #endif /* __AR7_H__ */ diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h deleted file mode 100644 index c177cd1eed25..000000000000 --- a/arch/mips/include/asm/mach-ar7/gpio.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007-2009 Florian Fainelli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __AR7_GPIO_H__ -#define __AR7_GPIO_H__ - -#include - -#define AR7_GPIO_MAX 32 -#define TITAN_GPIO_MAX 51 -#define NR_BUILTIN_GPIO TITAN_GPIO_MAX - -#define gpio_to_irq(gpio) -1 - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value - -#define gpio_cansleep __gpio_cansleep - -/* Board specific GPIO functions */ -int ar7_gpio_enable(unsigned gpio); -int ar7_gpio_disable(unsigned gpio); - -#include - -#endif diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/include/asm/mach-ath25/gpio.h deleted file mode 100644 index 713564b8e8ef..000000000000 --- a/arch/mips/include/asm/mach-ath25/gpio.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __ASM_MACH_ATH25_GPIO_H -#define __ASM_MACH_ATH25_GPIO_H - -#include - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#define gpio_to_irq __gpio_to_irq - -static inline int irq_to_gpio(unsigned irq) -{ - return -EINVAL; -} - -#endif /* __ASM_MACH_ATH25_GPIO_H */ diff --git a/arch/mips/include/asm/mach-ath79/gpio.h b/arch/mips/include/asm/mach-ath79/gpio.h deleted file mode 100644 index 60dcb62785b4..000000000000 --- a/arch/mips/include/asm/mach-ath79/gpio.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Atheros AR71XX/AR724X/AR913X GPIO API definitions - * - * Copyright (C) 2008-2010 Gabor Juhos - * Copyright (C) 2008 Imre Kaloz - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#ifndef __ASM_MACH_ATH79_GPIO_H -#define __ASM_MACH_ATH79_GPIO_H - -#define ARCH_NR_GPIOS 64 -#include - -int gpio_to_irq(unsigned gpio); -int irq_to_gpio(unsigned irq); -int gpio_get_value(unsigned gpio); -void gpio_set_value(unsigned gpio, int value); - -#define gpio_cansleep __gpio_cansleep - -#endif /* __ASM_MACH_ATH79_GPIO_H */ diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h index 9785e4ebb450..adde1fa5097e 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h +++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h @@ -266,6 +266,17 @@ static inline int alchemy_gpio1_to_irq(int gpio) return -ENXIO; } +/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before + * SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this + * register enables use of GPIOs as wake source. + */ +static inline void alchemy_gpio1_input_enable(void) +{ + void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR); + __raw_writel(0, base + 0x110); /* the write op is key */ + wmb(); +} + /* * GPIO2 block macros for common linux GPIO functions. The 'gpio' * parameter must be in range of ALCHEMY_GPIO2_BASE..ALCHEMY_GPIO2_MAX. @@ -518,141 +529,4 @@ static inline int alchemy_irq_to_gpio(int irq) return -ENXIO; } -/**********************************************************************/ - -/* Linux gpio framework integration. - * - * 4 use cases of Au1000-Au1200 GPIOS: - *(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y: - * Board must register gpiochips. - *(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n: - * 2 (1 for Au1000) gpio_chips are registered. - * - *(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y: - * the boards' gpio.h must provide the linux gpio wrapper functions, - * - *(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n: - * inlinable gpio functions are provided which enable access to the - * Au1000 gpios only by using the numbers straight out of the data- - * sheets. - - * Cases 1 and 3 are intended for boards which want to provide their own - * GPIO namespace and -operations (i.e. for example you have 8 GPIOs - * which are in part provided by spare Au1000 GPIO pins and in part by - * an external FPGA but you still want them to be accssible in linux - * as gpio0-7. The board can of course use the alchemy_gpioX_* functions - * as required). - */ - -#ifndef CONFIG_GPIOLIB - -#ifdef CONFIG_ALCHEMY_GPIOINT_AU1000 - -#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (4) */ - -static inline int gpio_direction_input(int gpio) -{ - return alchemy_gpio_direction_input(gpio); -} - -static inline int gpio_direction_output(int gpio, int v) -{ - return alchemy_gpio_direction_output(gpio, v); -} - -static inline int gpio_get_value(int gpio) -{ - return alchemy_gpio_get_value(gpio); -} - -static inline void gpio_set_value(int gpio, int v) -{ - alchemy_gpio_set_value(gpio, v); -} - -static inline int gpio_get_value_cansleep(unsigned gpio) -{ - return gpio_get_value(gpio); -} - -static inline void gpio_set_value_cansleep(unsigned gpio, int value) -{ - gpio_set_value(gpio, value); -} - -static inline int gpio_is_valid(int gpio) -{ - return alchemy_gpio_is_valid(gpio); -} - -static inline int gpio_cansleep(int gpio) -{ - return alchemy_gpio_cansleep(gpio); -} - -static inline int gpio_to_irq(int gpio) -{ - return alchemy_gpio_to_irq(gpio); -} - -static inline int irq_to_gpio(int irq) -{ - return alchemy_irq_to_gpio(irq); -} - -static inline int gpio_request(unsigned gpio, const char *label) -{ - return 0; -} - -static inline int gpio_request_one(unsigned gpio, - unsigned long flags, const char *label) -{ - return 0; -} - -static inline int gpio_request_array(struct gpio *array, size_t num) -{ - return 0; -} - -static inline void gpio_free(unsigned gpio) -{ -} - -static inline void gpio_free_array(struct gpio *array, size_t num) -{ -} - -static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) -{ - return -ENOSYS; -} - -static inline int gpio_export(unsigned gpio, bool direction_may_change) -{ - return -ENOSYS; -} - -static inline int gpio_export_link(struct device *dev, const char *name, - unsigned gpio) -{ - return -ENOSYS; -} - -static inline int gpio_sysfs_set_active_low(unsigned gpio, int value) -{ - return -ENOSYS; -} - -static inline void gpio_unexport(unsigned gpio) -{ -} - -#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */ - -#endif /* CONFIG_ALCHEMY_GPIOINT_AU1000 */ - -#endif /* !CONFIG_GPIOLIB */ - #endif /* _ALCHEMY_GPIO_AU1000_H_ */ diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h deleted file mode 100644 index 22e7ff17fc48..000000000000 --- a/arch/mips/include/asm/mach-au1x00/gpio.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Alchemy GPIO support. - * - * With CONFIG_GPIOLIB=y different types of on-chip GPIO can be supported within - * the same kernel image. - * With CONFIG_GPIOLIB=n, your board must select ALCHEMY_GPIOINT_AU1XXX for the - * appropriate CPU type (AU1000 currently). - */ - -#ifndef _ALCHEMY_GPIO_H_ -#define _ALCHEMY_GPIO_H_ - -#include -#include -#include - -/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before - * SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this - * register enables use of GPIOs as wake source. - */ -static inline void alchemy_gpio1_input_enable(void) -{ - void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR); - __raw_writel(0, base + 0x110); /* the write op is key */ - wmb(); -} - - -/* Linux gpio framework integration. -* -* 4 use cases of Alchemy GPIOS: -*(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y: -* Board must register gpiochips. -*(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n: -* A gpiochip for the 75 GPIOs is registered. -* -*(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y: -* the boards' gpio.h must provide the linux gpio wrapper functions, -* -*(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n: -* inlinable gpio functions are provided which enable access to the -* Au1300 gpios only by using the numbers straight out of the data- -* sheets. - -* Cases 1 and 3 are intended for boards which want to provide their own -* GPIO namespace and -operations (i.e. for example you have 8 GPIOs -* which are in part provided by spare Au1300 GPIO pins and in part by -* an external FPGA but you still want them to be accssible in linux -* as gpio0-7. The board can of course use the alchemy_gpioX_* functions -* as required). -*/ - -#ifdef CONFIG_GPIOLIB - -/* wraps the cpu-dependent irq_to_gpio functions */ -/* FIXME: gpiolib needs an irq_to_gpio hook */ -static inline int __au_irq_to_gpio(unsigned int irq) -{ - switch (alchemy_get_cputype()) { - case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200: - return alchemy_irq_to_gpio(irq); - case ALCHEMY_CPU_AU1300: - return au1300_irq_to_gpio(irq); - } - return -EINVAL; -} - - -/* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */ -#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (2) */ - -/* get everything through gpiolib */ -#define gpio_to_irq __gpio_to_irq -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#define irq_to_gpio __au_irq_to_gpio - -#include - -#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */ - - -#endif /* CONFIG_GPIOLIB */ - -#endif /* _ALCHEMY_GPIO_H_ */ diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h deleted file mode 100644 index 90daefa24a4d..000000000000 --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H -#define __ASM_MIPS_MACH_BCM47XX_GPIO_H - -#include - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value - -#define gpio_cansleep __gpio_cansleep -#define gpio_to_irq __gpio_to_irq - -static inline int irq_to_gpio(unsigned int irq) -{ - return -EINVAL; -} - -#endif diff --git a/arch/mips/include/asm/mach-bcm63xx/gpio.h b/arch/mips/include/asm/mach-bcm63xx/gpio.h deleted file mode 100644 index 1eb534de8e3b..000000000000 --- a/arch/mips/include/asm/mach-bcm63xx/gpio.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __ASM_MIPS_MACH_BCM63XX_GPIO_H -#define __ASM_MIPS_MACH_BCM63XX_GPIO_H - -#include - -#define gpio_to_irq(gpio) -1 - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value - -#define gpio_cansleep __gpio_cansleep - -#include - -#endif /* __ASM_MIPS_MACH_BCM63XX_GPIO_H */ diff --git a/arch/mips/include/asm/mach-cavium-octeon/gpio.h b/arch/mips/include/asm/mach-cavium-octeon/gpio.h deleted file mode 100644 index 34e9f7aabab4..000000000000 --- a/arch/mips/include/asm/mach-cavium-octeon/gpio.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __ASM_MACH_CAVIUM_OCTEON_GPIO_H -#define __ASM_MACH_CAVIUM_OCTEON_GPIO_H - -#ifdef CONFIG_GPIOLIB -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#else -int gpio_request(unsigned gpio, const char *label); -void gpio_free(unsigned gpio); -int gpio_direction_input(unsigned gpio); -int gpio_direction_output(unsigned gpio, int value); -int gpio_get_value(unsigned gpio); -void gpio_set_value(unsigned gpio, int value); -#endif - -#include - -#define gpio_to_irq __gpio_to_irq - -#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/arch/mips/include/asm/mach-generic/gpio.h b/arch/mips/include/asm/mach-generic/gpio.h deleted file mode 100644 index b4e70208da64..000000000000 --- a/arch/mips/include/asm/mach-generic/gpio.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __ASM_MACH_GENERIC_GPIO_H -#define __ASM_MACH_GENERIC_GPIO_H - -#ifdef CONFIG_GPIOLIB -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#else -int gpio_request(unsigned gpio, const char *label); -void gpio_free(unsigned gpio); -int gpio_direction_input(unsigned gpio); -int gpio_direction_output(unsigned gpio, int value); -int gpio_get_value(unsigned gpio); -void gpio_set_value(unsigned gpio, int value); -#endif -int gpio_to_irq(unsigned gpio); -int irq_to_gpio(unsigned irq); - -#include /* cansleep wrappers */ - -#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/arch/mips/include/asm/mach-jz4740/gpio.h b/arch/mips/include/asm/mach-jz4740/gpio.h index eaacba79cf18..bf8c3e1860e7 100644 --- a/arch/mips/include/asm/mach-jz4740/gpio.h +++ b/arch/mips/include/asm/mach-jz4740/gpio.h @@ -73,8 +73,6 @@ int jz_gpio_port_direction_output(int port, uint32_t mask); void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask); uint32_t jz_gpio_port_get_value(int port, uint32_t mask); -#include - #define JZ_GPIO_PORTA(x) ((x) + 32 * 0) #define JZ_GPIO_PORTB(x) ((x) + 32 * 1) #define JZ_GPIO_PORTC(x) ((x) + 32 * 2) diff --git a/arch/mips/include/asm/mach-lantiq/gpio.h b/arch/mips/include/asm/mach-lantiq/gpio.h deleted file mode 100644 index 9ba1caebca5f..000000000000 --- a/arch/mips/include/asm/mach-lantiq/gpio.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H -#define __ASM_MIPS_MACH_LANTIQ_GPIO_H - -#define gpio_to_irq __gpio_to_irq - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value - -#define gpio_cansleep __gpio_cansleep - -#include - -#endif diff --git a/arch/mips/include/asm/mach-loongson64/gpio.h b/arch/mips/include/asm/mach-loongson64/gpio.h deleted file mode 100644 index b3b216904a9a..000000000000 --- a/arch/mips/include/asm/mach-loongson64/gpio.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Loongson GPIO Support - * - * Copyright (c) 2008 Richard Liu, STMicroelectronics - * Copyright (c) 2008-2010 Arnaud Patard - * Copyright (c) 2014 Huacai Chen - * - * 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 __LOONGSON_GPIO_H -#define __LOONGSON_GPIO_H - -#include - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep - -/* The chip can do interrupt - * but it has not been tested and doc not clear - */ -static inline int gpio_to_irq(int gpio) -{ - return -EINVAL; -} - -static inline int irq_to_gpio(int gpio) -{ - return -EINVAL; -} - -#endif /* __LOONGSON_GPIO_H */ diff --git a/arch/mips/include/asm/mach-pistachio/gpio.h b/arch/mips/include/asm/mach-pistachio/gpio.h deleted file mode 100644 index 6c1649c27b8d..000000000000 --- a/arch/mips/include/asm/mach-pistachio/gpio.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Pistachio IRQ setup - * - * Copyright (C) 2014 Google, Inc. - * - * 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. - */ - -#ifndef __ASM_MACH_PISTACHIO_GPIO_H -#define __ASM_MACH_PISTACHIO_GPIO_H - -#include - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#define gpio_to_irq __gpio_to_irq - -#endif /* __ASM_MACH_PISTACHIO_GPIO_H */ diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h index 4dee0a34250c..db211212ce79 100644 --- a/arch/mips/include/asm/mach-rc32434/gpio.h +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -13,18 +13,6 @@ #ifndef _RC32434_GPIO_H_ #define _RC32434_GPIO_H_ -#include -#include - -#define NR_BUILTIN_GPIO 32 - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep - -#define gpio_to_irq(gpio) (8 + 4 * 32 + gpio) -#define irq_to_gpio(irq) (irq - (8 + 4 * 32)) - struct rb532_gpio_reg { u32 gpiofunc; /* GPIO Function Register * gpiofunc[x]==0 bit = gpio diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 77df1602f818..6cd69fdaa1c5 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c @@ -231,6 +231,13 @@ static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) return 0; } +static int jz_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + struct jz_gpio_chip *jz_gpio = gpio_chip_to_jz_gpio_chip(chip); + + return jz_gpio->irq_base + gpio; +} + int jz_gpio_port_direction_input(int port, uint32_t mask) { writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR)); @@ -262,18 +269,6 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask) } EXPORT_SYMBOL(jz_gpio_port_get_value); -int gpio_to_irq(unsigned gpio) -{ - return JZ4740_IRQ_GPIO(0) + gpio; -} -EXPORT_SYMBOL_GPL(gpio_to_irq); - -int irq_to_gpio(unsigned irq) -{ - return irq - JZ4740_IRQ_GPIO(0); -} -EXPORT_SYMBOL_GPL(irq_to_gpio); - #define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f) static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq) @@ -403,6 +398,7 @@ static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) .get = jz_gpio_get_value, \ .direction_output = jz_gpio_direction_output, \ .direction_input = jz_gpio_direction_input, \ + .to_irq = jz_gpio_to_irq, \ .base = JZ4740_GPIO_BASE_ ## _bank, \ .ngpio = JZ4740_GPIO_NUM_ ## _bank, \ }, \ diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index c5347d99cf3a..6a15dbd085aa 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -20,7 +20,6 @@ #include #include -#include #include #include diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index e31e8cdcb296..9bd7a2de0765 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 5aa3df853082..650d5d39f34d 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -140,6 +140,11 @@ static int rb532_gpio_direction_output(struct gpio_chip *chip, return 0; } +static int rb532_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + return 8 + 4 * 32 + gpio; +} + static struct rb532_gpio_chip rb532_gpio_chip[] = { [0] = { .chip = { @@ -148,6 +153,7 @@ static struct rb532_gpio_chip rb532_gpio_chip[] = { .direction_output = rb532_gpio_direction_output, .get = rb532_gpio_get, .set = rb532_gpio_set, + .to_irq = rb532_gpio_to_irq, .base = 0, .ngpio = 32, }, diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 2791b8641df6..9d9962ab7d25 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -117,22 +117,6 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); -/* GPIO support */ - -#ifdef CONFIG_GPIOLIB -int gpio_to_irq(unsigned gpio) -{ - return -EINVAL; -} -EXPORT_SYMBOL(gpio_to_irq); - -int irq_to_gpio(unsigned irq) -{ - return -EINVAL; -} -EXPORT_SYMBOL(irq_to_gpio); -#endif - #define BOARD_VEC(board) extern struct txx9_board_vec board; #include #undef BOARD_VEC diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 6d08446b877c..12fe0f3bb7e9 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -27,12 +27,11 @@ #include #include #include +#include #include #include -#include - #define DRV_NAME "pata-rb532-cf" #define DRV_VERSION "0.1.0" #define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash" diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index c3c92eb56e04..03b995304ad6 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -202,35 +202,3 @@ static struct platform_driver ath79_gpio_driver = { }; module_platform_driver(ath79_gpio_driver); - -int gpio_get_value(unsigned gpio) -{ - if (gpio < ath79_gpio_count) - return __ath79_gpio_get_value(gpio); - - return __gpio_get_value(gpio); -} -EXPORT_SYMBOL(gpio_get_value); - -void gpio_set_value(unsigned gpio, int value) -{ - if (gpio < ath79_gpio_count) - __ath79_gpio_set_value(gpio, value); - else - __gpio_set_value(gpio, value); -} -EXPORT_SYMBOL(gpio_set_value); - -int gpio_to_irq(unsigned gpio) -{ - /* FIXME */ - return -EINVAL; -} -EXPORT_SYMBOL(gpio_to_irq); - -int irq_to_gpio(unsigned irq) -{ - /* FIXME */ - return -EINVAL; -} -EXPORT_SYMBOL(irq_to_gpio); diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c index e956e81cd4e6..62c5814c796b 100644 --- a/drivers/input/misc/rb532_button.c +++ b/drivers/input/misc/rb532_button.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index dd9430043536..cba3d9fcb465 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -41,6 +41,8 @@ #include #include +#include + MODULE_AUTHOR("Eugene Konev "); MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 0df4f266b3af90442bbeb5e685a84a80745beba0 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Fri, 7 Aug 2015 17:34:37 +0100 Subject: xen: Use correctly the Xen memory terminologies Based on include/xen/mm.h [1], Linux is mistakenly using MFN when GFN is meant, I suspect this is because the first support for Xen was for PV. This resulted in some misimplementation of helpers on ARM and confused developers about the expected behavior. For instance, with pfn_to_mfn, we expect to get an MFN based on the name. Although, if we look at the implementation on x86, it's returning a GFN. For clarity and avoid new confusion, replace any reference to mfn with gfn in any helpers used by PV drivers. The x86 code will still keep some reference of pfn_to_mfn which may be used by all kind of guests No changes as been made in the hypercall field, even though they may be invalid, in order to keep the same as the defintion in xen repo. Note that page_to_mfn has been renamed to xen_page_to_gfn to avoid a name to close to the KVM function gfn_to_page. Take also the opportunity to simplify simple construction such as pfn_to_mfn(page_to_pfn(page)) into xen_page_to_gfn. More complex clean up will come in follow-up patches. [1] http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=e758ed14f390342513405dd766e874934573e6cb Signed-off-by: Julien Grall Reviewed-by: Stefano Stabellini Acked-by: Dmitry Torokhov Acked-by: Wei Liu Signed-off-by: David Vrabel --- arch/arm/include/asm/xen/page.h | 13 ++++++------ arch/x86/include/asm/xen/page.h | 35 +++++++++++++++++++++++++++++++-- arch/x86/xen/smp.c | 2 +- drivers/block/xen-blkfront.c | 6 +++--- drivers/input/misc/xen-kbdfront.c | 4 ++-- drivers/net/xen-netback/netback.c | 4 ++-- drivers/net/xen-netfront.c | 12 ++++++----- drivers/scsi/xen-scsifront.c | 10 +++++----- drivers/tty/hvc/hvc_xen.c | 5 +++-- drivers/video/fbdev/xen-fbfront.c | 4 ++-- drivers/xen/balloon.c | 2 +- drivers/xen/events/events_base.c | 2 +- drivers/xen/events/events_fifo.c | 4 ++-- drivers/xen/gntalloc.c | 3 ++- drivers/xen/manage.c | 2 +- drivers/xen/tmem.c | 4 ++-- drivers/xen/xenbus/xenbus_client.c | 2 +- drivers/xen/xenbus/xenbus_dev_backend.c | 2 +- drivers/xen/xenbus/xenbus_probe.c | 8 +++----- include/xen/page.h | 4 ++-- 20 files changed, 81 insertions(+), 47 deletions(-) (limited to 'drivers/input') diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index 911d62b4df26..127956353b00 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h @@ -34,14 +34,15 @@ typedef struct xpaddr { unsigned long __pfn_to_mfn(unsigned long pfn); extern struct rb_root phys_to_mach; -static inline unsigned long pfn_to_mfn(unsigned long pfn) +/* Pseudo-physical <-> Guest conversion */ +static inline unsigned long pfn_to_gfn(unsigned long pfn) { return pfn; } -static inline unsigned long mfn_to_pfn(unsigned long mfn) +static inline unsigned long gfn_to_pfn(unsigned long gfn) { - return mfn; + return gfn; } /* Pseudo-physical <-> BUS conversion */ @@ -65,9 +66,9 @@ static inline unsigned long bfn_to_pfn(unsigned long bfn) #define bfn_to_local_pfn(bfn) bfn_to_pfn(bfn) -/* VIRT <-> MACHINE conversion */ -#define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v))) -#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) +/* VIRT <-> GUEST conversion */ +#define virt_to_gfn(v) (pfn_to_gfn(virt_to_pfn(v))) +#define gfn_to_virt(m) (__va(gfn_to_pfn(m) << PAGE_SHIFT)) /* Only used in PV code. But ARM guests are always HVM. */ static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr) diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 724bffbde54d..0679e11d2cf7 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -101,6 +101,11 @@ static inline unsigned long pfn_to_mfn(unsigned long pfn) { unsigned long mfn; + /* + * Some x86 code are still using pfn_to_mfn instead of + * pfn_to_mfn. This will have to be removed when we figured + * out which call. + */ if (xen_feature(XENFEAT_auto_translated_physmap)) return pfn; @@ -147,6 +152,11 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn) { unsigned long pfn; + /* + * Some x86 code are still using mfn_to_pfn instead of + * gfn_to_pfn. This will have to be removed when we figure + * out which call. + */ if (xen_feature(XENFEAT_auto_translated_physmap)) return mfn; @@ -176,9 +186,26 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine) return XPADDR(PFN_PHYS(mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset); } +/* Pseudo-physical <-> Guest conversion */ +static inline unsigned long pfn_to_gfn(unsigned long pfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return pfn; + else + return pfn_to_mfn(pfn); +} + +static inline unsigned long gfn_to_pfn(unsigned long gfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return gfn; + else + return mfn_to_pfn(gfn); +} + /* Pseudo-physical <-> Bus conversion */ -#define pfn_to_bfn(pfn) pfn_to_mfn(pfn) -#define bfn_to_pfn(bfn) mfn_to_pfn(bfn) +#define pfn_to_bfn(pfn) pfn_to_gfn(pfn) +#define bfn_to_pfn(bfn) gfn_to_pfn(bfn) /* * We detect special mappings in one of two ways: @@ -219,6 +246,10 @@ static inline unsigned long bfn_to_local_pfn(unsigned long mfn) #define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v))) #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) +/* VIRT <-> GUEST conversion */ +#define virt_to_gfn(v) (pfn_to_gfn(virt_to_pfn(v))) +#define gfn_to_virt(g) (__va(gfn_to_pfn(g) << PAGE_SHIFT)) + static inline unsigned long pte_mfn(pte_t pte) { return (pte.pte & PTE_PFN_MASK) >> PAGE_SHIFT; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 2a9ff7342791..3f4ebf0261f2 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -453,7 +453,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) } #endif ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs); - ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir)); + ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_gfn(swapper_pg_dir)); if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, ctxt)) BUG(); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 5dd591d6c859..432e1058721f 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -250,7 +250,7 @@ static struct grant *get_grant(grant_ref_t *gref_head, struct blkfront_info *info) { struct grant *gnt_list_entry; - unsigned long buffer_mfn; + unsigned long buffer_gfn; BUG_ON(list_empty(&info->grants)); gnt_list_entry = list_first_entry(&info->grants, struct grant, @@ -269,10 +269,10 @@ static struct grant *get_grant(grant_ref_t *gref_head, BUG_ON(!pfn); gnt_list_entry->pfn = pfn; } - buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); + buffer_gfn = pfn_to_gfn(gnt_list_entry->pfn); gnttab_grant_foreign_access_ref(gnt_list_entry->gref, info->xbdev->otherend_id, - buffer_mfn, 0); + buffer_gfn, 0); return gnt_list_entry; } diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 95599e478e19..23d0549539d4 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -232,7 +232,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, struct xenbus_transaction xbt; ret = gnttab_grant_foreign_access(dev->otherend_id, - virt_to_mfn(info->page), 0); + virt_to_gfn(info->page), 0); if (ret < 0) return ret; info->gref = ret; @@ -255,7 +255,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, goto error_irqh; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", - virt_to_mfn(info->page)); + virt_to_gfn(info->page)); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 3f44b522b831..7c64c74711e8 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -314,7 +314,7 @@ static void xenvif_gop_frag_copy(struct xenvif_queue *queue, struct sk_buff *skb } else { copy_gop->source.domid = DOMID_SELF; copy_gop->source.u.gmfn = - virt_to_mfn(page_address(page)); + virt_to_gfn(page_address(page)); } copy_gop->source.offset = offset; @@ -1296,7 +1296,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, queue->tx_copy_ops[*copy_ops].source.offset = txreq.offset; queue->tx_copy_ops[*copy_ops].dest.u.gmfn = - virt_to_mfn(skb->data); + virt_to_gfn(skb->data); queue->tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF; queue->tx_copy_ops[*copy_ops].dest.offset = offset_in_page(skb->data); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f948c46d5132..47f791e60851 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -291,7 +291,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) struct sk_buff *skb; unsigned short id; grant_ref_t ref; - unsigned long pfn; + unsigned long gfn; struct xen_netif_rx_request *req; skb = xennet_alloc_one_rx_buffer(queue); @@ -307,12 +307,12 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) BUG_ON((signed short)ref < 0); queue->grant_rx_ref[id] = ref; - pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); + gfn = xen_page_to_gfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); req = RING_GET_REQUEST(&queue->rx, req_prod); gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, - pfn_to_mfn(pfn), + gfn, 0); req->id = id; @@ -430,8 +430,10 @@ static struct xen_netif_tx_request *xennet_make_one_txreq( ref = gnttab_claim_grant_reference(&queue->gref_tx_head); BUG_ON((signed short)ref < 0); - gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, - page_to_mfn(page), GNTMAP_readonly); + gnttab_grant_foreign_access_ref(ref, + queue->info->xbdev->otherend_id, + xen_page_to_gfn(page), + GNTMAP_readonly); queue->tx_skbs[id].skb = skb; queue->grant_tx_page[id] = page; diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index fad22caf0eff..9dc8687bf048 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c @@ -377,7 +377,6 @@ static int map_data_for_request(struct vscsifrnt_info *info, unsigned int data_len = scsi_bufflen(sc); unsigned int data_grants = 0, seg_grants = 0; struct scatterlist *sg; - unsigned long mfn; struct scsiif_request_segment *seg; ring_req->nr_segments = 0; @@ -420,9 +419,9 @@ static int map_data_for_request(struct vscsifrnt_info *info, ref = gnttab_claim_grant_reference(&gref_head); BUG_ON(ref == -ENOSPC); - mfn = pfn_to_mfn(page_to_pfn(page)); gnttab_grant_foreign_access_ref(ref, - info->dev->otherend_id, mfn, 1); + info->dev->otherend_id, + xen_page_to_gfn(page), 1); shadow->gref[ref_cnt] = ref; ring_req->seg[ref_cnt].gref = ref; ring_req->seg[ref_cnt].offset = (uint16_t)off; @@ -454,9 +453,10 @@ static int map_data_for_request(struct vscsifrnt_info *info, ref = gnttab_claim_grant_reference(&gref_head); BUG_ON(ref == -ENOSPC); - mfn = pfn_to_mfn(page_to_pfn(page)); gnttab_grant_foreign_access_ref(ref, - info->dev->otherend_id, mfn, grant_ro); + info->dev->otherend_id, + xen_page_to_gfn(page), + grant_ro); shadow->gref[ref_cnt] = ref; seg->gref = ref; diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index a9d837f83ce8..efe5124a368d 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -265,7 +265,8 @@ static int xen_pv_console_init(void) return 0; } info->evtchn = xen_start_info->console.domU.evtchn; - info->intf = mfn_to_virt(xen_start_info->console.domU.mfn); + /* GFN == MFN for PV guest */ + info->intf = gfn_to_virt(xen_start_info->console.domU.mfn); info->vtermno = HVC_COOKIE; spin_lock(&xencons_lock); @@ -390,7 +391,7 @@ static int xencons_connect_backend(struct xenbus_device *dev, if (IS_ERR(info->hvc)) return PTR_ERR(info->hvc); if (xen_pv_domain()) - mfn = virt_to_mfn(info->intf); + mfn = virt_to_gfn(info->intf); else mfn = __pa(info->intf) >> PAGE_SHIFT; ret = gnttab_alloc_grant_references(1, &gref_head); diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc44736c1a..25e3cce0c35f 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -539,7 +539,7 @@ static int xenfb_remove(struct xenbus_device *dev) static unsigned long vmalloc_to_mfn(void *address) { - return pfn_to_mfn(vmalloc_to_pfn(address)); + return pfn_to_gfn(vmalloc_to_pfn(address)); } static void xenfb_init_shared_page(struct xenfb_info *info, @@ -586,7 +586,7 @@ static int xenfb_connect_backend(struct xenbus_device *dev, goto unbind_irq; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", - virt_to_mfn(info->page)); + virt_to_gfn(info->page)); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 1fa633b2d556..c79329fcfa78 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -441,7 +441,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) /* Update direct mapping, invalidate P2M, and add to balloon. */ for (i = 0; i < nr_pages; i++) { pfn = frame_list[i]; - frame_list[i] = pfn_to_mfn(pfn); + frame_list[i] = pfn_to_gfn(pfn); page = pfn_to_page(pfn); #ifdef CONFIG_XEN_HAVE_PVMMU diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index ed620e5857a1..c49bb7a5be8f 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1688,7 +1688,7 @@ void __init xen_init_IRQ(void) struct physdev_pirq_eoi_gmfn eoi_gmfn; pirq_eoi_map = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO); - eoi_gmfn.gmfn = virt_to_mfn(pirq_eoi_map); + eoi_gmfn.gmfn = virt_to_gfn(pirq_eoi_map); rc = HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn_v2, &eoi_gmfn); /* TODO: No PVH support for PIRQ EOI */ if (rc != 0) { diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index ed673e1acd61..1d4baf56c36b 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -111,7 +111,7 @@ static int init_control_block(int cpu, for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++) q->head[i] = 0; - init_control.control_gfn = virt_to_mfn(control_block); + init_control.control_gfn = virt_to_gfn(control_block); init_control.offset = 0; init_control.vcpu = cpu; @@ -167,7 +167,7 @@ static int evtchn_fifo_setup(struct irq_info *info) /* Mask all events in this page before adding it. */ init_array_page(array_page); - expand_array.array_gfn = virt_to_mfn(array_page); + expand_array.array_gfn = virt_to_gfn(array_page); ret = HYPERVISOR_event_channel_op(EVTCHNOP_expand_array, &expand_array); if (ret < 0) diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index e53fe191738c..14370df9ac1c 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -142,7 +142,8 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, /* Grant foreign access to the page. */ rc = gnttab_grant_foreign_access(op->domid, - pfn_to_mfn(page_to_pfn(gref->page)), readonly); + xen_page_to_gfn(gref->page), + readonly); if (rc < 0) goto undo; gref_ids[i] = gref->gref_id = rc; diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index d10effee9b9e..e12bd3635f83 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -80,7 +80,7 @@ static int xen_suspend(void *data) * is resuming in a new domain. */ si->cancelled = HYPERVISOR_suspend(xen_pv_domain() - ? virt_to_mfn(xen_start_info) + ? virt_to_gfn(xen_start_info) : 0); xen_arch_post_suspend(si->cancelled); diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 239738f944ba..28c97ff606f4 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -131,7 +131,7 @@ static int xen_tmem_new_pool(struct tmem_pool_uuid uuid, static int xen_tmem_put_page(u32 pool_id, struct tmem_oid oid, u32 index, unsigned long pfn) { - unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; + unsigned long gmfn = pfn_to_gfn(pfn); return xen_tmem_op(TMEM_PUT_PAGE, pool_id, oid, index, gmfn, 0, 0, 0); @@ -140,7 +140,7 @@ static int xen_tmem_put_page(u32 pool_id, struct tmem_oid oid, static int xen_tmem_get_page(u32 pool_id, struct tmem_oid oid, u32 index, unsigned long pfn) { - unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; + unsigned long gmfn = pfn_to_gfn(pfn); return xen_tmem_op(TMEM_GET_PAGE, pool_id, oid, index, gmfn, 0, 0, 0); diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index e30353575d5d..2ba09c1195c8 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -380,7 +380,7 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr, for (i = 0; i < nr_pages; i++) { err = gnttab_grant_foreign_access(dev->otherend_id, - virt_to_mfn(vaddr), 0); + virt_to_gfn(vaddr), 0); if (err < 0) { xenbus_dev_fatal(dev, err, "granting access to ring page"); diff --git a/drivers/xen/xenbus/xenbus_dev_backend.c b/drivers/xen/xenbus/xenbus_dev_backend.c index b17707ee07d4..ee6d9efd7b76 100644 --- a/drivers/xen/xenbus/xenbus_dev_backend.c +++ b/drivers/xen/xenbus/xenbus_dev_backend.c @@ -49,7 +49,7 @@ static long xenbus_alloc(domid_t domid) goto out_err; gnttab_grant_foreign_access_ref(GNTTAB_RESERVED_XENSTORE, domid, - virt_to_mfn(xen_store_interface), 0 /* writable */); + virt_to_gfn(xen_store_interface), 0 /* writable */); arg.dom = DOMID_SELF; arg.remote_dom = domid; diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 4308fb3cf7c2..b3870f4ca1d0 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -711,9 +711,7 @@ static int __init xenstored_local_init(void) if (!page) goto out_err; - xen_store_mfn = xen_start_info->store_mfn = - pfn_to_mfn(virt_to_phys((void *)page) >> - PAGE_SHIFT); + xen_store_mfn = xen_start_info->store_mfn = virt_to_gfn((void *)page); /* Next allocate a local port which xenstored can bind to */ alloc_unbound.dom = DOMID_SELF; @@ -787,12 +785,12 @@ static int __init xenbus_init(void) err = xenstored_local_init(); if (err) goto out_error; - xen_store_interface = mfn_to_virt(xen_store_mfn); + xen_store_interface = gfn_to_virt(xen_store_mfn); break; case XS_PV: xen_store_evtchn = xen_start_info->store_evtchn; xen_store_mfn = xen_start_info->store_mfn; - xen_store_interface = mfn_to_virt(xen_store_mfn); + xen_store_interface = gfn_to_virt(xen_store_mfn); break; case XS_HVM: err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); diff --git a/include/xen/page.h b/include/xen/page.h index a5983da2f5cd..1daae485e336 100644 --- a/include/xen/page.h +++ b/include/xen/page.h @@ -3,9 +3,9 @@ #include -static inline unsigned long page_to_mfn(struct page *page) +static inline unsigned long xen_page_to_gfn(struct page *page) { - return pfn_to_mfn(page_to_pfn(page)); + return pfn_to_gfn(page_to_pfn(page)); } struct xen_memory_region { -- cgit v1.2.3 From c5c18a06af753eab1162fcdfb1cf03581e70b3f4 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Sat, 12 Sep 2015 11:08:34 -0700 Subject: Input: ad714x - convert to using managed resources Use managed resource functions devm_request_threaded_irq, devm_inpute_allocate_device and devm_kzalloc to simplify error handling. Also, remove use of input_unregister_device as input_register_device itself handles it and works as resource managed function. To be compatible with the change, various gotos are replaced with direct returns, and unneeded labels are dropped. With these changes remove ad714x_remove and corresponding calls of it as they are now redundant. Signed-off-by: Vaishali Thakkar Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ad714x-i2c.c | 10 -- drivers/input/misc/ad714x-spi.c | 10 -- drivers/input/misc/ad714x.c | 214 +++++++++++++++------------------------- drivers/input/misc/ad714x.h | 1 - 4 files changed, 82 insertions(+), 153 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 189bdc8e91a5..2f047738bc0b 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -85,15 +85,6 @@ static int ad714x_i2c_probe(struct i2c_client *client, return 0; } -static int ad714x_i2c_remove(struct i2c_client *client) -{ - struct ad714x_chip *chip = i2c_get_clientdata(client); - - ad714x_remove(chip); - - return 0; -} - static const struct i2c_device_id ad714x_id[] = { { "ad7142_captouch", 0 }, { "ad7143_captouch", 0 }, @@ -110,7 +101,6 @@ static struct i2c_driver ad714x_i2c_driver = { .pm = &ad714x_i2c_pm, }, .probe = ad714x_i2c_probe, - .remove = ad714x_i2c_remove, .id_table = ad714x_id, }; diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index a79e50b58bf5..c8170f082962 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c @@ -101,15 +101,6 @@ static int ad714x_spi_probe(struct spi_device *spi) return 0; } -static int ad714x_spi_remove(struct spi_device *spi) -{ - struct ad714x_chip *chip = spi_get_drvdata(spi); - - ad714x_remove(chip); - - return 0; -} - static struct spi_driver ad714x_spi_driver = { .driver = { .name = "ad714x_captouch", @@ -117,7 +108,6 @@ static struct spi_driver ad714x_spi_driver = { .pm = &ad714x_spi_pm, }, .probe = ad714x_spi_probe, - .remove = ad714x_spi_remove, }; module_spi_driver(ad714x_spi_driver); diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 7a61e9ee682c..84b51dd51f6e 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -960,13 +960,12 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data) return IRQ_HANDLED; } -#define MAX_DEVICE_NUM 8 struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, ad714x_read_t read, ad714x_write_t write) { - int i, alloc_idx; + int i; int error; - struct input_dev *input[MAX_DEVICE_NUM]; + struct input_dev *input; struct ad714x_platform_data *plat_data = dev_get_platdata(dev); struct ad714x_chip *ad714x; @@ -982,25 +981,25 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, if (irq <= 0) { dev_err(dev, "IRQ not configured!\n"); error = -EINVAL; - goto err_out; + return ERR_PTR(error); } if (dev_get_platdata(dev) == NULL) { dev_err(dev, "platform data for ad714x doesn't exist\n"); error = -EINVAL; - goto err_out; + return ERR_PTR(error); } - ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) + - sizeof(*sd_drv) * plat_data->slider_num + - sizeof(*wl_drv) * plat_data->wheel_num + - sizeof(*tp_drv) * plat_data->touchpad_num + - sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL); + ad714x = devm_kzalloc(dev, sizeof(*ad714x) + sizeof(*ad714x->sw) + + sizeof(*sd_drv) * plat_data->slider_num + + sizeof(*wl_drv) * plat_data->wheel_num + + sizeof(*tp_drv) * plat_data->touchpad_num + + sizeof(*bt_drv) * plat_data->button_num, + GFP_KERNEL); if (!ad714x) { error = -ENOMEM; - goto err_out; + return ERR_PTR(error); } - ad714x->hw = plat_data; drv_mem = ad714x + 1; @@ -1022,47 +1021,40 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, error = ad714x_hw_detect(ad714x); if (error) - goto err_free_mem; + return ERR_PTR(error); /* initialize and request sw/hw resources */ ad714x_hw_init(ad714x); mutex_init(&ad714x->mutex); - /* - * Allocate and register AD714X input device - */ - alloc_idx = 0; - /* a slider uses one input_dev instance */ if (ad714x->hw->slider_num > 0) { struct ad714x_slider_plat *sd_plat = ad714x->hw->slider; for (i = 0; i < ad714x->hw->slider_num; i++) { - sd_drv[i].input = input[alloc_idx] = input_allocate_device(); - if (!input[alloc_idx]) { - error = -ENOMEM; - goto err_free_dev; - } - - __set_bit(EV_ABS, input[alloc_idx]->evbit); - __set_bit(EV_KEY, input[alloc_idx]->evbit); - __set_bit(ABS_X, input[alloc_idx]->absbit); - __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); - input_set_abs_params(input[alloc_idx], + input = devm_input_allocate_device(dev); + if (!input) + return ERR_PTR(-ENOMEM); + + __set_bit(EV_ABS, input->evbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(ABS_X, input->absbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_X, 0, sd_plat->max_coord, 0, 0); - input[alloc_idx]->id.bustype = bus_type; - input[alloc_idx]->id.product = ad714x->product; - input[alloc_idx]->id.version = ad714x->version; - input[alloc_idx]->name = "ad714x_captouch_slider"; - input[alloc_idx]->dev.parent = dev; + input->id.bustype = bus_type; + input->id.product = ad714x->product; + input->id.version = ad714x->version; + input->name = "ad714x_captouch_slider"; + input->dev.parent = dev; - error = input_register_device(input[alloc_idx]); + error = input_register_device(input); if (error) - goto err_free_dev; + return ERR_PTR(error); - alloc_idx++; + sd_drv[i].input = input; } } @@ -1071,30 +1063,28 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel; for (i = 0; i < ad714x->hw->wheel_num; i++) { - wl_drv[i].input = input[alloc_idx] = input_allocate_device(); - if (!input[alloc_idx]) { - error = -ENOMEM; - goto err_free_dev; - } - - __set_bit(EV_KEY, input[alloc_idx]->evbit); - __set_bit(EV_ABS, input[alloc_idx]->evbit); - __set_bit(ABS_WHEEL, input[alloc_idx]->absbit); - __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); - input_set_abs_params(input[alloc_idx], + input = devm_input_allocate_device(dev); + if (!input) + return ERR_PTR(-ENOMEM); + + __set_bit(EV_KEY, input->evbit); + __set_bit(EV_ABS, input->evbit); + __set_bit(ABS_WHEEL, input->absbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_WHEEL, 0, wl_plat->max_coord, 0, 0); - input[alloc_idx]->id.bustype = bus_type; - input[alloc_idx]->id.product = ad714x->product; - input[alloc_idx]->id.version = ad714x->version; - input[alloc_idx]->name = "ad714x_captouch_wheel"; - input[alloc_idx]->dev.parent = dev; + input->id.bustype = bus_type; + input->id.product = ad714x->product; + input->id.version = ad714x->version; + input->name = "ad714x_captouch_wheel"; + input->dev.parent = dev; - error = input_register_device(input[alloc_idx]); + error = input_register_device(input); if (error) - goto err_free_dev; + return ERR_PTR(error); - alloc_idx++; + wl_drv[i].input = input; } } @@ -1103,33 +1093,31 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad; for (i = 0; i < ad714x->hw->touchpad_num; i++) { - tp_drv[i].input = input[alloc_idx] = input_allocate_device(); - if (!input[alloc_idx]) { - error = -ENOMEM; - goto err_free_dev; - } - - __set_bit(EV_ABS, input[alloc_idx]->evbit); - __set_bit(EV_KEY, input[alloc_idx]->evbit); - __set_bit(ABS_X, input[alloc_idx]->absbit); - __set_bit(ABS_Y, input[alloc_idx]->absbit); - __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); - input_set_abs_params(input[alloc_idx], + input = devm_input_allocate_device(dev); + if (!input) + return ERR_PTR(-ENOMEM); + + __set_bit(EV_ABS, input->evbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(ABS_X, input->absbit); + __set_bit(ABS_Y, input->absbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_X, 0, tp_plat->x_max_coord, 0, 0); - input_set_abs_params(input[alloc_idx], + input_set_abs_params(input, ABS_Y, 0, tp_plat->y_max_coord, 0, 0); - input[alloc_idx]->id.bustype = bus_type; - input[alloc_idx]->id.product = ad714x->product; - input[alloc_idx]->id.version = ad714x->version; - input[alloc_idx]->name = "ad714x_captouch_pad"; - input[alloc_idx]->dev.parent = dev; + input->id.bustype = bus_type; + input->id.product = ad714x->product; + input->id.version = ad714x->version; + input->name = "ad714x_captouch_pad"; + input->dev.parent = dev; - error = input_register_device(input[alloc_idx]); + error = input_register_device(input); if (error) - goto err_free_dev; + return ERR_PTR(error); - alloc_idx++; + tp_drv[i].input = input; } } @@ -1137,82 +1125,44 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, if (ad714x->hw->button_num > 0) { struct ad714x_button_plat *bt_plat = ad714x->hw->button; - input[alloc_idx] = input_allocate_device(); - if (!input[alloc_idx]) { + input = devm_input_allocate_device(dev); + if (!input) { error = -ENOMEM; - goto err_free_dev; + return ERR_PTR(error); } - __set_bit(EV_KEY, input[alloc_idx]->evbit); + __set_bit(EV_KEY, input->evbit); for (i = 0; i < ad714x->hw->button_num; i++) { - bt_drv[i].input = input[alloc_idx]; - __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit); + bt_drv[i].input = input; + __set_bit(bt_plat[i].keycode, input->keybit); } - input[alloc_idx]->id.bustype = bus_type; - input[alloc_idx]->id.product = ad714x->product; - input[alloc_idx]->id.version = ad714x->version; - input[alloc_idx]->name = "ad714x_captouch_button"; - input[alloc_idx]->dev.parent = dev; + input->id.bustype = bus_type; + input->id.product = ad714x->product; + input->id.version = ad714x->version; + input->name = "ad714x_captouch_button"; + input->dev.parent = dev; - error = input_register_device(input[alloc_idx]); + error = input_register_device(input); if (error) - goto err_free_dev; - - alloc_idx++; + return ERR_PTR(error); } irqflags = plat_data->irqflags ?: IRQF_TRIGGER_FALLING; irqflags |= IRQF_ONESHOT; - error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread, - irqflags, "ad714x_captouch", ad714x); + error = devm_request_threaded_irq(dev, ad714x->irq, NULL, + ad714x_interrupt_thread, + irqflags, "ad714x_captouch", ad714x); if (error) { dev_err(dev, "can't allocate irq %d\n", ad714x->irq); - goto err_unreg_dev; + return ERR_PTR(error); } return ad714x; - - err_free_dev: - dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx); - input_free_device(input[alloc_idx]); - err_unreg_dev: - while (--alloc_idx >= 0) - input_unregister_device(input[alloc_idx]); - err_free_mem: - kfree(ad714x); - err_out: - return ERR_PTR(error); } EXPORT_SYMBOL(ad714x_probe); -void ad714x_remove(struct ad714x_chip *ad714x) -{ - struct ad714x_platform_data *hw = ad714x->hw; - struct ad714x_driver_data *sw = ad714x->sw; - int i; - - free_irq(ad714x->irq, ad714x); - - /* unregister and free all input devices */ - - for (i = 0; i < hw->slider_num; i++) - input_unregister_device(sw->slider[i].input); - - for (i = 0; i < hw->wheel_num; i++) - input_unregister_device(sw->wheel[i].input); - - for (i = 0; i < hw->touchpad_num; i++) - input_unregister_device(sw->touchpad[i].input); - - if (hw->button_num) - input_unregister_device(sw->button[0].input); - - kfree(ad714x); -} -EXPORT_SYMBOL(ad714x_remove); - #ifdef CONFIG_PM int ad714x_disable(struct ad714x_chip *ad714x) { diff --git a/drivers/input/misc/ad714x.h b/drivers/input/misc/ad714x.h index 3c85455aa66d..5d65d303b9bf 100644 --- a/drivers/input/misc/ad714x.h +++ b/drivers/input/misc/ad714x.h @@ -50,6 +50,5 @@ int ad714x_disable(struct ad714x_chip *ad714x); int ad714x_enable(struct ad714x_chip *ad714x); struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, ad714x_read_t read, ad714x_write_t write); -void ad714x_remove(struct ad714x_chip *ad714x); #endif -- cgit v1.2.3 From 13c23cd18bd12ddbf00beddd136e3cd33b4f2dfa Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Fri, 11 Sep 2015 17:30:34 -0700 Subject: Input: edt-ft5x06 - switch to newer gpio framework The current/old gpio framework used doesn't properly listen to ACTIVE_LOW and ACTIVE_HIGH flags. The newer gpio framework takes into account these flags when setting gpio values. Since the values being output were based on voltage and not logic they change to reflect this difference. Also use gpiod_set_value_cansleep since wake and reset pins can be provided by bus based io expanders. Switch from msleep(5) to udelay_range(5000,6000) to avoid check patch warning. Signed-off-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/edt-ft5x06.txt | 4 +- drivers/input/touchscreen/edt-ft5x06.c | 129 ++++++--------------- include/linux/input/edt-ft5x06.h | 3 - 3 files changed, 40 insertions(+), 96 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index 76db96704a60..9330d4d34cb9 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -50,6 +50,6 @@ Example: pinctrl-0 = <&edt_ft5x06_pins>; interrupt-parent = <&gpio2>; interrupts = <5 0>; - reset-gpios = <&gpio2 6 1>; - wake-gpios = <&gpio4 9 0>; + reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>; }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 48de1e8b3c93..5738722873bb 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -34,8 +34,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -91,9 +90,9 @@ struct edt_ft5x06_ts_data { u16 num_x; u16 num_y; - int reset_pin; - int irq_pin; - int wake_pin; + struct gpio_desc *reset_gpio; + struct gpio_desc *wake_gpio; + struct gpio_desc *irq_gpio; #if defined(CONFIG_DEBUG_FS) struct dentry *debug_dir; @@ -752,45 +751,6 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) #endif /* CONFIG_DEBUGFS */ -static int edt_ft5x06_ts_reset(struct i2c_client *client, - struct edt_ft5x06_ts_data *tsdata) -{ - int error; - - if (gpio_is_valid(tsdata->wake_pin)) { - error = devm_gpio_request_one(&client->dev, - tsdata->wake_pin, GPIOF_OUT_INIT_LOW, - "edt-ft5x06 wake"); - if (error) { - dev_err(&client->dev, - "Failed to request GPIO %d as wake pin, error %d\n", - tsdata->wake_pin, error); - return error; - } - - msleep(5); - gpio_set_value(tsdata->wake_pin, 1); - } - if (gpio_is_valid(tsdata->reset_pin)) { - /* this pulls reset down, enabling the low active reset */ - error = devm_gpio_request_one(&client->dev, - tsdata->reset_pin, GPIOF_OUT_INIT_LOW, - "edt-ft5x06 reset"); - if (error) { - dev_err(&client->dev, - "Failed to request GPIO %d as reset pin, error %d\n", - tsdata->reset_pin, error); - return error; - } - - msleep(5); - gpio_set_value(tsdata->reset_pin, 1); - msleep(300); - } - - return 0; -} - static int edt_ft5x06_ts_identify(struct i2c_client *client, struct edt_ft5x06_ts_data *tsdata, char *fw_version) @@ -931,30 +891,6 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) } } -#ifdef CONFIG_OF -static int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, - struct edt_ft5x06_ts_data *tsdata) -{ - struct device_node *np = dev->of_node; - - /* - * irq_pin is not needed for DT setup. - * irq is associated via 'interrupts' property in DT - */ - tsdata->irq_pin = -EINVAL; - tsdata->reset_pin = of_get_named_gpio(np, "reset-gpios", 0); - tsdata->wake_pin = of_get_named_gpio(np, "wake-gpios", 0); - - return 0; -} -#else -static inline int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, - struct edt_ft5x06_ts_data *tsdata) -{ - return -ENODEV; -} -#endif - static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -973,32 +909,42 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return -ENOMEM; } - if (!pdata) { - error = edt_ft5x06_i2c_ts_probe_dt(&client->dev, tsdata); - if (error) { - dev_err(&client->dev, - "DT probe failed and no platform data present\n"); - return error; - } - } else { - tsdata->reset_pin = pdata->reset_pin; - tsdata->irq_pin = pdata->irq_pin; - tsdata->wake_pin = -EINVAL; + tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev, + "reset", GPIOD_OUT_HIGH); + if (IS_ERR(tsdata->reset_gpio)) { + error = PTR_ERR(tsdata->reset_gpio); + dev_err(&client->dev, + "Failed to request GPIO reset pin, error %d\n", error); + return error; } - error = edt_ft5x06_ts_reset(client, tsdata); - if (error) + tsdata->wake_gpio = devm_gpiod_get_optional(&client->dev, + "wake", GPIOD_OUT_LOW); + if (IS_ERR(tsdata->wake_gpio)) { + error = PTR_ERR(tsdata->wake_gpio); + dev_err(&client->dev, + "Failed to request GPIO wake pin, error %d\n", error); return error; + } - if (gpio_is_valid(tsdata->irq_pin)) { - error = devm_gpio_request_one(&client->dev, tsdata->irq_pin, - GPIOF_IN, "edt-ft5x06 irq"); - if (error) { - dev_err(&client->dev, - "Failed to request GPIO %d, error %d\n", - tsdata->irq_pin, error); - return error; - } + tsdata->irq_gpio = devm_gpiod_get_optional(&client->dev, + "irq", GPIOD_IN); + if (IS_ERR(tsdata->irq_gpio)) { + error = PTR_ERR(tsdata->irq_gpio); + dev_err(&client->dev, + "Failed to request GPIO irq pin, error %d\n", error); + return error; + } + + if (tsdata->wake_gpio) { + usleep_range(5000, 6000); + gpiod_set_value_cansleep(tsdata->wake_gpio, 1); + } + + if (tsdata->reset_gpio) { + usleep_range(5000, 6000); + gpiod_set_value_cansleep(tsdata->reset_gpio, 0); + msleep(300); } input = devm_input_allocate_device(&client->dev); @@ -1074,7 +1020,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, dev_dbg(&client->dev, "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n", - client->irq, tsdata->wake_pin, tsdata->reset_pin); + client->irq, desc_to_gpio(tsdata->wake_gpio), + desc_to_gpio(tsdata->reset_gpio)); return 0; diff --git a/include/linux/input/edt-ft5x06.h b/include/linux/input/edt-ft5x06.h index 8a1e0d1a0124..5ca5b4cc308c 100644 --- a/include/linux/input/edt-ft5x06.h +++ b/include/linux/input/edt-ft5x06.h @@ -10,9 +10,6 @@ */ struct edt_ft5x06_platform_data { - int irq_pin; - int reset_pin; - /* startup defaults for operational parameters */ bool use_parameters; u8 gain; -- cgit v1.2.3 From 079128eba8075daff59390c14ce2d2a2e9a1f3a1 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 12 Sep 2015 09:17:47 -0700 Subject: Input: edt-ft5x06 - drop parsing of irq gpio The driver does not use irq gpio as gpio, but rather relies on I2C core or board code to set up client's structure IRQ line, so let's stop trying to locate the resource and parse it. Tested-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 5738722873bb..df76f19673e8 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -92,7 +92,6 @@ struct edt_ft5x06_ts_data { struct gpio_desc *reset_gpio; struct gpio_desc *wake_gpio; - struct gpio_desc *irq_gpio; #if defined(CONFIG_DEBUG_FS) struct dentry *debug_dir; @@ -927,15 +926,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } - tsdata->irq_gpio = devm_gpiod_get_optional(&client->dev, - "irq", GPIOD_IN); - if (IS_ERR(tsdata->irq_gpio)) { - error = PTR_ERR(tsdata->irq_gpio); - dev_err(&client->dev, - "Failed to request GPIO irq pin, error %d\n", error); - return error; - } - if (tsdata->wake_gpio) { usleep_range(5000, 6000); gpiod_set_value_cansleep(tsdata->wake_gpio, 1); -- cgit v1.2.3 From 22ddbacc4bb54ef8577c46114227c06c31e3c47d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 12 Sep 2015 09:37:03 -0700 Subject: Input: edt-ft5x06 - remove support for platform data We do not have any users of platform data in the tree and all newer platforms are either DT or ACPI, so let's drop handling of platform data. Tested-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 41 ++++------------------------------ include/linux/input/edt-ft5x06.h | 21 ----------------- 2 files changed, 4 insertions(+), 58 deletions(-) delete mode 100644 include/linux/input/edt-ft5x06.h (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index df76f19673e8..134c66c431b8 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -37,7 +37,6 @@ #include #include #include -#include #define MAX_SUPPORT_POINTS 5 @@ -809,21 +808,14 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, return 0; } -#define EDT_ATTR_CHECKSET(name, reg) \ -do { \ - if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \ - pdata->name <= edt_ft5x06_attr_##name.limit_high) \ - edt_ft5x06_register_write(tsdata, reg, pdata->name); \ -} while (0) - #define EDT_GET_PROP(name, reg) { \ u32 val; \ if (of_property_read_u32(np, #name, &val) == 0) \ edt_ft5x06_register_write(tsdata, reg, val); \ } -static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np, - struct edt_ft5x06_ts_data *tsdata) +static void edt_ft5x06_ts_get_defaults(struct device_node *np, + struct edt_ft5x06_ts_data *tsdata) { struct edt_reg_addr *reg_addr = &tsdata->reg_addr; @@ -832,23 +824,6 @@ static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np, EDT_GET_PROP(offset, reg_addr->reg_offset); } -static void -edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, - const struct edt_ft5x06_platform_data *pdata) -{ - struct edt_reg_addr *reg_addr = &tsdata->reg_addr; - - if (!pdata->use_parameters) - return; - - /* pick up defaults from the platform data */ - EDT_ATTR_CHECKSET(threshold, reg_addr->reg_threshold); - EDT_ATTR_CHECKSET(gain, reg_addr->reg_gain); - EDT_ATTR_CHECKSET(offset, reg_addr->reg_offset); - if (reg_addr->reg_report_rate != NO_REGISTER) - EDT_ATTR_CHECKSET(report_rate, reg_addr->reg_report_rate); -} - static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) { @@ -893,8 +868,6 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct edt_ft5x06_platform_data *pdata = - dev_get_platdata(&client->dev); struct edt_ft5x06_ts_data *tsdata; struct input_dev *input; int error; @@ -955,12 +928,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, } edt_ft5x06_ts_set_regs(tsdata); - - if (!pdata) - edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata); - else - edt_ft5x06_ts_get_defaults(tsdata, pdata); - + edt_ft5x06_ts_get_defaults(client->dev.of_node, tsdata); edt_ft5x06_ts_get_parameters(tsdata); dev_dbg(&client->dev, @@ -976,8 +944,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, input_set_abs_params(input, ABS_MT_POSITION_Y, 0, tsdata->num_y * 64 - 1, 0, 0); - if (!pdata) - touchscreen_parse_properties(input, true); + touchscreen_parse_properties(input, true); error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, INPUT_MT_DIRECT); if (error) { diff --git a/include/linux/input/edt-ft5x06.h b/include/linux/input/edt-ft5x06.h deleted file mode 100644 index 5ca5b4cc308c..000000000000 --- a/include/linux/input/edt-ft5x06.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _EDT_FT5X06_H -#define _EDT_FT5X06_H - -/* - * Copyright (c) 2012 Simon Budig, - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -struct edt_ft5x06_platform_data { - /* startup defaults for operational parameters */ - bool use_parameters; - u8 gain; - u8 threshold; - u8 offset; - u8 report_rate; -}; - -#endif /* _EDT_FT5X06_H */ -- cgit v1.2.3 From 2e23b7a96372f855d4a006e82b183915e249e2ac Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 12 Sep 2015 09:54:15 -0700 Subject: Input: edt-ft5x06 - use generic properties API Instead of only parsing device tree properties let's switch to using generic properties API so that the driver can also work on other platforms. Tested-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 134c66c431b8..ef8a7cddb017 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -808,20 +808,24 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, return 0; } -#define EDT_GET_PROP(name, reg) { \ - u32 val; \ - if (of_property_read_u32(np, #name, &val) == 0) \ - edt_ft5x06_register_write(tsdata, reg, val); \ -} - -static void edt_ft5x06_ts_get_defaults(struct device_node *np, +static void edt_ft5x06_ts_get_defaults(struct device *dev, struct edt_ft5x06_ts_data *tsdata) { struct edt_reg_addr *reg_addr = &tsdata->reg_addr; + u32 val; + int error; + + error = device_property_read_u32(dev, "threshold", &val); + if (!error) + reg_addr->reg_threshold = val; + + error = device_property_read_u32(dev, "gain", &val); + if (!error) + reg_addr->reg_gain = val; - EDT_GET_PROP(threshold, reg_addr->reg_threshold); - EDT_GET_PROP(gain, reg_addr->reg_gain); - EDT_GET_PROP(offset, reg_addr->reg_offset); + error = device_property_read_u32(dev, "offset", &val); + if (!error) + reg_addr->reg_offset = val; } static void @@ -928,7 +932,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, } edt_ft5x06_ts_set_regs(tsdata); - edt_ft5x06_ts_get_defaults(client->dev.of_node, tsdata); + edt_ft5x06_ts_get_defaults(&client->dev, tsdata); edt_ft5x06_ts_get_parameters(tsdata); dev_dbg(&client->dev, -- cgit v1.2.3 From f0bef75c593391198f2c9f855aae8e994a0e9293 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 12 Sep 2015 10:11:09 -0700 Subject: Input: edt-ft5x06 - do not hardcode interrupt trigger type Instead of hardcoding IRQ trigger type to IRQF_TRIGGER_FALLING, let's respect settings specified in device tree. To be compatible with older DTSes, if trigger type is not set up in DTS we'll set it to default (falling edge). Tested-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/touchscreen/edt-ft5x06.txt | 2 +- drivers/input/touchscreen/edt-ft5x06.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index 9330d4d34cb9..bedd7ddc56aa 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -49,7 +49,7 @@ Example: pinctrl-names = "default"; pinctrl-0 = <&edt_ft5x06_pins>; interrupt-parent = <&gpio2>; - interrupts = <5 0>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>; wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>; }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index ef8a7cddb017..7239c314c9e9 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -874,6 +875,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, { struct edt_ft5x06_ts_data *tsdata; struct input_dev *input; + unsigned long irq_flags; int error; char fw_version[EDT_NAME_LEN]; @@ -959,9 +961,13 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, input_set_drvdata(input, tsdata); i2c_set_clientdata(client, tsdata); - error = devm_request_threaded_irq(&client->dev, client->irq, NULL, - edt_ft5x06_ts_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + irq_flags = irq_get_trigger_type(client->irq); + if (irq_flags == IRQF_TRIGGER_NONE) + irq_flags = IRQF_TRIGGER_FALLING; + irq_flags |= IRQF_ONESHOT; + + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, edt_ft5x06_ts_isr, irq_flags, client->name, tsdata); if (error) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); -- cgit v1.2.3 From 2260c419b52bd71166aa96fac9081388f76df5e0 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 28 Sep 2015 16:09:51 -0700 Subject: Input: db9 - use parallel port device model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modify db9 driver to use the new Parallel Port device model. Signed-off-by: Sudip Mukherjee Tested-By: Pali Rohár Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/db9.c | 110 ++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 54 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 8e7de5c7754f..cf1f602e0f0a 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -48,7 +48,7 @@ struct db9_config { }; #define DB9_MAX_PORTS 3 -static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata; +static struct db9_config db9_cfg[DB9_MAX_PORTS]; module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0); MODULE_PARM_DESC(dev, "Describes first attached device (,)"); @@ -106,6 +106,7 @@ struct db9 { struct pardevice *pd; int mode; int used; + int parportno; struct mutex mutex; char phys[DB9_MAX_DEVICES][32]; }; @@ -553,54 +554,60 @@ static void db9_close(struct input_dev *dev) mutex_unlock(&db9->mutex); } -static struct db9 __init *db9_probe(int parport, int mode) +static void db9_attach(struct parport *pp) { struct db9 *db9; const struct db9_mode_data *db9_mode; - struct parport *pp; struct pardevice *pd; struct input_dev *input_dev; int i, j; - int err; + int mode; + struct pardev_cb db9_parport_cb; + + for (i = 0; i < DB9_MAX_PORTS; i++) { + if (db9_cfg[i].nargs == 0 || + db9_cfg[i].args[DB9_ARG_PARPORT] < 0) + continue; + + if (db9_cfg[i].args[DB9_ARG_PARPORT] == pp->number) + break; + } + + if (i == DB9_MAX_PORTS) { + pr_debug("Not using parport%d.\n", pp->number); + return; + } + + mode = db9_cfg[i].args[DB9_ARG_MODE]; if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) { printk(KERN_ERR "db9.c: Bad device type %d\n", mode); - err = -EINVAL; - goto err_out; + return; } db9_mode = &db9_modes[mode]; - pp = parport_find_number(parport); - if (!pp) { - printk(KERN_ERR "db9.c: no such parport\n"); - err = -ENODEV; - goto err_out; - } - if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) { printk(KERN_ERR "db9.c: specified parport is not bidirectional\n"); - err = -EINVAL; - goto err_put_pp; + return; } - pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + db9_parport_cb.flags = PARPORT_FLAG_EXCL; + + pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, i); if (!pd) { printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n"); - err = -EBUSY; - goto err_put_pp; + return; } db9 = kzalloc(sizeof(struct db9), GFP_KERNEL); - if (!db9) { - printk(KERN_ERR "db9.c: Not enough memory\n"); - err = -ENOMEM; + if (!db9) goto err_unreg_pardev; - } mutex_init(&db9->mutex); db9->pd = pd; db9->mode = mode; + db9->parportno = pp->number; init_timer(&db9->timer); db9->timer.data = (long) db9; db9->timer.function = db9_timer; @@ -610,7 +617,6 @@ static struct db9 __init *db9_probe(int parport, int mode) db9->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "db9.c: Not enough memory for input device\n"); - err = -ENOMEM; goto err_unreg_devs; } @@ -639,13 +645,12 @@ static struct db9 __init *db9_probe(int parport, int mode) input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0); } - err = input_register_device(input_dev); - if (err) + if (input_register_device(input_dev)) goto err_free_dev; } - parport_put_port(pp); - return db9; + db9_base[i] = db9; + return; err_free_dev: input_free_device(db9->dev[i]); @@ -655,15 +660,22 @@ static struct db9 __init *db9_probe(int parport, int mode) kfree(db9); err_unreg_pardev: parport_unregister_device(pd); - err_put_pp: - parport_put_port(pp); - err_out: - return ERR_PTR(err); } -static void db9_remove(struct db9 *db9) +static void db9_detach(struct parport *port) { int i; + struct db9 *db9; + + for (i = 0; i < DB9_MAX_PORTS; i++) { + if (db9_base[i] && db9_base[i]->parportno == port->number) + break; + } + + if (i == DB9_MAX_PORTS) + return; + + db9 = db9_base[i]; for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++) input_unregister_device(db9->dev[i]); @@ -671,11 +683,17 @@ static void db9_remove(struct db9 *db9) kfree(db9); } +static struct parport_driver db9_parport_driver = { + .name = "db9", + .match_port = db9_attach, + .detach = db9_detach, + .devmodel = true, +}; + static int __init db9_init(void) { int i; int have_dev = 0; - int err = 0; for (i = 0; i < DB9_MAX_PORTS; i++) { if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0) @@ -683,37 +701,21 @@ static int __init db9_init(void) if (db9_cfg[i].nargs < 2) { printk(KERN_ERR "db9.c: Device type must be specified.\n"); - err = -EINVAL; - break; - } - - db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT], - db9_cfg[i].args[DB9_ARG_MODE]); - if (IS_ERR(db9_base[i])) { - err = PTR_ERR(db9_base[i]); - break; + return -EINVAL; } have_dev = 1; } - if (err) { - while (--i >= 0) - if (db9_base[i]) - db9_remove(db9_base[i]); - return err; - } + if (!have_dev) + return -ENODEV; - return have_dev ? 0 : -ENODEV; + return parport_register_driver(&db9_parport_driver); } static void __exit db9_exit(void) { - int i; - - for (i = 0; i < DB9_MAX_PORTS; i++) - if (db9_base[i]) - db9_remove(db9_base[i]); + parport_unregister_driver(&db9_parport_driver); } module_init(db9_init); -- cgit v1.2.3 From b83b14598ffbb59bc96dbd3d4350a3b8f0287bb2 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 28 Sep 2015 15:59:22 -0700 Subject: Input: omap4-keypad - fix memory leak If omap4_keypad_parse_dt() fails we returned the error code but we missed releasing keypad_data. Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap4-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index b052afec9a11..6639b2b8528a 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -266,7 +266,7 @@ static int omap4_keypad_probe(struct platform_device *pdev) error = omap4_keypad_parse_dt(&pdev->dev, keypad_data); if (error) - return error; + goto err_free_keypad; res = request_mem_region(res->start, resource_size(res), pdev->name); if (!res) { -- cgit v1.2.3 From 379d7cfa9bcae3b89299fdcb135ec0e2810e97bc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Sep 2015 16:02:29 -0700 Subject: Input: ff-core - silence an underflow warning My static checker complains that "value" comes from the user in evdev_do_ioctl() and we check that it's not too large here but we don't check that it's negative. It's harmless because the ->set_gain() and ->set_autocenter() functions truncate it to a valid u16 value, but we may as well fix it just to make the static checker happy. Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/ff-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index c64208267198..eab56c0aacd5 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -273,14 +273,14 @@ int input_ff_event(struct input_dev *dev, unsigned int type, switch (code) { case FF_GAIN: - if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff) + if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU) break; ff->set_gain(dev, value); break; case FF_AUTOCENTER: - if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff) + if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU) break; ff->set_autocenter(dev, value); -- cgit v1.2.3 From a517e87c3dfccc8b7a655e6208829ad7b04e16df Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 29 Sep 2015 16:03:43 -0700 Subject: Input: gamecon - use parallel port device model Modify gamecon driver to use the new Parallel Port device model. Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 100 +++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 47 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index e68e49786483..394ccbeb957c 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -53,7 +53,7 @@ struct gc_config { unsigned int nargs; }; -static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata; +static struct gc_config gc_cfg[GC_MAX_PORTS]; module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0); MODULE_PARM_DESC(map, "Describes first set of devices (,,,..)"); @@ -92,6 +92,7 @@ struct gc { struct timer_list timer; int pad_count[GC_MAX]; int used; + int parportno; struct mutex mutex; }; @@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data, return 0; } -static int __init gc_n64_init_ff(struct input_dev *dev, int i) +static int gc_n64_init_ff(struct input_dev *dev, int i) { struct gc_subdev *sdev; int err; @@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev) mutex_unlock(&gc->mutex); } -static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) +static int gc_setup_pad(struct gc *gc, int idx, int pad_type) { struct gc_pad *pad = &gc->pads[idx]; struct input_dev *input_dev; @@ -926,46 +927,54 @@ err_free_dev: return err; } -static struct gc __init *gc_probe(int parport, int *pads, int n_pads) +static void gc_attach(struct parport *pp) { struct gc *gc; - struct parport *pp; struct pardevice *pd; int i; int count = 0; - int err; + int *pads, n_pads; + struct pardev_cb gc_parport_cb; + + for (i = 0; i < GC_MAX_PORTS; i++) { + if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) + continue; + + if (gc_cfg[i].args[0] == pp->number) + break; + } - pp = parport_find_number(parport); - if (!pp) { - pr_err("no such parport %d\n", parport); - err = -EINVAL; - goto err_out; + if (i == GC_MAX_PORTS) { + pr_debug("Not using parport%d.\n", pp->number); + return; } + pads = gc_cfg[i].args + 1; + n_pads = gc_cfg[i].nargs - 1; + + gc_parport_cb.flags = PARPORT_FLAG_EXCL; - pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, i); if (!pd) { pr_err("parport busy already - lp.o loaded?\n"); - err = -EBUSY; - goto err_put_pp; + return; } gc = kzalloc(sizeof(struct gc), GFP_KERNEL); if (!gc) { pr_err("Not enough memory\n"); - err = -ENOMEM; goto err_unreg_pardev; } mutex_init(&gc->mutex); gc->pd = pd; + gc->parportno = pp->number; setup_timer(&gc->timer, gc_timer, (long) gc); for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { if (!pads[i]) continue; - err = gc_setup_pad(gc, i, pads[i]); - if (err) + if (gc_setup_pad(gc, i, pads[i])) goto err_unreg_devs; count++; @@ -973,12 +982,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) if (count == 0) { pr_err("No valid devices specified\n"); - err = -EINVAL; goto err_free_gc; } - parport_put_port(pp); - return gc; + gc_base[i] = gc; + return; err_unreg_devs: while (--i >= 0) @@ -988,15 +996,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) kfree(gc); err_unreg_pardev: parport_unregister_device(pd); - err_put_pp: - parport_put_port(pp); - err_out: - return ERR_PTR(err); } -static void gc_remove(struct gc *gc) +static void gc_detach(struct parport *port) { int i; + struct gc *gc; + + for (i = 0; i < GC_MAX_PORTS; i++) { + if (gc_base[i] && gc_base[i]->parportno == port->number) + break; + } + + if (i == GC_MAX_PORTS) + return; + + gc = gc_base[i]; + gc_base[i] = NULL; for (i = 0; i < GC_MAX_DEVICES; i++) if (gc->pads[i].dev) @@ -1005,11 +1021,17 @@ static void gc_remove(struct gc *gc) kfree(gc); } +static struct parport_driver gc_parport_driver = { + .name = "gamecon", + .match_port = gc_attach, + .detach = gc_detach, + .devmodel = true, +}; + static int __init gc_init(void) { int i; int have_dev = 0; - int err = 0; for (i = 0; i < GC_MAX_PORTS; i++) { if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) @@ -1017,37 +1039,21 @@ static int __init gc_init(void) if (gc_cfg[i].nargs < 2) { pr_err("at least one device must be specified\n"); - err = -EINVAL; - break; - } - - gc_base[i] = gc_probe(gc_cfg[i].args[0], - gc_cfg[i].args + 1, gc_cfg[i].nargs - 1); - if (IS_ERR(gc_base[i])) { - err = PTR_ERR(gc_base[i]); - break; + return -EINVAL; } have_dev = 1; } - if (err) { - while (--i >= 0) - if (gc_base[i]) - gc_remove(gc_base[i]); - return err; - } + if (!have_dev) + return -ENODEV; - return have_dev ? 0 : -ENODEV; + return parport_register_driver(&gc_parport_driver); } static void __exit gc_exit(void) { - int i; - - for (i = 0; i < GC_MAX_PORTS; i++) - if (gc_base[i]) - gc_remove(gc_base[i]); + parport_unregister_driver(&gc_parport_driver); } module_init(gc_init); -- cgit v1.2.3 From 4de27a638a99d1a36b14a8fbe982a043223143f6 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 29 Sep 2015 16:04:01 -0700 Subject: Input: turbografx - use parallel port device model Modify turbografx driver to use the new Parallel Port device model. Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/turbografx.c | 100 ++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 49 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 27b6a3ce18ca..5f7382af70c9 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -49,7 +49,7 @@ struct tgfx_config { unsigned int nargs; }; -static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata; +static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS]; module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0); MODULE_PARM_DESC(map, "Describes first set of devices (,,,.."); @@ -81,6 +81,7 @@ static struct tgfx { char phys[TGFX_MAX_DEVICES][32]; int sticks; int used; + int parportno; struct mutex sem; } *tgfx_base[TGFX_MAX_PORTS]; @@ -156,38 +157,46 @@ static void tgfx_close(struct input_dev *dev) * tgfx_probe() probes for tg gamepads. */ -static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) +static void tgfx_attach(struct parport *pp) { struct tgfx *tgfx; struct input_dev *input_dev; - struct parport *pp; struct pardevice *pd; int i, j; - int err; + int *n_buttons, n_devs; + struct pardev_cb tgfx_parport_cb; + + for (i = 0; i < TGFX_MAX_PORTS; i++) { + if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0) + continue; + if (tgfx_cfg[i].args[0] == pp->number) + break; + } - pp = parport_find_number(parport); - if (!pp) { - printk(KERN_ERR "turbografx.c: no such parport\n"); - err = -EINVAL; - goto err_out; + if (i == TGFX_MAX_PORTS) { + pr_debug("Not using parport%d.\n", pp->number); + return; } + n_buttons = tgfx_cfg[i].args + 1; + n_devs = tgfx_cfg[i].nargs - 1; - pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + tgfx_parport_cb.flags = PARPORT_FLAG_EXCL; + + pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb, i); if (!pd) { - printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n"); - err = -EBUSY; - goto err_put_pp; + pr_err("parport busy already - lp.o loaded?\n"); + return; } tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL); if (!tgfx) { printk(KERN_ERR "turbografx.c: Not enough memory\n"); - err = -ENOMEM; goto err_unreg_pardev; } mutex_init(&tgfx->sem); tgfx->pd = pd; + tgfx->parportno = pp->number; init_timer(&tgfx->timer); tgfx->timer.data = (long) tgfx; tgfx->timer.function = tgfx_timer; @@ -198,14 +207,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) if (n_buttons[i] > 6) { printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]); - err = -EINVAL; goto err_unreg_devs; } tgfx->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "turbografx.c: Not enough memory for input device\n"); - err = -ENOMEM; goto err_unreg_devs; } @@ -234,19 +241,17 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) for (j = 0; j < n_buttons[i]; j++) set_bit(tgfx_buttons[j], input_dev->keybit); - err = input_register_device(tgfx->dev[i]); - if (err) + if (input_register_device(tgfx->dev[i])) goto err_free_dev; } if (!tgfx->sticks) { printk(KERN_ERR "turbografx.c: No valid devices specified\n"); - err = -EINVAL; goto err_free_tgfx; } - parport_put_port(pp); - return tgfx; + tgfx_base[i] = tgfx; + return; err_free_dev: input_free_device(tgfx->dev[i]); @@ -258,15 +263,23 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) kfree(tgfx); err_unreg_pardev: parport_unregister_device(pd); - err_put_pp: - parport_put_port(pp); - err_out: - return ERR_PTR(err); } -static void tgfx_remove(struct tgfx *tgfx) +static void tgfx_detach(struct parport *port) { int i; + struct tgfx *tgfx; + + for (i = 0; i < TGFX_MAX_PORTS; i++) { + if (tgfx_base[i] && tgfx_base[i]->parportno == port->number) + break; + } + + if (i == TGFX_MAX_PORTS) + return; + + tgfx = tgfx_base[i]; + tgfx_base[i] = NULL; for (i = 0; i < TGFX_MAX_DEVICES; i++) if (tgfx->dev[i]) @@ -275,11 +288,17 @@ static void tgfx_remove(struct tgfx *tgfx) kfree(tgfx); } +static struct parport_driver tgfx_parport_driver = { + .name = "turbografx", + .match_port = tgfx_attach, + .detach = tgfx_detach, + .devmodel = true, +}; + static int __init tgfx_init(void) { int i; int have_dev = 0; - int err = 0; for (i = 0; i < TGFX_MAX_PORTS; i++) { if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0) @@ -287,38 +306,21 @@ static int __init tgfx_init(void) if (tgfx_cfg[i].nargs < 2) { printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n"); - err = -EINVAL; - break; - } - - tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0], - tgfx_cfg[i].args + 1, - tgfx_cfg[i].nargs - 1); - if (IS_ERR(tgfx_base[i])) { - err = PTR_ERR(tgfx_base[i]); - break; + return -EINVAL; } have_dev = 1; } - if (err) { - while (--i >= 0) - if (tgfx_base[i]) - tgfx_remove(tgfx_base[i]); - return err; - } + if (!have_dev) + return -ENODEV; - return have_dev ? 0 : -ENODEV; + return parport_register_driver(&tgfx_parport_driver); } static void __exit tgfx_exit(void) { - int i; - - for (i = 0; i < TGFX_MAX_PORTS; i++) - if (tgfx_base[i]) - tgfx_remove(tgfx_base[i]); + parport_unregister_driver(&tgfx_parport_driver); } module_init(tgfx_init); -- cgit v1.2.3 From 221bcb24c6530be17468fdcdbf91299aba32a693 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 29 Sep 2015 16:06:22 -0700 Subject: Input: walkera0701 - use parallel port device model Modify walkera0701 driver to use the new Parallel Port device model. Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/walkera0701.c | 64 +++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 27 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index b76ac580703c..9c07fe911075 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -200,35 +200,38 @@ static void walkera0701_close(struct input_dev *dev) parport_release(w->pardevice); } -static int walkera0701_connect(struct walkera_dev *w, int parport) +static void walkera0701_attach(struct parport *pp) { - int error; + struct pardev_cb walkera0701_parport_cb; + struct walkera_dev *w = &w_dev; - w->parport = parport_find_number(parport); - if (!w->parport) { - pr_err("parport %d does not exist\n", parport); - return -ENODEV; + if (pp->number != walkera0701_pp_no) { + pr_debug("Not using parport%d.\n", pp->number); + return; } - if (w->parport->irq == -1) { + if (pp->irq == -1) { pr_err("parport %d does not have interrupt assigned\n", - parport); - error = -EINVAL; - goto err_put_parport; + pp->number); + return; } - w->pardevice = parport_register_device(w->parport, "walkera0701", - NULL, NULL, walkera0701_irq_handler, - PARPORT_DEV_EXCL, w); + w->parport = pp; + + walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL; + walkera0701_parport_cb.irq_func = walkera0701_irq_handler; + walkera0701_parport_cb.private = w; + + w->pardevice = parport_register_dev_model(pp, "walkera0701", + &walkera0701_parport_cb, 0); + if (!w->pardevice) { pr_err("failed to register parport device\n"); - error = -EIO; - goto err_put_parport; + return; } if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) { pr_err("failed to negotiate parport mode\n"); - error = -EIO; goto err_unregister_device; } @@ -238,7 +241,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) w->input_dev = input_allocate_device(); if (!w->input_dev) { pr_err("failed to allocate input device\n"); - error = -ENOMEM; goto err_unregister_device; } @@ -265,38 +267,46 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0); input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0); - error = input_register_device(w->input_dev); - if (error) { + if (input_register_device(w->input_dev)) { pr_err("failed to register input device\n"); goto err_free_input_dev; } - return 0; + return; err_free_input_dev: input_free_device(w->input_dev); err_unregister_device: parport_unregister_device(w->pardevice); -err_put_parport: - parport_put_port(w->parport); - return error; } -static void walkera0701_disconnect(struct walkera_dev *w) +static void walkera0701_detach(struct parport *port) { + struct walkera_dev *w = &w_dev; + + if (!w->pardevice || w->parport->number != port->number) + return; + input_unregister_device(w->input_dev); parport_unregister_device(w->pardevice); - parport_put_port(w->parport); + w->parport = NULL; } +static struct parport_driver walkera0701_parport_driver = { + .name = "walkera0701", + .match_port = walkera0701_attach, + .detach = walkera0701_detach, + .devmodel = true, +}; + static int __init walkera0701_init(void) { - return walkera0701_connect(&w_dev, walkera0701_pp_no); + return parport_register_driver(&walkera0701_parport_driver); } static void __exit walkera0701_exit(void) { - walkera0701_disconnect(&w_dev); + parport_unregister_driver(&walkera0701_parport_driver); } module_init(walkera0701_init); -- cgit v1.2.3 From a27b5e0a78c31b57fa5cceaec4415caeca2e50dd Mon Sep 17 00:00:00 2001 From: S Twiss Date: Mon, 27 Jul 2015 22:28:40 -0700 Subject: Input: add DA9062 OnKey capability to DA9063 OnKey driver Add DA9062 OnKey support into the existing DA9063 OnKey driver component by using generic access tables for common register and bit mask definitions. The following change will add generic register and bit mask support to the DA9063 OnKey. The following alterations have been made to the DA9063 OnKey: - Addition of a da906x_chip_config structure to hold all generic registers and bitmasks for this type of OnKey component. - Addition of an struct of_device_id table for DA9063 and DA9062 defaults - Refactoring functions to use struct da9063_onkey accesses to generic registers/masks instead of using defines from registers.h - Re-work of da9063_onkey_probe() to use of_match_node() and dev_get_regmap() to provide initialisation of generic registers and masks and access to regmap Signed-off-by: Steve Twiss Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/da9062-onkey.txt | 32 +++++ drivers/input/misc/Kconfig | 8 +- drivers/input/misc/da9063_onkey.c | 129 +++++++++++++++++---- 3 files changed, 140 insertions(+), 29 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/da9062-onkey.txt (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/da9062-onkey.txt b/Documentation/devicetree/bindings/input/da9062-onkey.txt new file mode 100644 index 000000000000..ab0e0488fe92 --- /dev/null +++ b/Documentation/devicetree/bindings/input/da9062-onkey.txt @@ -0,0 +1,32 @@ +* Dialog DA9062/63 OnKey Module + +This module is part of the DA9062/DA9063. For more details about entire +chips see Documentation/devicetree/bindings/mfd/da9062.txt and +Documentation/devicetree/bindings/mfd/da9063.txt + +This module provides KEY_POWER, KEY_SLEEP and events. + +Required properties: + +- compatible: should be one of: + dlg,da9062-onkey + dlg,da9063-onkey + +Optional properties: + + - dlg,disable-key-power : Disable power-down using a long key-press. If this + entry exists the OnKey driver will remove support for the KEY_POWER key + press. If this entry does not exist then by default the key-press + triggered power down is enabled and the OnKey will support both KEY_POWER + and KEY_SLEEP. + +Example: + + pmic0: da9062@58 { + + onkey { + compatible = "dlg,da9063-onkey"; + dlg,disable-key-power; + }; + + }; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 906dd1b25e41..d1ef61c2decd 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -599,11 +599,11 @@ config INPUT_DA9055_ONKEY will be called da9055_onkey. config INPUT_DA9063_ONKEY - tristate "Dialog DA9063 OnKey" - depends on MFD_DA9063 + tristate "Dialog DA9062/63 OnKey" + depends on MFD_DA9063 || MFD_DA9062 help - Support the ONKEY of Dialog DA9063 Power Management IC as an - input device reporting power button statue. + Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs + as an input device capable of reporting the power button status. To compile this driver as a module, choose M here: the module will be called da9063_onkey. diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c index f577585ef999..8eb697db82d0 100644 --- a/drivers/input/misc/da9063_onkey.c +++ b/drivers/input/misc/da9063_onkey.c @@ -1,5 +1,5 @@ /* - * OnKey device driver for DA9063 + * OnKey device driver for DA9063 and DA9062 PMICs * Copyright (C) 2015 Dialog Semiconductor Ltd. * * This program is free software; you can redistribute it and/or @@ -24,36 +24,96 @@ #include #include #include +#include +#include + +struct da906x_chip_config { + /* REGS */ + int onkey_status; + int onkey_pwr_signalling; + int onkey_fault_log; + int onkey_shutdown; + /* MASKS */ + int onkey_nonkey_mask; + int onkey_nonkey_lock_mask; + int onkey_key_reset_mask; + int onkey_shutdown_mask; + /* NAMES */ + const char *name; +}; struct da9063_onkey { - struct da9063 *hw; struct delayed_work work; struct input_dev *input; struct device *dev; + struct regmap *regmap; + const struct da906x_chip_config *config; + char phys[32]; bool key_power; }; +static const struct da906x_chip_config da9063_regs = { + /* REGS */ + .onkey_status = DA9063_REG_STATUS_A, + .onkey_pwr_signalling = DA9063_REG_CONTROL_B, + .onkey_fault_log = DA9063_REG_FAULT_LOG, + .onkey_shutdown = DA9063_REG_CONTROL_F, + /* MASKS */ + .onkey_nonkey_mask = DA9063_NONKEY, + .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK, + .onkey_key_reset_mask = DA9063_KEY_RESET, + .onkey_shutdown_mask = DA9063_SHUTDOWN, + /* NAMES */ + .name = DA9063_DRVNAME_ONKEY, +}; + +static const struct da906x_chip_config da9062_regs = { + /* REGS */ + .onkey_status = DA9062AA_STATUS_A, + .onkey_pwr_signalling = DA9062AA_CONTROL_B, + .onkey_fault_log = DA9062AA_FAULT_LOG, + .onkey_shutdown = DA9062AA_CONTROL_F, + /* MASKS */ + .onkey_nonkey_mask = DA9062AA_NONKEY_MASK, + .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK, + .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK, + .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK, + /* NAMES */ + .name = "da9062-onkey", +}; + +static const struct of_device_id da9063_compatible_reg_id_table[] = { + { .compatible = "dlg,da9063-onkey", .data = &da9063_regs }, + { .compatible = "dlg,da9062-onkey", .data = &da9062_regs }, + { }, +}; + static void da9063_poll_on(struct work_struct *work) { - struct da9063_onkey *onkey = container_of(work, struct da9063_onkey, - work.work); + struct da9063_onkey *onkey = container_of(work, + struct da9063_onkey, + work.work); + const struct da906x_chip_config *config = onkey->config; unsigned int val; int fault_log = 0; bool poll = true; int error; /* Poll to see when the pin is released */ - error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); + error = regmap_read(onkey->regmap, + config->onkey_status, + &val); if (error) { dev_err(onkey->dev, "Failed to read ON status: %d\n", error); goto err_poll; } - if (!(val & DA9063_NONKEY)) { - error = regmap_update_bits(onkey->hw->regmap, - DA9063_REG_CONTROL_B, - DA9063_NONKEY_LOCK, 0); + if (!(val & config->onkey_nonkey_mask)) { + error = regmap_update_bits(onkey->regmap, + config->onkey_pwr_signalling, + config->onkey_nonkey_lock_mask, + 0); if (error) { dev_err(onkey->dev, "Failed to reset the Key Delay %d\n", error); @@ -70,15 +130,16 @@ static void da9063_poll_on(struct work_struct *work) * If the fault log KEY_RESET is detected, then clear it * and shut down the system. */ - error = regmap_read(onkey->hw->regmap, - DA9063_REG_FAULT_LOG, &fault_log); + error = regmap_read(onkey->regmap, + config->onkey_fault_log, + &fault_log); if (error) { dev_warn(&onkey->input->dev, "Cannot read FAULT_LOG: %d\n", error); - } else if (fault_log & DA9063_KEY_RESET) { - error = regmap_write(onkey->hw->regmap, - DA9063_REG_FAULT_LOG, - DA9063_KEY_RESET); + } else if (fault_log & config->onkey_key_reset_mask) { + error = regmap_write(onkey->regmap, + config->onkey_fault_log, + config->onkey_key_reset_mask); if (error) { dev_warn(&onkey->input->dev, "Cannot reset KEY_RESET fault log: %d\n", @@ -88,10 +149,10 @@ static void da9063_poll_on(struct work_struct *work) * and then send shutdown command */ dev_dbg(&onkey->input->dev, - "Sending SHUTDOWN to DA9063 ...\n"); - error = regmap_write(onkey->hw->regmap, - DA9063_REG_CONTROL_F, - DA9063_SHUTDOWN); + "Sending SHUTDOWN to DA9063 ...\n"); + error = regmap_write(onkey->regmap, + config->onkey_shutdown, + config->onkey_shutdown_mask); if (error) dev_err(&onkey->input->dev, "Cannot SHUTDOWN DA9063: %d\n", @@ -107,11 +168,14 @@ err_poll: static irqreturn_t da9063_onkey_irq_handler(int irq, void *data) { struct da9063_onkey *onkey = data; + const struct da906x_chip_config *config = onkey->config; unsigned int val; int error; - error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); - if (onkey->key_power && !error && (val & DA9063_NONKEY)) { + error = regmap_read(onkey->regmap, + config->onkey_status, + &val); + if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) { input_report_key(onkey->input, KEY_POWER, 1); input_sync(onkey->input); schedule_delayed_work(&onkey->work, 0); @@ -139,9 +203,15 @@ static int da9063_onkey_probe(struct platform_device *pdev) struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); struct da9063_pdata *pdata = dev_get_platdata(da9063->dev); struct da9063_onkey *onkey; + const struct of_device_id *match; int irq; int error; + match = of_match_node(da9063_compatible_reg_id_table, + pdev->dev.of_node); + if (!match) + return -ENXIO; + onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey), GFP_KERNEL); if (!onkey) { @@ -149,8 +219,14 @@ static int da9063_onkey_probe(struct platform_device *pdev) return -ENOMEM; } + onkey->config = match->data; onkey->dev = &pdev->dev; - onkey->hw = da9063; + + onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!onkey->regmap) { + dev_err(&pdev->dev, "Parent regmap unavailable.\n"); + return -ENXIO; + } if (pdata) onkey->key_power = pdata->key_power; @@ -165,8 +241,10 @@ static int da9063_onkey_probe(struct platform_device *pdev) return -ENOMEM; } - onkey->input->name = DA9063_DRVNAME_ONKEY; - onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0"; + onkey->input->name = onkey->config->name; + snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0", + onkey->config->name); + onkey->input->phys = onkey->phys; onkey->input->dev.parent = &pdev->dev; if (onkey->key_power) @@ -216,11 +294,12 @@ static struct platform_driver da9063_onkey_driver = { .probe = da9063_onkey_probe, .driver = { .name = DA9063_DRVNAME_ONKEY, + .of_match_table = da9063_compatible_reg_id_table, }, }; module_platform_driver(da9063_onkey_driver); MODULE_AUTHOR("S Twiss "); -MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063"); +MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY); -- cgit v1.2.3 From 09a59a9d57a9d6f49510c93304d6e105deb83b93 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 1 Oct 2015 15:37:08 -0700 Subject: drivers/input/joystick/Kconfig: zhenhua.c needs BITREVERSE It uses bitrev8(), so it must ensure that lib/bitrev.o gets included in vmlinux. Cc: Fengguang Wu Cc: yalin wang Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/joystick/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 56eb471b5576..4215b5382092 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -196,6 +196,7 @@ config JOYSTICK_TWIDJOY config JOYSTICK_ZHENHUA tristate "5-byte Zhenhua RC transmitter" select SERIO + select BITREVERSE help Say Y here if you have a Zhen Hua PPM-4CH transmitter which is supplied with a ready to fly micro electric indoor helicopters -- cgit v1.2.3 From 77fa05541cc02ab87e6d6e42254052b0cd30c3a4 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 2 Oct 2015 10:44:00 -0700 Subject: Input: gpio_keys - don't report events on gpio failure In the cases where the gpio chip fails to acquire the current state an error is reported back to gpio_keys. This is currently interpreted as if the line went high, which just confuses the developer. This patch introduces an error print in this case and skipps the reporting of a input event; to aid in debugging this issue. Reported-by: John Stultz Signed-off-by: Bjorn Andersson Reviewed-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 9d517ca7eb5a..bef317ff7352 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -341,8 +341,14 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; - int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; + int state = gpio_get_value_cansleep(button->gpio); + if (state < 0) { + dev_err(input->dev.parent, "failed to get gpio state\n"); + return; + } + + state = (state ? 1 : 0) ^ button->active_low; if (type == EV_ABS) { if (state) input_event(input, type, button->code, button->value); -- cgit v1.2.3 From aaa59e0911f5624663217c248cfa7cc1c2e33e08 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 10:49:48 -0700 Subject: Input: goldfish - allow compile the driver with COMPILE_TEST The driver depends on GOLDFISH but there isn't a build dependency so it's a good idea to allow the driver to be built even if that option is disabled, if the COMPILE_TEST option is enabled. That way, the driver can be built with a config generated by make allyesconfig and can be checked if a patch would break the build. Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2e80107ff630..ddd8148d51d7 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -516,7 +516,7 @@ config KEYBOARD_SAMSUNG module will be called samsung-keypad. config KEYBOARD_GOLDFISH_EVENTS - depends on GOLDFISH + depends on GOLDFISH || COMPILE_TEST tristate "Generic Input Event device for Goldfish" help Say Y here to get an input event device for the Goldfish virtual -- cgit v1.2.3 From 5702222c9a7af4a207066d54aa95cfe31f34f2f8 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:12:53 -0700 Subject: Input: joydev - use memdup_user() to duplicate memory from user-space The memdup_user() helper function can be used to duplicate a memory region from user-space to kernel-space. There is no need to open code the same logic using kmalloc() and copy_from_user() instead. This was found with make coccicheck that reported the following warning: drivers/input/joydev.c:447:10-17: WARNING opportunity for memdup_user drivers/input/joydev.c:483:10-17: WARNING opportunity for memdup_user Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/joydev.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 6cb5a3e5f9a1..e3dcd4abae18 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -444,12 +444,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, len = min(len, sizeof(joydev->abspam)); /* Validate the map. */ - abspam = kmalloc(len, GFP_KERNEL); - if (!abspam) - return -ENOMEM; - - if (copy_from_user(abspam, argp, len)) { - retval = -EFAULT; + abspam = memdup_user(argp, len); + if (IS_ERR(abspam)) { + retval = PTR_ERR(abspam); goto out; } @@ -480,12 +477,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, len = min(len, sizeof(joydev->keypam)); /* Validate the map. */ - keypam = kmalloc(len, GFP_KERNEL); - if (!keypam) - return -ENOMEM; - - if (copy_from_user(keypam, argp, len)) { - retval = -EFAULT; + keypam = memdup_user(argp, len); + if (IS_ERR(keypam)) { + retval = PTR_ERR(keypam); goto out; } -- cgit v1.2.3 From 5ccd9abd508644cefee8641ccd6157e8b55a6ee3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:14:26 -0700 Subject: Input: kxtj9 - remove unneeded retval variable The retval variable isn't needed since isn't used in the function. Remove the variable and just return 0 instead. This also fixes the following make coccicheck warning: drivers/input/misc/kxtj9.c:638:5-11: Unneeded variable: "retval". Return "0" on line 646 Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/misc/kxtj9.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index e058d711256a..efaffcc57e36 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -635,7 +635,6 @@ static int __maybe_unused kxtj9_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct kxtj9_data *tj9 = i2c_get_clientdata(client); struct input_dev *input_dev = tj9->input_dev; - int retval = 0; mutex_lock(&input_dev->mutex); @@ -643,7 +642,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev) kxtj9_enable(tj9); mutex_unlock(&input_dev->mutex); - return retval; + return 0; } static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume); -- cgit v1.2.3 From a47fcbc24f24c2620bf4bf499d13ec2bf8355e72 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:15:08 -0700 Subject: Input: zforce - simplify function return logic The invoked function already returns zero on success or a negative errno code so there is no need to open code the logic in the caller. This also fixes the following make coccicheck warning: end returns can be simplified and declaration on line 602 can be dropped Signed-off-by: Javier Martinez Canillas Reviewed-by: Heiko Stuebner Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/zforce_ts.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 781d0f83050a..9bbadaaf6bc3 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -599,13 +599,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) static int zforce_input_open(struct input_dev *dev) { struct zforce_ts *ts = input_get_drvdata(dev); - int ret; - ret = zforce_start(ts); - if (ret) - return ret; - - return 0; + return zforce_start(ts); } static void zforce_input_close(struct input_dev *dev) -- cgit v1.2.3 From 901ea5e3a8251c05fcf252149103df7f35733967 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:18:59 -0700 Subject: Input: auo-pixcir-ts - simplify function return logic The invoked function already returns zero on success or a negative errno code so there is no need to open code the logic in the caller. This also fixes the following make coccicheck warnings: end returns can be simplified and declaration on line 402 can be dropped Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/auo-pixcir-ts.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 38c06f754acd..6592fc5d48b4 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -399,13 +399,8 @@ static int auo_pixcir_stop(struct auo_pixcir_ts *ts) static int auo_pixcir_input_open(struct input_dev *dev) { struct auo_pixcir_ts *ts = input_get_drvdata(dev); - int ret; - - ret = auo_pixcir_start(ts); - if (ret) - return ret; - return 0; + return auo_pixcir_start(ts); } static void auo_pixcir_input_close(struct input_dev *dev) -- cgit v1.2.3 From e5e66ed00ea555a4f66793b4be84ff99c9c7fa6e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:19:54 -0700 Subject: Input: tps6507x-ts - simplify function return logic The invoked function already returns zero on success or a negative errno code so there is no need to open code the logic in the caller. This also fixes the following make coccicheck warning: drivers/input/touchscreen/tps6507x-ts.c:57:5-8: WARNING: end returns can be simplified Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tps6507x-ts.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 4ffd829d1990..a340bfccdfb6 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -50,14 +50,7 @@ struct tps6507x_ts { static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data) { - int err; - - err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data); - - if (err) - return err; - - return 0; + return tsc->mfd->read_dev(tsc->mfd, reg, 1, data); } static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data) -- cgit v1.2.3 From c4517f82d23eb72bf0768257bccc5f326c9ceada Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:20:40 -0700 Subject: Input: ads7846 - use PTR_ERR_OR_ZERO() The PTR_ERR_OR_ZERO() helper function checks if a pointer contains an errno code and returns it or return 0 if that's not the case. Use the helper instead of open coding the same logic in the driver. This was found with make coccicheck that complains with the following warning: drivers/input/touchscreen/ads7846.c:532:1-3: WARNING: PTR_ERR_OR_ZERO can be used Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 0f5f968592bd..727d88c900c1 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -529,10 +529,8 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias, ts, ads7846_attr_groups); - if (IS_ERR(ts->hwmon)) - return PTR_ERR(ts->hwmon); - return 0; + return PTR_ERR_OR_ZERO(ts->hwmon); } static void ads784x_hwmon_unregister(struct spi_device *spi, -- cgit v1.2.3 From d6f0c3d3a815aca40f1ea9daf6ed0d1f9e243185 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 2 Oct 2015 11:21:12 -0700 Subject: Input: cyttsp - use PTR_ERR_OR_ZERO() The PTR_ERR_OR_ZERO() helper function checks if a pointer contains an errno code and returns it or return 0 if that's not the case. Use the helper instead of open coding the same logic in the driver. This was found with make coccicheck that complains with the following warning: drivers/input/touchscreen/cyttsp4_i2c.c:53:1-3: WARNING: PTR_ERR_OR_ZERO can be used Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp4_i2c.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c index a9f95c7d3c00..564e49002d5d 100644 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ b/drivers/input/touchscreen/cyttsp4_i2c.c @@ -50,10 +50,7 @@ static int cyttsp4_i2c_probe(struct i2c_client *client, ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq, CYTTSP4_I2C_DATA_SIZE); - if (IS_ERR(ts)) - return PTR_ERR(ts); - - return 0; + return PTR_ERR_OR_ZERO(ts); } static int cyttsp4_i2c_remove(struct i2c_client *client) -- cgit v1.2.3 From 92deea1350f9fa97a841d45cd1f8228d5e8aa667 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Fri, 2 Oct 2015 11:30:11 -0700 Subject: Input: add support for FocalTech FT6236 touchscreen controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for the FT6x06 and the FT6x36 family of capacitive touch panel controllers, in particular the FT6236. Signed-off-by: Noralf Trønnes Signed-off-by: Dmitry Torokhov --- .../input/touchscreen/focaltech-ft6236.txt | 35 +++ .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/input/touchscreen/Kconfig | 13 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/ft6236.c | 327 +++++++++++++++++++++ 5 files changed, 377 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt create mode 100644 drivers/input/touchscreen/ft6236.c (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt b/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt new file mode 100644 index 000000000000..777521da3da5 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt @@ -0,0 +1,35 @@ +* FocalTech FT6236 I2C touchscreen controller + +Required properties: + - compatible : "focaltech,ft6236" + - reg : I2C slave address of the chip (0x38) + - interrupt-parent : a phandle pointing to the interrupt controller + serving the interrupt for this chip + - interrupts : interrupt specification for the touch controller + interrupt + - reset-gpios : GPIO specification for the RSTN input + - touchscreen-size-x : horizontal resolution of touchscreen (in pixels) + - touchscreen-size-y : vertical resolution of touchscreen (in pixels) + +Optional properties: + - touchscreen-fuzz-x : horizontal noise value of the absolute input + device (in pixels) + - touchscreen-fuzz-y : vertical noise value of the absolute input + device (in pixels) + - touchscreen-inverted-x : X axis is inverted (boolean) + - touchscreen-inverted-y : Y axis is inverted (boolean) + - touchscreen-swapped-x-y: X and Y axis are swapped (boolean) + Swapping is done after inverting the axis + +Example: + + ft6x06@38 { + compatible = "focaltech,ft6236"; + reg = <0x38>; + interrupt-parent = <&gpio>; + interrupts = <23 2>; + touchscreen-size-x = <320>; + touchscreen-size-y = <480>; + touchscreen-inverted-x; + touchscreen-swapped-x-y; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 82d2ac97af74..3222b2ff475e 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -82,6 +82,7 @@ everspin Everspin Technologies, Inc. excito Excito fcs Fairchild Semiconductor firefly Firefly +focaltech FocalTech Systems Co.,Ltd fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 600dcceff542..eda89b6b7e11 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -295,6 +295,19 @@ config TOUCHSCREEN_EGALAX To compile this driver as a module, choose M here: the module will be called egalax_ts. +config TOUCHSCREEN_FT6236 + tristate "FT6236 I2C touchscreen" + depends on I2C + depends on GPIOLIB || COMPILE_TEST + help + Say Y here to enable support for the I2C connected FT6x06 and + FT6x36 family of capacitive touchscreen drivers. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft6236. + config TOUCHSCREEN_FUJITSU tristate "Fujitsu serial touchscreen" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 1b79cc09744a..baba189e3e16 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o +obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o diff --git a/drivers/input/touchscreen/ft6236.c b/drivers/input/touchscreen/ft6236.c new file mode 100644 index 000000000000..cccae193668e --- /dev/null +++ b/drivers/input/touchscreen/ft6236.c @@ -0,0 +1,327 @@ +/* + * FocalTech FT6236 TouchScreen driver. + * + * Copyright (c) 2010 Focal tech Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FT6236_MAX_TOUCH_POINTS 2 + +#define FT6236_REG_TH_GROUP 0x80 +#define FT6236_REG_PERIODACTIVE 0x88 +#define FT6236_REG_LIB_VER_H 0xa1 +#define FT6236_REG_LIB_VER_L 0xa2 +#define FT6236_REG_CIPHER 0xa3 +#define FT6236_REG_FIRMID 0xa6 +#define FT6236_REG_FOCALTECH_ID 0xa8 +#define FT6236_REG_RELEASE_CODE_ID 0xaf + +#define FT6236_EVENT_PRESS_DOWN 0 +#define FT6236_EVENT_LIFT_UP 1 +#define FT6236_EVENT_CONTACT 2 +#define FT6236_EVENT_NO_EVENT 3 + +struct ft6236_data { + struct i2c_client *client; + struct input_dev *input; + struct gpio_desc *reset_gpio; + u32 max_x; + u32 max_y; + bool invert_x; + bool invert_y; + bool swap_xy; +}; + +/* + * This struct is a touchpoint as stored in hardware. Note that the id, + * as well as the event, are stored in the upper nybble of the hi byte. + */ +struct ft6236_touchpoint { + union { + u8 xhi; + u8 event; + }; + u8 xlo; + union { + u8 yhi; + u8 id; + }; + u8 ylo; + u8 weight; + u8 misc; +} __packed; + +/* This packet represents the register map as read from offset 0 */ +struct ft6236_packet { + u8 dev_mode; + u8 gest_id; + u8 touches; + struct ft6236_touchpoint points[FT6236_MAX_TOUCH_POINTS]; +} __packed; + +static int ft6236_read(struct i2c_client *client, u8 reg, u8 len, void *data) +{ + int error; + + error = i2c_smbus_read_i2c_block_data(client, reg, len, data); + if (error < 0) + return error; + + if (error != len) + return -EIO; + + return 0; +} + +static irqreturn_t ft6236_interrupt(int irq, void *dev_id) +{ + struct ft6236_data *ft6236 = dev_id; + struct device *dev = &ft6236->client->dev; + struct input_dev *input = ft6236->input; + struct ft6236_packet buf; + u8 touches; + int i, error; + + error = ft6236_read(ft6236->client, 0, sizeof(buf), &buf); + if (error) { + dev_err(dev, "read touchdata failed %d\n", error); + return IRQ_HANDLED; + } + + touches = buf.touches & 0xf; + if (touches > FT6236_MAX_TOUCH_POINTS) { + dev_dbg(dev, + "%d touch points reported, only %d are supported\n", + touches, FT6236_MAX_TOUCH_POINTS); + touches = FT6236_MAX_TOUCH_POINTS; + } + + for (i = 0; i < touches; i++) { + struct ft6236_touchpoint *point = &buf.points[i]; + u16 x = ((point->xhi & 0xf) << 8) | buf.points[i].xlo; + u16 y = ((point->yhi & 0xf) << 8) | buf.points[i].ylo; + u8 event = point->event >> 6; + u8 id = point->id >> 4; + bool act = (event == FT6236_EVENT_PRESS_DOWN || + event == FT6236_EVENT_CONTACT); + + input_mt_slot(input, id); + input_mt_report_slot_state(input, MT_TOOL_FINGER, act); + if (!act) + continue; + + if (ft6236->invert_x) + x = ft6236->max_x - x; + + if (ft6236->invert_y) + y = ft6236->max_y - y; + + if (ft6236->swap_xy) { + input_report_abs(input, ABS_MT_POSITION_X, y); + input_report_abs(input, ABS_MT_POSITION_Y, x); + } else { + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + } + } + + input_mt_sync_frame(input); + input_sync(input); + + return IRQ_HANDLED; +} + +static u8 ft6236_debug_read_byte(struct ft6236_data *ft6236, u8 reg) +{ + struct i2c_client *client = ft6236->client; + u8 val = 0; + int error; + + error = ft6236_read(client, reg, 1, &val); + if (error) + dev_dbg(&client->dev, + "error reading register 0x%02x: %d\n", reg, error); + + return val; +} + +static void ft6236_debug_info(struct ft6236_data *ft6236) +{ + struct device *dev = &ft6236->client->dev; + + dev_dbg(dev, "Touch threshold is %d\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_TH_GROUP) * 4); + dev_dbg(dev, "Report rate is %dHz\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_PERIODACTIVE) * 10); + dev_dbg(dev, "Firmware library version 0x%02x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_H), + ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_L)); + dev_dbg(dev, "Firmware version 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_FIRMID)); + dev_dbg(dev, "Chip vendor ID 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_CIPHER)); + dev_dbg(dev, "CTPM vendor ID 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_FOCALTECH_ID)); + dev_dbg(dev, "Release code version 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_RELEASE_CODE_ID)); +} + +static void ft6236_reset(struct ft6236_data *ft6236) +{ + if (!ft6236->reset_gpio) + return; + + gpiod_set_value_cansleep(ft6236->reset_gpio, 1); + usleep_range(5000, 20000); + gpiod_set_value_cansleep(ft6236->reset_gpio, 0); + msleep(300); +} + +static int ft6236_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct ft6236_data *ft6236; + struct input_dev *input; + u32 fuzz_x = 0, fuzz_y = 0; + u8 val; + int error; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENXIO; + + if (!client->irq) { + dev_err(dev, "irq is missing\n"); + return -EINVAL; + } + + ft6236 = devm_kzalloc(dev, sizeof(*ft6236), GFP_KERNEL); + if (!ft6236) + return -ENOMEM; + + ft6236->client = client; + ft6236->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(ft6236->reset_gpio)) { + error = PTR_ERR(ft6236->reset_gpio); + if (error != -EPROBE_DEFER) + dev_err(dev, "error getting reset gpio: %d\n", error); + return error; + } + + ft6236_reset(ft6236); + + /* verify that the controller is present */ + error = ft6236_read(client, 0x00, 1, &val); + if (error) { + dev_err(dev, "failed to read from controller: %d\n", error); + return error; + } + + ft6236_debug_info(ft6236); + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + + ft6236->input = input; + input->name = client->name; + input->id.bustype = BUS_I2C; + + if (device_property_read_u32(dev, "touchscreen-size-x", + &ft6236->max_x) || + device_property_read_u32(dev, "touchscreen-size-y", + &ft6236->max_y)) { + dev_err(dev, "touchscreen-size-x and/or -y missing\n"); + return -EINVAL; + } + + device_property_read_u32(dev, "touchscreen-fuzz-x", &fuzz_x); + device_property_read_u32(dev, "touchscreen-fuzz-y", &fuzz_y); + ft6236->invert_x = device_property_read_bool(dev, + "touchscreen-inverted-x"); + ft6236->invert_y = device_property_read_bool(dev, + "touchscreen-inverted-y"); + ft6236->swap_xy = device_property_read_bool(dev, + "touchscreen-swapped-x-y"); + + if (ft6236->swap_xy) { + input_set_abs_params(input, ABS_MT_POSITION_X, 0, + ft6236->max_y, fuzz_y, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, + ft6236->max_x, fuzz_x, 0); + } else { + input_set_abs_params(input, ABS_MT_POSITION_X, 0, + ft6236->max_x, fuzz_x, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, + ft6236->max_y, fuzz_y, 0); + } + + error = input_mt_init_slots(input, FT6236_MAX_TOUCH_POINTS, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) + return error; + + error = devm_request_threaded_irq(dev, client->irq, NULL, + ft6236_interrupt, IRQF_ONESHOT, + client->name, ft6236); + if (error) { + dev_err(dev, "request irq %d failed: %d\n", client->irq, error); + return error; + } + + error = input_register_device(input); + if (error) { + dev_err(dev, "failed to register input device: %d\n", error); + return error; + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id ft6236_of_match[] = { + { .compatible = "focaltech,ft6236", }, + { } +}; +MODULE_DEVICE_TABLE(of, ft6236_of_match); +#endif + +static const struct i2c_device_id ft6236_id[] = { + { "ft6236", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ft6236_id); + +static struct i2c_driver ft6236_driver = { + .driver = { + .name = "ft6236", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ft6236_of_match), + }, + .probe = ft6236_probe, + .id_table = ft6236_id, +}; +module_i2c_driver(ft6236_driver); + +MODULE_AUTHOR("Sean Cross "); +MODULE_AUTHOR("Noralf Trønnes "); +MODULE_DESCRIPTION("FocalTech FT6236 TouchScreen driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From dd23bf1044e89f46e2d1af9725c0b24864309082 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 5 Oct 2015 17:22:47 -0700 Subject: Input: db9 - store object at correct index The variable i is used to check the port to attach to and we are supposed to save the reference of struct db9 in the location given by db9_base[i]. But after finding out the index, i is getting modified again so we saved in a wrong index. While at it mark db9_base[i] as NULL after it is freed. Fixes: 2260c419b52b ("Input: db9 - use parallel port device model") Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/db9.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index cf1f602e0f0a..932d07307454 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -560,25 +560,25 @@ static void db9_attach(struct parport *pp) const struct db9_mode_data *db9_mode; struct pardevice *pd; struct input_dev *input_dev; - int i, j; + int i, j, port_idx; int mode; struct pardev_cb db9_parport_cb; - for (i = 0; i < DB9_MAX_PORTS; i++) { - if (db9_cfg[i].nargs == 0 || - db9_cfg[i].args[DB9_ARG_PARPORT] < 0) + for (port_idx = 0; port_idx < DB9_MAX_PORTS; port_idx++) { + if (db9_cfg[port_idx].nargs == 0 || + db9_cfg[port_idx].args[DB9_ARG_PARPORT] < 0) continue; - if (db9_cfg[i].args[DB9_ARG_PARPORT] == pp->number) + if (db9_cfg[port_idx].args[DB9_ARG_PARPORT] == pp->number) break; } - if (i == DB9_MAX_PORTS) { + if (port_idx == DB9_MAX_PORTS) { pr_debug("Not using parport%d.\n", pp->number); return; } - mode = db9_cfg[i].args[DB9_ARG_MODE]; + mode = db9_cfg[port_idx].args[DB9_ARG_MODE]; if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) { printk(KERN_ERR "db9.c: Bad device type %d\n", mode); @@ -594,7 +594,7 @@ static void db9_attach(struct parport *pp) db9_parport_cb.flags = PARPORT_FLAG_EXCL; - pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, i); + pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx); if (!pd) { printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n"); return; @@ -649,7 +649,7 @@ static void db9_attach(struct parport *pp) goto err_free_dev; } - db9_base[i] = db9; + db9_base[port_idx] = db9; return; err_free_dev: @@ -676,6 +676,7 @@ static void db9_detach(struct parport *port) return; db9 = db9_base[i]; + db9_base[i] = NULL; for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++) input_unregister_device(db9->dev[i]); -- cgit v1.2.3 From c36906c53ccff0f43310fac9606976440a71c742 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 5 Oct 2015 17:22:58 -0700 Subject: Input: gamecon - store object at correct index The variable i is used to check the port to attach to and we are supposed to save the reference of struct gc in the location given by gc_base[i]. But after finding out the index, i is getting modified again so we saved in a wrong index. Reported-by: Dan Carpenter Fixes: a517e87c3dfc ("Input: gamecon - use parallel port device model") Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 394ccbeb957c..5a672dcac0d8 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -931,29 +931,30 @@ static void gc_attach(struct parport *pp) { struct gc *gc; struct pardevice *pd; - int i; + int i, port_idx; int count = 0; int *pads, n_pads; struct pardev_cb gc_parport_cb; - for (i = 0; i < GC_MAX_PORTS; i++) { - if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) + for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) { + if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0) continue; - if (gc_cfg[i].args[0] == pp->number) + if (gc_cfg[port_idx].args[0] == pp->number) break; } - if (i == GC_MAX_PORTS) { + if (port_idx == GC_MAX_PORTS) { pr_debug("Not using parport%d.\n", pp->number); return; } - pads = gc_cfg[i].args + 1; - n_pads = gc_cfg[i].nargs - 1; + pads = gc_cfg[port_idx].args + 1; + n_pads = gc_cfg[port_idx].nargs - 1; gc_parport_cb.flags = PARPORT_FLAG_EXCL; - pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, i); + pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, + port_idx); if (!pd) { pr_err("parport busy already - lp.o loaded?\n"); return; @@ -985,7 +986,7 @@ static void gc_attach(struct parport *pp) goto err_free_gc; } - gc_base[i] = gc; + gc_base[port_idx] = gc; return; err_unreg_devs: -- cgit v1.2.3 From c65cf815653ec64e73d40819806c2d1aed91681e Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 5 Oct 2015 17:23:08 -0700 Subject: Input: turbografx - store object in correct index The variable i is used to check the port to attach to and we are supposed to save the reference of struct tgfx in the location given by tgfx_base[i]. But after finding out the index, i is getting modified again so we saved in a wrong index. Fixes: 4de27a638a99 ("Input: turbografx - use parallel port device model") Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/turbografx.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 01e8ea92b9ad..9f5bca26bd2f 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -162,27 +162,29 @@ static void tgfx_attach(struct parport *pp) struct tgfx *tgfx; struct input_dev *input_dev; struct pardevice *pd; - int i, j; + int i, j, port_idx; int *n_buttons, n_devs; struct pardev_cb tgfx_parport_cb; - for (i = 0; i < TGFX_MAX_PORTS; i++) { - if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0) + for (port_idx = 0; port_idx < TGFX_MAX_PORTS; port_idx++) { + if (tgfx_cfg[port_idx].nargs == 0 || + tgfx_cfg[port_idx].args[0] < 0) continue; - if (tgfx_cfg[i].args[0] == pp->number) + if (tgfx_cfg[port_idx].args[0] == pp->number) break; } - if (i == TGFX_MAX_PORTS) { + if (port_idx == TGFX_MAX_PORTS) { pr_debug("Not using parport%d.\n", pp->number); return; } - n_buttons = tgfx_cfg[i].args + 1; - n_devs = tgfx_cfg[i].nargs - 1; + n_buttons = tgfx_cfg[port_idx].args + 1; + n_devs = tgfx_cfg[port_idx].nargs - 1; tgfx_parport_cb.flags = PARPORT_FLAG_EXCL; - pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb, i); + pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb, + port_idx); if (!pd) { pr_err("parport busy already - lp.o loaded?\n"); return; @@ -250,7 +252,7 @@ static void tgfx_attach(struct parport *pp) goto err_free_tgfx; } - tgfx_base[i] = tgfx; + tgfx_base[port_idx] = tgfx; return; err_free_dev: -- cgit v1.2.3 From 33ca8ab97cbb676d11a4b026ad392c046893a6dc Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 29 Sep 2015 16:04:36 -0700 Subject: Input: parkbd - use parallel port device model Modify parkbd driver to use the new Parallel Port device model. Signed-off-by: Sudip Mukherjee Signed-off-by: Dmitry Torokhov --- drivers/input/serio/parkbd.c | 55 +++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index 1e8cd6f1fe9e..74bb17270255 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c @@ -141,19 +141,15 @@ static void parkbd_interrupt(void *dev_id) parkbd_last = jiffies; } -static int parkbd_getport(void) +static int parkbd_getport(struct parport *pp) { - struct parport *pp; + struct pardev_cb parkbd_parport_cb; - pp = parport_find_number(parkbd_pp_no); + parkbd_parport_cb.irq_func = parkbd_interrupt; + parkbd_parport_cb.flags = PARPORT_FLAG_EXCL; - if (pp == NULL) { - printk(KERN_ERR "parkbd: no such parport\n"); - return -ENODEV; - } - - parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL); - parport_put_port(pp); + parkbd_dev = parport_register_dev_model(pp, "parkbd", + &parkbd_parport_cb, 0); if (!parkbd_dev) return -ENODEV; @@ -183,19 +179,21 @@ static struct serio * __init parkbd_allocate_serio(void) return serio; } -static int __init parkbd_init(void) +static void parkbd_attach(struct parport *pp) { - int err; + if (pp->number != parkbd_pp_no) { + pr_debug("Not using parport%d.\n", pp->number); + return; + } - err = parkbd_getport(); - if (err) - return err; + if (parkbd_getport(pp)) + return; parkbd_port = parkbd_allocate_serio(); if (!parkbd_port) { parport_release(parkbd_dev); parport_unregister_device(parkbd_dev); - return -ENOMEM; + return; } parkbd_writelines(3); @@ -205,14 +203,35 @@ static int __init parkbd_init(void) printk(KERN_INFO "serio: PARKBD %s adapter on %s\n", parkbd_mode ? "AT" : "XT", parkbd_dev->port->name); - return 0; + return; } -static void __exit parkbd_exit(void) +static void parkbd_detach(struct parport *port) { + if (!parkbd_port || port->number != parkbd_pp_no) + return; + parport_release(parkbd_dev); serio_unregister_port(parkbd_port); parport_unregister_device(parkbd_dev); + parkbd_port = NULL; +} + +static struct parport_driver parkbd_parport_driver = { + .name = "parkbd", + .match_port = parkbd_attach, + .detach = parkbd_detach, + .devmodel = true, +}; + +static int __init parkbd_init(void) +{ + return parport_register_driver(&parkbd_parport_driver); +} + +static void __exit parkbd_exit(void) +{ + parport_unregister_driver(&parkbd_parport_driver); } module_init(parkbd_init); -- cgit v1.2.3 From c7efd123500b11568ce928a5cd91ad132ec36df5 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sat, 19 Sep 2015 11:34:30 -0700 Subject: Input: add support for ROHM BU21023/24 touchscreen This adds support for ROHM BU21023/24 Dual touch resistive touchscreens. Signed-off-by: Yoichi Yuasa Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 11 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/rohm_bu21023.c | 1218 ++++++++++++++++++++++++++++++ 3 files changed, 1230 insertions(+) create mode 100644 drivers/input/touchscreen/rohm_bu21023.c (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index eda89b6b7e11..771d95c11221 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1077,4 +1077,15 @@ config TOUCHSCREEN_COLIBRI_VF50 To compile this driver as a module, choose M here: the module will be called colibri_vf50_ts. +config TOUCHSCREEN_ROHM_BU21023 + tristate "ROHM BU21023/24 Dual touch support resistive touchscreens" + depends on I2C + help + Say Y here if you have a touchscreen using ROHM BU21023/24. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called bu21023_ts. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index baba189e3e16..17435c7e97e3 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -88,3 +88,4 @@ obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o +obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c new file mode 100644 index 000000000000..ba6024f93469 --- /dev/null +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -0,0 +1,1218 @@ +/* + * ROHM BU21023/24 Dual touch support resistive touch screen driver + * Copyright (C) 2012 ROHM CO.,LTD. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define BU21023_NAME "bu21023_ts" +#define BU21023_FIRMWARE_NAME "bu21023.bin" + +#define MAX_CONTACTS 2 + +#define AXIS_ADJUST 4 +#define AXIS_OFFSET 8 + +#define FIRMWARE_BLOCK_SIZE 32U +#define FIRMWARE_RETRY_MAX 4 + +#define SAMPLING_DELAY 12 /* msec */ + +#define CALIBRATION_RETRY_MAX 6 + +#define ROHM_TS_ABS_X_MIN 40 +#define ROHM_TS_ABS_X_MAX 990 +#define ROHM_TS_ABS_Y_MIN 160 +#define ROHM_TS_ABS_Y_MAX 920 +#define ROHM_TS_DISPLACEMENT_MAX 0 /* zero for infinite */ + +/* + * BU21023GUL/BU21023MUV/BU21024FV-M registers map + */ +#define VADOUT_YP_H 0x00 +#define VADOUT_YP_L 0x01 +#define VADOUT_XP_H 0x02 +#define VADOUT_XP_L 0x03 +#define VADOUT_YN_H 0x04 +#define VADOUT_YN_L 0x05 +#define VADOUT_XN_H 0x06 +#define VADOUT_XN_L 0x07 + +#define PRM1_X_H 0x08 +#define PRM1_X_L 0x09 +#define PRM1_Y_H 0x0a +#define PRM1_Y_L 0x0b +#define PRM2_X_H 0x0c +#define PRM2_X_L 0x0d +#define PRM2_Y_H 0x0e +#define PRM2_Y_L 0x0f + +#define MLT_PRM_MONI_X 0x10 +#define MLT_PRM_MONI_Y 0x11 + +#define DEBUG_MONI_1 0x12 +#define DEBUG_MONI_2 0x13 + +#define VADOUT_ZX_H 0x14 +#define VADOUT_ZX_L 0x15 +#define VADOUT_ZY_H 0x16 +#define VADOUT_ZY_L 0x17 + +#define Z_PARAM_H 0x18 +#define Z_PARAM_L 0x19 + +/* + * Value for VADOUT_*_L + */ +#define VADOUT_L_MASK 0x01 + +/* + * Value for PRM*_*_L + */ +#define PRM_L_MASK 0x01 + +#define POS_X1_H 0x20 +#define POS_X1_L 0x21 +#define POS_Y1_H 0x22 +#define POS_Y1_L 0x23 +#define POS_X2_H 0x24 +#define POS_X2_L 0x25 +#define POS_Y2_H 0x26 +#define POS_Y2_L 0x27 + +/* + * Value for POS_*_L + */ +#define POS_L_MASK 0x01 + +#define TOUCH 0x28 +#define TOUCH_DETECT 0x01 + +#define TOUCH_GESTURE 0x29 +#define SINGLE_TOUCH 0x01 +#define DUAL_TOUCH 0x03 +#define TOUCH_MASK 0x03 +#define CALIBRATION_REQUEST 0x04 +#define CALIBRATION_STATUS 0x08 +#define CALIBRATION_MASK 0x0c +#define GESTURE_SPREAD 0x10 +#define GESTURE_PINCH 0x20 +#define GESTURE_ROTATE_R 0x40 +#define GESTURE_ROTATE_L 0x80 + +#define INT_STATUS 0x2a +#define INT_MASK 0x3d +#define INT_CLEAR 0x3e + +/* + * Values for INT_* + */ +#define COORD_UPDATE 0x01 +#define CALIBRATION_DONE 0x02 +#define SLEEP_IN 0x04 +#define SLEEP_OUT 0x08 +#define PROGRAM_LOAD_DONE 0x10 +#define ERROR 0x80 +#define INT_ALL 0x9f + +#define ERR_STATUS 0x2b +#define ERR_MASK 0x3f + +/* + * Values for ERR_* + */ +#define ADC_TIMEOUT 0x01 +#define CPU_TIMEOUT 0x02 +#define CALIBRATION_ERR 0x04 +#define PROGRAM_LOAD_ERR 0x10 + +#define COMMON_SETUP1 0x30 +#define PROGRAM_LOAD_HOST 0x02 +#define PROGRAM_LOAD_EEPROM 0x03 +#define CENSOR_4PORT 0x04 +#define CENSOR_8PORT 0x00 /* Not supported by BU21023 */ +#define CALIBRATION_TYPE_DEFAULT 0x08 +#define CALIBRATION_TYPE_SPECIAL 0x00 +#define INT_ACTIVE_HIGH 0x10 +#define INT_ACTIVE_LOW 0x00 +#define AUTO_CALIBRATION 0x40 +#define MANUAL_CALIBRATION 0x00 +#define COMMON_SETUP1_DEFAULT 0x4e + +#define COMMON_SETUP2 0x31 +#define MAF_NONE 0x00 +#define MAF_1SAMPLE 0x01 +#define MAF_3SAMPLES 0x02 +#define MAF_5SAMPLES 0x03 +#define INV_Y 0x04 +#define INV_X 0x08 +#define SWAP_XY 0x10 + +#define COMMON_SETUP3 0x32 +#define EN_SLEEP 0x01 +#define EN_MULTI 0x02 +#define EN_GESTURE 0x04 +#define EN_INTVL 0x08 +#define SEL_STEP 0x10 +#define SEL_MULTI 0x20 +#define SEL_TBL_DEFAULT 0x40 + +#define INTERVAL_TIME 0x33 +#define INTERVAL_TIME_DEFAULT 0x10 + +#define STEP_X 0x34 +#define STEP_X_DEFAULT 0x41 + +#define STEP_Y 0x35 +#define STEP_Y_DEFAULT 0x8d + +#define OFFSET_X 0x38 +#define OFFSET_X_DEFAULT 0x0c + +#define OFFSET_Y 0x39 +#define OFFSET_Y_DEFAULT 0x0c + +#define THRESHOLD_TOUCH 0x3a +#define THRESHOLD_TOUCH_DEFAULT 0xa0 + +#define THRESHOLD_GESTURE 0x3b +#define THRESHOLD_GESTURE_DEFAULT 0x17 + +#define SYSTEM 0x40 +#define ANALOG_POWER_ON 0x01 +#define ANALOG_POWER_OFF 0x00 +#define CPU_POWER_ON 0x02 +#define CPU_POWER_OFF 0x00 + +#define FORCE_CALIBRATION 0x42 +#define FORCE_CALIBRATION_ON 0x01 +#define FORCE_CALIBRATION_OFF 0x00 + +#define CPU_FREQ 0x50 /* 10 / (reg + 1) MHz */ +#define CPU_FREQ_10MHZ 0x00 +#define CPU_FREQ_5MHZ 0x01 +#define CPU_FREQ_1MHZ 0x09 + +#define EEPROM_ADDR 0x51 + +#define CALIBRATION_ADJUST 0x52 +#define CALIBRATION_ADJUST_DEFAULT 0x00 + +#define THRESHOLD_SLEEP_IN 0x53 + +#define EVR_XY 0x56 +#define EVR_XY_DEFAULT 0x10 + +#define PRM_SWOFF_TIME 0x57 +#define PRM_SWOFF_TIME_DEFAULT 0x04 + +#define PROGRAM_VERSION 0x5f + +#define ADC_CTRL 0x60 +#define ADC_DIV_MASK 0x1f /* The minimum value is 4 */ +#define ADC_DIV_DEFAULT 0x08 + +#define ADC_WAIT 0x61 +#define ADC_WAIT_DEFAULT 0x0a + +#define SWCONT 0x62 +#define SWCONT_DEFAULT 0x0f + +#define EVR_X 0x63 +#define EVR_X_DEFAULT 0x86 + +#define EVR_Y 0x64 +#define EVR_Y_DEFAULT 0x64 + +#define TEST1 0x65 +#define DUALTOUCH_STABILIZE_ON 0x01 +#define DUALTOUCH_STABILIZE_OFF 0x00 +#define DUALTOUCH_REG_ON 0x20 +#define DUALTOUCH_REG_OFF 0x00 + +#define CALIBRATION_REG1 0x68 +#define CALIBRATION_REG1_DEFAULT 0xd9 + +#define CALIBRATION_REG2 0x69 +#define CALIBRATION_REG2_DEFAULT 0x36 + +#define CALIBRATION_REG3 0x6a +#define CALIBRATION_REG3_DEFAULT 0x32 + +#define EX_ADDR_H 0x70 +#define EX_ADDR_L 0x71 +#define EX_WDAT 0x72 +#define EX_RDAT 0x73 +#define EX_CHK_SUM1 0x74 +#define EX_CHK_SUM2 0x75 +#define EX_CHK_SUM3 0x76 + +struct rohm_ts_data { + struct i2c_client *client; + struct input_dev *input; + + bool initialized; + + unsigned int contact_count[MAX_CONTACTS + 1]; + int finger_count; + + u8 setup2; +}; + +/* + * rohm_i2c_burst_read - execute combined I2C message for ROHM BU21023/24 + * @client: Handle to ROHM BU21023/24 + * @start: Where to start read address from ROHM BU21023/24 + * @buf: Where to store read data from ROHM BU21023/24 + * @len: How many bytes to read + * + * Returns negative errno, else zero on success. + * + * Note + * In BU21023/24 burst read, stop condition is needed after "address write". + * Therefore, transmission is performed in 2 steps. + */ +static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf, + size_t len) +{ + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg[2]; + int i, ret = 0; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &start; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = len; + msg[1].buf = buf; + + i2c_lock_adapter(adap); + + for (i = 0; i < 2; i++) { + if (__i2c_transfer(adap, &msg[i], 1) < 0) { + ret = -EIO; + break; + } + } + + i2c_unlock_adapter(adap); + + return ret; +} + +static int rohm_ts_manual_calibration(struct rohm_ts_data *ts) +{ + struct i2c_client *client = ts->client; + struct device *dev = &client->dev; + u8 buf[33]; /* for PRM1_X_H(0x08)-TOUCH(0x28) */ + + int retry; + bool success = false; + bool first_time = true; + bool calibration_done; + + u8 reg1, reg2, reg3; + s32 reg1_orig, reg2_orig, reg3_orig; + s32 val; + + int calib_x = 0, calib_y = 0; + int reg_x, reg_y; + int err_x, err_y; + + int error, error2; + int i; + + reg1_orig = i2c_smbus_read_byte_data(client, CALIBRATION_REG1); + if (reg1_orig < 0) + return reg1_orig; + + reg2_orig = i2c_smbus_read_byte_data(client, CALIBRATION_REG2); + if (reg2_orig < 0) + return reg2_orig; + + reg3_orig = i2c_smbus_read_byte_data(client, CALIBRATION_REG3); + if (reg3_orig < 0) + return reg3_orig; + + error = i2c_smbus_write_byte_data(client, INT_MASK, + COORD_UPDATE | SLEEP_IN | SLEEP_OUT | + PROGRAM_LOAD_DONE); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, TEST1, + DUALTOUCH_STABILIZE_ON); + if (error) + goto out; + + for (retry = 0; retry < CALIBRATION_RETRY_MAX; retry++) { + /* wait 2 sampling for update */ + mdelay(2 * SAMPLING_DELAY); + +#define READ_CALIB_BUF(reg) buf[((reg) - PRM1_X_H)] + + error = rohm_i2c_burst_read(client, PRM1_X_H, buf, sizeof(buf)); + if (error) + goto out; + + if (READ_CALIB_BUF(TOUCH) & TOUCH_DETECT) + continue; + + if (first_time) { + /* generate calibration parameter */ + calib_x = ((int)READ_CALIB_BUF(PRM1_X_H) << 2 | + READ_CALIB_BUF(PRM1_X_L)) - AXIS_OFFSET; + calib_y = ((int)READ_CALIB_BUF(PRM1_Y_H) << 2 | + READ_CALIB_BUF(PRM1_Y_L)) - AXIS_OFFSET; + + error = i2c_smbus_write_byte_data(client, TEST1, + DUALTOUCH_STABILIZE_ON | DUALTOUCH_REG_ON); + if (error) + goto out; + + first_time = false; + } else { + /* generate adjustment parameter */ + err_x = (int)READ_CALIB_BUF(PRM1_X_H) << 2 | + READ_CALIB_BUF(PRM1_X_L); + err_y = (int)READ_CALIB_BUF(PRM1_Y_H) << 2 | + READ_CALIB_BUF(PRM1_Y_L); + + /* X axis ajust */ + if (err_x <= 4) + calib_x -= AXIS_ADJUST; + else if (err_x >= 60) + calib_x += AXIS_ADJUST; + + /* Y axis ajust */ + if (err_y <= 4) + calib_y -= AXIS_ADJUST; + else if (err_y >= 60) + calib_y += AXIS_ADJUST; + } + + /* generate calibration setting value */ + reg_x = calib_x + ((calib_x & 0x200) << 1); + reg_y = calib_y + ((calib_y & 0x200) << 1); + + /* convert for register format */ + reg1 = reg_x >> 3; + reg2 = (reg_y & 0x7) << 4 | (reg_x & 0x7); + reg3 = reg_y >> 3; + + error = i2c_smbus_write_byte_data(client, + CALIBRATION_REG1, reg1); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, + CALIBRATION_REG2, reg2); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, + CALIBRATION_REG3, reg3); + if (error) + goto out; + + /* + * force calibration sequcence + */ + error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION, + FORCE_CALIBRATION_OFF); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION, + FORCE_CALIBRATION_ON); + if (error) + goto out; + + /* clear all interrupts */ + error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff); + if (error) + goto out; + + /* + * Wait for the status change of calibration, max 10 sampling + */ + calibration_done = false; + + for (i = 0; i < 10; i++) { + mdelay(SAMPLING_DELAY); + + val = i2c_smbus_read_byte_data(client, TOUCH_GESTURE); + if (!(val & CALIBRATION_MASK)) { + calibration_done = true; + break; + } else if (val < 0) { + error = val; + goto out; + } + } + + if (calibration_done) { + val = i2c_smbus_read_byte_data(client, INT_STATUS); + if (val == CALIBRATION_DONE) { + success = true; + break; + } else if (val < 0) { + error = val; + goto out; + } + } else { + dev_warn(dev, "calibration timeout\n"); + } + } + + if (!success) { + error = i2c_smbus_write_byte_data(client, CALIBRATION_REG1, + reg1_orig); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, CALIBRATION_REG2, + reg2_orig); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, CALIBRATION_REG3, + reg3_orig); + if (error) + goto out; + + /* calibration data enable */ + error = i2c_smbus_write_byte_data(client, TEST1, + DUALTOUCH_STABILIZE_ON | + DUALTOUCH_REG_ON); + if (error) + goto out; + + /* wait 10 sampling */ + mdelay(10 * SAMPLING_DELAY); + + error = -EBUSY; + } + +out: + error2 = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL); + if (!error2) + /* Clear all interrupts */ + error2 = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff); + + return error ? error : error2; +} + +static const unsigned int untouch_threshold[3] = { 0, 1, 5 }; +static const unsigned int single_touch_threshold[3] = { 0, 0, 4 }; +static const unsigned int dual_touch_threshold[3] = { 10, 8, 0 }; + +static irqreturn_t rohm_ts_soft_irq(int irq, void *dev_id) +{ + struct rohm_ts_data *ts = dev_id; + struct i2c_client *client = ts->client; + struct input_dev *input_dev = ts->input; + struct device *dev = &client->dev; + + u8 buf[10]; /* for POS_X1_H(0x20)-TOUCH_GESTURE(0x29) */ + + struct input_mt_pos pos[MAX_CONTACTS]; + int slots[MAX_CONTACTS]; + u8 touch_flags; + unsigned int threshold; + int finger_count = -1; + int prev_finger_count = ts->finger_count; + int count; + int error; + int i; + + error = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL); + if (error) + return IRQ_HANDLED; + + /* Clear all interrupts */ + error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff); + if (error) + return IRQ_HANDLED; + +#define READ_POS_BUF(reg) buf[((reg) - POS_X1_H)] + + error = rohm_i2c_burst_read(client, POS_X1_H, buf, sizeof(buf)); + if (error) + return IRQ_HANDLED; + + touch_flags = READ_POS_BUF(TOUCH_GESTURE) & TOUCH_MASK; + if (touch_flags) { + /* generate coordinates */ + pos[0].x = ((s16)READ_POS_BUF(POS_X1_H) << 2) | + READ_POS_BUF(POS_X1_L); + pos[0].y = ((s16)READ_POS_BUF(POS_Y1_H) << 2) | + READ_POS_BUF(POS_Y1_L); + pos[1].x = ((s16)READ_POS_BUF(POS_X2_H) << 2) | + READ_POS_BUF(POS_X2_L); + pos[1].y = ((s16)READ_POS_BUF(POS_Y2_H) << 2) | + READ_POS_BUF(POS_Y2_L); + } + + switch (touch_flags) { + case 0: + threshold = untouch_threshold[prev_finger_count]; + if (++ts->contact_count[0] >= threshold) + finger_count = 0; + break; + + case SINGLE_TOUCH: + threshold = single_touch_threshold[prev_finger_count]; + if (++ts->contact_count[1] >= threshold) + finger_count = 1; + + if (finger_count == 1) { + if (pos[1].x != 0 && pos[1].y != 0) { + pos[0].x = pos[1].x; + pos[0].y = pos[1].y; + pos[1].x = 0; + pos[1].y = 0; + } + } + break; + + case DUAL_TOUCH: + threshold = dual_touch_threshold[prev_finger_count]; + if (++ts->contact_count[2] >= threshold) + finger_count = 2; + break; + + default: + dev_dbg(dev, + "Three or more touches are not supported\n"); + return IRQ_HANDLED; + } + + if (finger_count >= 0) { + if (prev_finger_count != finger_count) { + count = ts->contact_count[finger_count]; + memset(ts->contact_count, 0, sizeof(ts->contact_count)); + ts->contact_count[finger_count] = count; + } + + input_mt_assign_slots(input_dev, slots, pos, + finger_count, ROHM_TS_DISPLACEMENT_MAX); + + for (i = 0; i < finger_count; i++) { + input_mt_slot(input_dev, slots[i]); + input_mt_report_slot_state(input_dev, + MT_TOOL_FINGER, true); + input_report_abs(input_dev, + ABS_MT_POSITION_X, pos[i].x); + input_report_abs(input_dev, + ABS_MT_POSITION_Y, pos[i].y); + } + + input_mt_sync_frame(input_dev); + input_mt_report_pointer_emulation(input_dev, true); + input_sync(input_dev); + + ts->finger_count = finger_count; + } + + if (READ_POS_BUF(TOUCH_GESTURE) & CALIBRATION_REQUEST) { + error = rohm_ts_manual_calibration(ts); + if (error) + dev_warn(dev, "manual calibration failed: %d\n", + error); + } + + i2c_smbus_write_byte_data(client, INT_MASK, + CALIBRATION_DONE | SLEEP_OUT | SLEEP_IN | + PROGRAM_LOAD_DONE); + + return IRQ_HANDLED; +} + +static int rohm_ts_load_firmware(struct i2c_client *client, + const char *firmware_name) +{ + struct device *dev = &client->dev; + const struct firmware *fw; + s32 status; + unsigned int offset, len, xfer_len; + unsigned int retry = 0; + int error, error2; + + error = request_firmware(&fw, firmware_name, dev); + if (error) { + dev_err(dev, "unable to retrieve firmware %s: %d\n", + firmware_name, error); + return error; + } + + error = i2c_smbus_write_byte_data(client, INT_MASK, + COORD_UPDATE | CALIBRATION_DONE | + SLEEP_IN | SLEEP_OUT); + if (error) + goto out; + + do { + if (retry) { + dev_warn(dev, "retrying firmware load\n"); + + /* settings for retry */ + error = i2c_smbus_write_byte_data(client, EX_WDAT, 0); + if (error) + goto out; + } + + error = i2c_smbus_write_byte_data(client, EX_ADDR_H, 0); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, EX_ADDR_L, 0); + if (error) + goto out; + + error = i2c_smbus_write_byte_data(client, COMMON_SETUP1, + COMMON_SETUP1_DEFAULT); + if (error) + goto out; + + /* firmware load to the device */ + offset = 0; + len = fw->size; + + while (len) { + xfer_len = min(FIRMWARE_BLOCK_SIZE, len); + + error = i2c_smbus_write_i2c_block_data(client, EX_WDAT, + xfer_len, &fw->data[offset]); + if (error) + goto out; + + len -= xfer_len; + offset += xfer_len; + } + + /* check firmware load result */ + status = i2c_smbus_read_byte_data(client, INT_STATUS); + if (status < 0) { + error = status; + goto out; + } + + /* clear all interrupts */ + error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff); + if (error) + goto out; + + if (status == PROGRAM_LOAD_DONE) + break; + + error = -EIO; + } while (++retry >= FIRMWARE_RETRY_MAX); + +out: + error2 = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL); + + release_firmware(fw); + + return error ? error : error2; +} + +static ssize_t swap_xy_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rohm_ts_data *ts = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", !!(ts->setup2 & SWAP_XY)); +} + +static ssize_t swap_xy_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rohm_ts_data *ts = i2c_get_clientdata(client); + unsigned int val; + int error; + + error = kstrtouint(buf, 0, &val); + if (error) + return error; + + error = mutex_lock_interruptible(&ts->input->mutex); + if (error) + return error; + + if (val) + ts->setup2 |= SWAP_XY; + else + ts->setup2 &= ~SWAP_XY; + + if (ts->initialized) + error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2, + ts->setup2); + + mutex_unlock(&ts->input->mutex); + + return error ? error : count; +} + +static ssize_t inv_x_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rohm_ts_data *ts = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", !!(ts->setup2 & INV_X)); +} + +static ssize_t inv_x_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rohm_ts_data *ts = i2c_get_clientdata(client); + unsigned int val; + int error; + + error = kstrtouint(buf, 0, &val); + if (error) + return error; + + error = mutex_lock_interruptible(&ts->input->mutex); + if (error) + return error; + + if (val) + ts->setup2 |= INV_X; + else + ts->setup2 &= ~INV_X; + + if (ts->initialized) + error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2, + ts->setup2); + + mutex_unlock(&ts->input->mutex); + + return error ? error : count; +} + +static ssize_t inv_y_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rohm_ts_data *ts = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", !!(ts->setup2 & INV_Y)); +} + +static ssize_t inv_y_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rohm_ts_data *ts = i2c_get_clientdata(client); + unsigned int val; + int error; + + error = kstrtouint(buf, 0, &val); + if (error) + return error; + + error = mutex_lock_interruptible(&ts->input->mutex); + if (error) + return error; + + if (val) + ts->setup2 |= INV_Y; + else + ts->setup2 &= ~INV_Y; + + if (ts->initialized) + error = i2c_smbus_write_byte_data(client, COMMON_SETUP2, + ts->setup2); + + mutex_unlock(&ts->input->mutex); + + return error ? error : count; +} + +static DEVICE_ATTR_RW(swap_xy); +static DEVICE_ATTR_RW(inv_x); +static DEVICE_ATTR_RW(inv_y); + +static struct attribute *rohm_ts_attrs[] = { + &dev_attr_swap_xy.attr, + &dev_attr_inv_x.attr, + &dev_attr_inv_y.attr, + NULL, +}; + +static const struct attribute_group rohm_ts_attr_group = { + .attrs = rohm_ts_attrs, +}; + +static int rohm_ts_device_init(struct i2c_client *client, u8 setup2) +{ + struct device *dev = &client->dev; + int error; + + disable_irq(client->irq); + + /* + * Wait 200usec for reset + */ + udelay(200); + + /* Release analog reset */ + error = i2c_smbus_write_byte_data(client, SYSTEM, + ANALOG_POWER_ON | CPU_POWER_OFF); + if (error) + return error; + + /* Waiting for the analog warm-up, max. 200usec */ + udelay(200); + + /* clear all interrupts */ + error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, EX_WDAT, 0); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, COMMON_SETUP1, 0); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, COMMON_SETUP2, setup2); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, COMMON_SETUP3, + SEL_TBL_DEFAULT | EN_MULTI); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, THRESHOLD_GESTURE, + THRESHOLD_GESTURE_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, INTERVAL_TIME, + INTERVAL_TIME_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, CPU_FREQ, CPU_FREQ_10MHZ); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, PRM_SWOFF_TIME, + PRM_SWOFF_TIME_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, ADC_CTRL, ADC_DIV_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, ADC_WAIT, ADC_WAIT_DEFAULT); + if (error) + return error; + + /* + * Panel setup, these values change with the panel. + */ + error = i2c_smbus_write_byte_data(client, STEP_X, STEP_X_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, STEP_Y, STEP_Y_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, OFFSET_X, OFFSET_X_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, OFFSET_Y, OFFSET_Y_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, THRESHOLD_TOUCH, + THRESHOLD_TOUCH_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, EVR_XY, EVR_XY_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, EVR_X, EVR_X_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, EVR_Y, EVR_Y_DEFAULT); + if (error) + return error; + + /* Fixed value settings */ + error = i2c_smbus_write_byte_data(client, CALIBRATION_ADJUST, + CALIBRATION_ADJUST_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, SWCONT, SWCONT_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, TEST1, + DUALTOUCH_STABILIZE_ON | + DUALTOUCH_REG_ON); + if (error) + return error; + + error = rohm_ts_load_firmware(client, BU21023_FIRMWARE_NAME); + if (error) { + dev_err(dev, "failed to load firmware: %d\n", error); + return error; + } + + /* + * Manual calibration results are not changed in same environment. + * If the force calibration is performed, + * the controller will not require calibration request interrupt + * when the typical values are set to the calibration registers. + */ + error = i2c_smbus_write_byte_data(client, CALIBRATION_REG1, + CALIBRATION_REG1_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, CALIBRATION_REG2, + CALIBRATION_REG2_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, CALIBRATION_REG3, + CALIBRATION_REG3_DEFAULT); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION, + FORCE_CALIBRATION_OFF); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, FORCE_CALIBRATION, + FORCE_CALIBRATION_ON); + if (error) + return error; + + /* Clear all interrupts */ + error = i2c_smbus_write_byte_data(client, INT_CLEAR, 0xff); + if (error) + return error; + + /* Enable coordinates update interrupt */ + error = i2c_smbus_write_byte_data(client, INT_MASK, + CALIBRATION_DONE | SLEEP_OUT | + SLEEP_IN | PROGRAM_LOAD_DONE); + if (error) + return error; + + error = i2c_smbus_write_byte_data(client, ERR_MASK, + PROGRAM_LOAD_ERR | CPU_TIMEOUT | + ADC_TIMEOUT); + if (error) + return error; + + /* controller CPU power on */ + error = i2c_smbus_write_byte_data(client, SYSTEM, + ANALOG_POWER_ON | CPU_POWER_ON); + + enable_irq(client->irq); + + return error; +} + +static int rohm_ts_power_off(struct i2c_client *client) +{ + int error; + + error = i2c_smbus_write_byte_data(client, SYSTEM, + ANALOG_POWER_ON | CPU_POWER_OFF); + if (error) { + dev_err(&client->dev, + "failed to power off device CPU: %d\n", error); + return error; + } + + error = i2c_smbus_write_byte_data(client, SYSTEM, + ANALOG_POWER_OFF | CPU_POWER_OFF); + if (error) + dev_err(&client->dev, + "failed to power off the device: %d\n", error); + + return error; +} + +static int rohm_ts_open(struct input_dev *input_dev) +{ + struct rohm_ts_data *ts = input_get_drvdata(input_dev); + struct i2c_client *client = ts->client; + int error; + + if (!ts->initialized) { + error = rohm_ts_device_init(client, ts->setup2); + if (error) { + dev_err(&client->dev, + "device initialization failed: %d\n", error); + return error; + } + + ts->initialized = true; + } + + return 0; +} + +static void rohm_ts_close(struct input_dev *input_dev) +{ + struct rohm_ts_data *ts = input_get_drvdata(input_dev); + + rohm_ts_power_off(ts->client); + + ts->initialized = false; +} + +static void rohm_ts_remove_sysfs_group(void *_dev) +{ + struct device *dev = _dev; + + sysfs_remove_group(&dev->kobj, &rohm_ts_attr_group); +} + +static int rohm_bu21023_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct rohm_ts_data *ts; + struct input_dev *input; + int error; + + if (!client->irq) { + dev_err(dev, "IRQ is not assigned\n"); + return -EINVAL; + } + + if (!client->adapter->algo->master_xfer) { + dev_err(dev, "I2C level transfers not supported\n"); + return -EOPNOTSUPP; + } + + /* Turn off CPU just in case */ + error = rohm_ts_power_off(client); + if (error) + return error; + + ts = devm_kzalloc(dev, sizeof(struct rohm_ts_data), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + ts->client = client; + ts->setup2 = MAF_1SAMPLE; + i2c_set_clientdata(client, ts); + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + + input->name = BU21023_NAME; + input->id.bustype = BUS_I2C; + input->open = rohm_ts_open; + input->close = rohm_ts_close; + + ts->input = input; + input_set_drvdata(input, ts); + + input_set_abs_params(input, ABS_MT_POSITION_X, + ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, + ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0); + + error = input_mt_init_slots(input, MAX_CONTACTS, + INPUT_MT_DIRECT | INPUT_MT_TRACK | + INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(dev, "failed to multi touch slots initialization\n"); + return error; + } + + error = devm_request_threaded_irq(dev, client->irq, + NULL, rohm_ts_soft_irq, + IRQF_ONESHOT, client->name, ts); + if (error) { + dev_err(dev, "failed to request IRQ: %d\n", error); + return error; + } + + error = input_register_device(input); + if (error) { + dev_err(dev, "failed to register input device: %d\n", error); + return error; + } + + error = sysfs_create_group(&dev->kobj, &rohm_ts_attr_group); + if (error) { + dev_err(dev, "failed to create sysfs group: %d\n", error); + return error; + } + + error = devm_add_action(dev, rohm_ts_remove_sysfs_group, dev); + if (error) { + rohm_ts_remove_sysfs_group(dev); + dev_err(&client->dev, + "Failed to add sysfs cleanup action: %d\n", + error); + return error; + } + + return error; +} + +static const struct i2c_device_id rohm_bu21023_i2c_id[] = { + { BU21023_NAME, 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id); + +static struct i2c_driver rohm_bu21023_i2c_driver = { + .driver = { + .name = BU21023_NAME, + }, + .probe = rohm_bu21023_i2c_probe, + .id_table = rohm_bu21023_i2c_id, +}; +module_i2c_driver(rohm_bu21023_i2c_driver); + +MODULE_DESCRIPTION("ROHM BU21023/24 Touchscreen driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("ROHM Co., Ltd."); -- cgit v1.2.3 From 5b21e3c740b770fb2548a5a8ea66e544d114d0a8 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 6 Oct 2015 15:23:36 -0700 Subject: Input: joydev - fix possible ERR_PTR() dereferencing Commit 5702222c9a7a ("Input: joydev - use memdup_user() to duplicate memory from user-space") changed the kmalloc() and copy_from_user() with a single call to memdup_user() but wrongly used the same error path than the old code in which the buffer allocated by kmalloc() was freed if copy_from_user() failed. This is of course wrong since if memdup_user() fails, no memory was allocated and the error in the error-valued pointer should be returned. Fixes: 5702222c9a7a ("Input: joydev - use memdup_user() to duplicate memory from user-space") Reported-by: Dan Carpenter Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/joydev.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index e3dcd4abae18..5d11fea3c8ec 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -445,10 +445,8 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, /* Validate the map. */ abspam = memdup_user(argp, len); - if (IS_ERR(abspam)) { - retval = PTR_ERR(abspam); - goto out; - } + if (IS_ERR(abspam)) + return PTR_ERR(abspam); for (i = 0; i < joydev->nabs; i++) { if (abspam[i] > ABS_MAX) { @@ -478,10 +476,8 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, /* Validate the map. */ keypam = memdup_user(argp, len); - if (IS_ERR(keypam)) { - retval = PTR_ERR(keypam); - goto out; - } + if (IS_ERR(keypam)) + return PTR_ERR(keypam); for (i = 0; i < joydev->nkey; i++) { if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { -- cgit v1.2.3 From 8b58cc36b11bafb9305db2417eab1eb47a212082 Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Tue, 6 Oct 2015 15:24:34 -0700 Subject: Input: edt-ft5x06 - do not call desc_to_gpio for invalid gpios Since reset and wake pin are optional the gpio structure for those pins may be null. Therefore, they can't be blindly passed to desc_to_gpio. Reported-by: Dan Carpenter Signed-off-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 7239c314c9e9..a8640c7b6713 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -987,8 +987,9 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, dev_dbg(&client->dev, "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n", - client->irq, desc_to_gpio(tsdata->wake_gpio), - desc_to_gpio(tsdata->reset_gpio)); + client->irq, + tsdata->wake_gpio ? desc_to_gpio(tsdata->wake_gpio) : -1, + tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1); return 0; -- cgit v1.2.3 From 726d0d407b9a06b4f30053b33ae7d5edec8d5095 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 6 Oct 2015 15:37:02 -0700 Subject: Input: ft6236 - do not explicitly set driver's owner There is no need to explicitly set .owner for the driver, the core will do it for us. Signed-off-by: Fengguang Wu Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ft6236.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ft6236.c b/drivers/input/touchscreen/ft6236.c index cccae193668e..a394cd48dd3c 100644 --- a/drivers/input/touchscreen/ft6236.c +++ b/drivers/input/touchscreen/ft6236.c @@ -313,7 +313,6 @@ MODULE_DEVICE_TABLE(i2c, ft6236_id); static struct i2c_driver ft6236_driver = { .driver = { .name = "ft6236", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(ft6236_of_match), }, .probe = ft6236_probe, -- cgit v1.2.3 From 10fbb8f56b2f0c13e1f9da9aad45ede6a4c2fb51 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 6 Oct 2015 17:00:36 -0700 Subject: Input: ft6236 - change module license string to match copyright notice The copyright/license notice says that the code is licensed under GPL v2 only (not GPL v2+), so let's use proper string in MODULE_LICENSE(). Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ft6236.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ft6236.c b/drivers/input/touchscreen/ft6236.c index a394cd48dd3c..d240d2e212bd 100644 --- a/drivers/input/touchscreen/ft6236.c +++ b/drivers/input/touchscreen/ft6236.c @@ -323,4 +323,4 @@ module_i2c_driver(ft6236_driver); MODULE_AUTHOR("Sean Cross "); MODULE_AUTHOR("Noralf Trønnes "); MODULE_DESCRIPTION("FocalTech FT6236 TouchScreen driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 39a7a88872df98f0c3c50fe278fd1a1f597afd95 Mon Sep 17 00:00:00 2001 From: Erik Lundgren Date: Tue, 6 Oct 2015 17:04:11 -0700 Subject: Input: xpad - add Covert Forces edition of the Xbox One controller It is identical to the Xbox One controller but has a different product ID. Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f8850f9cb331..c3ba5bee1582 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -125,6 +125,7 @@ static const struct xpad_device { { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02dd, "Microsoft X-Box One pad (Covert Forces)", 0, XTYPE_XBOXONE }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, -- cgit v1.2.3 From 470446ecef213b17b2c01df9879102948d77f999 Mon Sep 17 00:00:00 2001 From: Dario Scarpa Date: Tue, 6 Oct 2015 17:04:36 -0700 Subject: Input: xpad - fix Razer Atrox Arcade Stick button mapping The "Razer Atrox Arcade Stick" features 10 buttons, and two of them (LT/RT) don't work properly. Change its definition in xpad_device[] (mapping field) to fix. Signed-off-by: Dario Scarpa Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index c3ba5bee1582..e3b393c3e696 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -205,7 +205,7 @@ static const struct xpad_device { { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, - { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, -- cgit v1.2.3 From 1f6f02b728eef0d937d5138ae60dbf8fbd045f3e Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Tue, 6 Oct 2015 17:06:16 -0700 Subject: Input: xpad - clarify LED enumeration Rename led_no -> pad_nr: the number stored there is not the LED number - it gets translated later on to a LED number in xpad_identify_controller; Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index e3b393c3e696..5257194ef0c0 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -345,7 +345,7 @@ struct usb_xpad { int mapping; /* map d-pad to buttons or to axes */ int xtype; /* type of xbox device */ - unsigned long led_no; /* led to lit on xbox360 controllers */ + unsigned long pad_nr; /* the order x360 pads were attached */ }; /* @@ -357,7 +357,6 @@ struct usb_xpad { * The used report descriptor was taken from ITO Takayukis website: * http://euc.jp/periphs/xbox-controller.ja.html */ - static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { struct input_dev *dev = xpad->dev; @@ -506,7 +505,6 @@ static void xpad_identify_controller(struct usb_xpad *xpad); * 01.1 - Pad state (Bytes 4+) valid * */ - static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { /* Presence change */ @@ -891,6 +889,7 @@ struct xpad_led { }; /** + * set the LEDs on Xbox360 / Wireless Controllers * @param command * 0: off * 1: all blink, then previous setting @@ -943,10 +942,13 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command) mutex_unlock(&xpad->odata_mutex); } +/* + * Light up the segment corresponding to the pad number on + * Xbox 360 Controllers. + */ static void xpad_identify_controller(struct usb_xpad *xpad) { - /* Light up the segment corresponding to controller number */ - xpad_send_led_command(xpad, (xpad->led_no % 4) + 2); + xpad_send_led_command(xpad, (xpad->pad_nr % 4) + 2); } static void xpad_led_set(struct led_classdev *led_cdev, @@ -972,9 +974,9 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (!led) return -ENOMEM; - xpad->led_no = atomic_inc_return(&led_seq); + xpad->pad_nr = atomic_inc_return(&led_seq); - snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->led_no); + snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->pad_nr); led->xpad = xpad; led_cdev = &led->led_cdev; -- cgit v1.2.3 From e3b651745a03810efffd7ebf2a9b5be65fb70ec3 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 10:00:49 -0700 Subject: Input: xpad - use ida() for finding the pad_nr The pad_nr corresponds to the lit up LED on the controller. Therefore there should be no gaps when enumerating. Currently a LED is only re-assigned after a controller is re-connected 4 times. This patch uses ida to track connected pads - this way we can re-assign freed up pad number immediately. Consider the following case: 1. pad A is connected and gets pad_nr = 0 2. pad B is connected and gets pad_nr = 1 3. pad A is disconnected 4. pad A is connected again using ida_simple_get() controller A now correctly gets pad_nr = 0 again. Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 5257194ef0c0..9e85a234d5f1 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -243,7 +243,6 @@ static const signed short xpad_btn_triggers[] = { -1 }; - static const signed short xpad360_btn[] = { /* buttons for x360 controller */ BTN_TL, BTN_TR, /* Button LB/RB */ BTN_MODE, /* The big X button */ @@ -345,7 +344,7 @@ struct usb_xpad { int mapping; /* map d-pad to buttons or to axes */ int xtype; /* type of xbox device */ - unsigned long pad_nr; /* the order x360 pads were attached */ + int pad_nr; /* the order x360 pads were attached */ }; /* @@ -881,6 +880,9 @@ static int xpad_init_ff(struct usb_xpad *xpad) { return 0; } #if defined(CONFIG_JOYSTICK_XPAD_LEDS) #include +#include + +static DEFINE_IDA(xpad_pad_seq); struct xpad_led { char name[16]; @@ -962,7 +964,6 @@ static void xpad_led_set(struct led_classdev *led_cdev, static int xpad_led_probe(struct usb_xpad *xpad) { - static atomic_t led_seq = ATOMIC_INIT(-1); struct xpad_led *led; struct led_classdev *led_cdev; int error; @@ -974,9 +975,13 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (!led) return -ENOMEM; - xpad->pad_nr = atomic_inc_return(&led_seq); + xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL); + if (xpad->pad_nr < 0) { + error = xpad->pad_nr; + goto err_free_mem; + } - snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->pad_nr); + snprintf(led->name, sizeof(led->name), "xpad%d", xpad->pad_nr); led->xpad = xpad; led_cdev = &led->led_cdev; @@ -984,16 +989,19 @@ static int xpad_led_probe(struct usb_xpad *xpad) led_cdev->brightness_set = xpad_led_set; error = led_classdev_register(&xpad->udev->dev, led_cdev); - if (error) { - kfree(led); - xpad->led = NULL; - return error; - } + if (error) + goto err_free_id; /* Light up the segment corresponding to controller number */ xpad_identify_controller(xpad); - return 0; + +err_free_id: + ida_simple_remove(&xpad_pad_seq, xpad->pad_nr); +err_free_mem: + kfree(led); + xpad->led = NULL; + return error; } static void xpad_led_disconnect(struct usb_xpad *xpad) @@ -1002,6 +1010,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) if (xpad_led) { led_classdev_unregister(&xpad_led->led_cdev); + ida_simple_remove(&xpad_pad_seq, xpad->pad_nr); kfree(xpad_led); } } @@ -1011,7 +1020,6 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { } static void xpad_identify_controller(struct usb_xpad *xpad) { } #endif - static int xpad_open(struct input_dev *dev) { struct usb_xpad *xpad = input_get_drvdata(dev); -- cgit v1.2.3 From a306a65f46acb040d208523592a2d34f67d47a61 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Tue, 6 Oct 2015 17:07:31 -0700 Subject: Input: xpad - remove needless bulk out URB used for LED setup This code was probably wrong ever since and is redundant with xpad_send_led_command. Both try to send a similar command to the xbox360 controller. However xpad_send_led_command correctly uses the pad_nr instead of bInterfaceNumber to select the led and re-uses the irq_out URB instead of creating a new one. Note that this change only affects the two supported wireless controllers. Tested using the xbox360 wireless controller (PC). Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 79 +------------------------------------------ 1 file changed, 1 insertion(+), 78 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 9e85a234d5f1..946bf3c74834 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -328,9 +328,6 @@ struct usb_xpad { unsigned char *idata; /* input data */ dma_addr_t idata_dma; - struct urb *bulk_out; - unsigned char *bdata; - struct urb *irq_out; /* urb for interrupt out report */ unsigned char *odata; /* output data */ dma_addr_t odata_dma; @@ -510,7 +507,6 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha if (data[0] & 0x08) { if (data[1] & 0x80) { xpad->pad_present = 1; - usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); /* * Light up the segment corresponding to * controller number. @@ -672,28 +668,6 @@ exit: __func__, retval); } -static void xpad_bulk_out(struct urb *urb) -{ - struct usb_xpad *xpad = urb->context; - struct device *dev = &xpad->intf->dev; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dev_dbg(dev, "%s - urb shutting down with status: %d\n", - __func__, urb->status); - break; - default: - dev_dbg(dev, "%s - nonzero urb status received: %d\n", - __func__, urb->status); - } -} - static void xpad_irq_out(struct urb *urb) { struct usb_xpad *xpad = urb->context; @@ -1229,52 +1203,6 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id usb_set_intfdata(intf, xpad); if (xpad->xtype == XTYPE_XBOX360W) { - /* - * Setup the message to set the LEDs on the - * controller when it shows up - */ - xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->bulk_out) { - error = -ENOMEM; - goto fail7; - } - - xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); - if (!xpad->bdata) { - error = -ENOMEM; - goto fail8; - } - - xpad->bdata[2] = 0x08; - switch (intf->cur_altsetting->desc.bInterfaceNumber) { - case 0: - xpad->bdata[3] = 0x42; - break; - case 2: - xpad->bdata[3] = 0x43; - break; - case 4: - xpad->bdata[3] = 0x44; - break; - case 6: - xpad->bdata[3] = 0x45; - } - - ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; - if (usb_endpoint_is_bulk_out(ep_irq_in)) { - usb_fill_bulk_urb(xpad->bulk_out, udev, - usb_sndbulkpipe(udev, - ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, - xpad_bulk_out, xpad); - } else { - usb_fill_int_urb(xpad->bulk_out, udev, - usb_sndintpipe(udev, - ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, - xpad_bulk_out, xpad, 0); - } - /* * Submit the int URB immediately rather than waiting for open * because we get status messages from the device whether @@ -1285,13 +1213,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->dev = xpad->udev; error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); if (error) - goto fail9; + goto fail7; } return 0; - fail9: kfree(xpad->bdata); - fail8: usb_free_urb(xpad->bulk_out); fail7: input_unregister_device(input_dev); input_dev = NULL; fail6: xpad_led_disconnect(xpad); @@ -1315,8 +1241,6 @@ static void xpad_disconnect(struct usb_interface *intf) xpad_deinit_output(xpad); if (xpad->xtype == XTYPE_XBOX360W) { - usb_kill_urb(xpad->bulk_out); - usb_free_urb(xpad->bulk_out); usb_kill_urb(xpad->irq_in); } @@ -1324,7 +1248,6 @@ static void xpad_disconnect(struct usb_interface *intf) usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - kfree(xpad->bdata); kfree(xpad); usb_set_intfdata(intf, NULL); -- cgit v1.2.3 From 060081529c64cfa9baa2748a4b949159e700da0d Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 09:32:55 -0700 Subject: Input: xpad - factor out URB submission in xpad_play_effect Move submission logic to a single point at the end of the function. This makes it easy to add locking/ queuing code later on. Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 140 +++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 71 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 946bf3c74834..67ab85a4fd0e 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -762,80 +762,78 @@ static void xpad_deinit_output(struct usb_xpad *xpad) static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { struct usb_xpad *xpad = input_get_drvdata(dev); + __u16 strong; + __u16 weak; - if (effect->type == FF_RUMBLE) { - __u16 strong = effect->u.rumble.strong_magnitude; - __u16 weak = effect->u.rumble.weak_magnitude; - - switch (xpad->xtype) { - - case XTYPE_XBOX: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x06; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; /* left actuator */ - xpad->odata[4] = 0x00; - xpad->odata[5] = weak / 256; /* right actuator */ - xpad->irq_out->transfer_buffer_length = 6; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOX360: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x08; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; /* left actuator? */ - xpad->odata[4] = weak / 256; /* right actuator? */ - xpad->odata[5] = 0x00; - xpad->odata[6] = 0x00; - xpad->odata[7] = 0x00; - xpad->irq_out->transfer_buffer_length = 8; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOX360W: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x01; - xpad->odata[2] = 0x0F; - xpad->odata[3] = 0xC0; - xpad->odata[4] = 0x00; - xpad->odata[5] = strong / 256; - xpad->odata[6] = weak / 256; - xpad->odata[7] = 0x00; - xpad->odata[8] = 0x00; - xpad->odata[9] = 0x00; - xpad->odata[10] = 0x00; - xpad->odata[11] = 0x00; - xpad->irq_out->transfer_buffer_length = 12; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOXONE: - xpad->odata[0] = 0x09; /* activate rumble */ - xpad->odata[1] = 0x08; - xpad->odata[2] = 0x00; - xpad->odata[3] = 0x08; /* continuous effect */ - xpad->odata[4] = 0x00; /* simple rumble mode */ - xpad->odata[5] = 0x03; /* L and R actuator only */ - xpad->odata[6] = 0x00; /* TODO: LT actuator */ - xpad->odata[7] = 0x00; /* TODO: RT actuator */ - xpad->odata[8] = strong / 256; /* left actuator */ - xpad->odata[9] = weak / 256; /* right actuator */ - xpad->odata[10] = 0x80; /* length of pulse */ - xpad->odata[11] = 0x00; /* stop period of pulse */ - xpad->irq_out->transfer_buffer_length = 12; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - default: - dev_dbg(&xpad->dev->dev, - "%s - rumble command sent to unsupported xpad type: %d\n", - __func__, xpad->xtype); - return -1; - } + if (effect->type != FF_RUMBLE) + return 0; + + strong = effect->u.rumble.strong_magnitude; + weak = effect->u.rumble.weak_magnitude; + + switch (xpad->xtype) { + case XTYPE_XBOX: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x06; + xpad->odata[2] = 0x00; + xpad->odata[3] = strong / 256; /* left actuator */ + xpad->odata[4] = 0x00; + xpad->odata[5] = weak / 256; /* right actuator */ + xpad->irq_out->transfer_buffer_length = 6; + break; + + case XTYPE_XBOX360: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x08; + xpad->odata[2] = 0x00; + xpad->odata[3] = strong / 256; /* left actuator? */ + xpad->odata[4] = weak / 256; /* right actuator? */ + xpad->odata[5] = 0x00; + xpad->odata[6] = 0x00; + xpad->odata[7] = 0x00; + xpad->irq_out->transfer_buffer_length = 8; + break; + + case XTYPE_XBOX360W: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x01; + xpad->odata[2] = 0x0F; + xpad->odata[3] = 0xC0; + xpad->odata[4] = 0x00; + xpad->odata[5] = strong / 256; + xpad->odata[6] = weak / 256; + xpad->odata[7] = 0x00; + xpad->odata[8] = 0x00; + xpad->odata[9] = 0x00; + xpad->odata[10] = 0x00; + xpad->odata[11] = 0x00; + xpad->irq_out->transfer_buffer_length = 12; + break; + + case XTYPE_XBOXONE: + xpad->odata[0] = 0x09; /* activate rumble */ + xpad->odata[1] = 0x08; + xpad->odata[2] = 0x00; + xpad->odata[3] = 0x08; /* continuous effect */ + xpad->odata[4] = 0x00; /* simple rumble mode */ + xpad->odata[5] = 0x03; /* L and R actuator only */ + xpad->odata[6] = 0x00; /* TODO: LT actuator */ + xpad->odata[7] = 0x00; /* TODO: RT actuator */ + xpad->odata[8] = strong / 256; /* left actuator */ + xpad->odata[9] = weak / 256; /* right actuator */ + xpad->odata[10] = 0x80; /* length of pulse */ + xpad->odata[11] = 0x00; /* stop period of pulse */ + xpad->irq_out->transfer_buffer_length = 12; + break; + + default: + dev_dbg(&xpad->dev->dev, + "%s - rumble command sent to unsupported xpad type: %d\n", + __func__, xpad->xtype); + return -EINVAL; } - return 0; + return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); } static int xpad_init_ff(struct usb_xpad *xpad) -- cgit v1.2.3 From 5ee8bda943de20017636845a5c8d7069a4a283b8 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 09:33:52 -0700 Subject: Input: xpad - x360w: report dpad as buttons and axes as discussed here[0], x360w is the only pad that maps dpad_to_button. This is bad for downstream developers as they have to differ between x360 and x360w which is not intuitive. This patch implements the suggested solution of exposing the dpad both as axes and as buttons. This retains backward compatibility with software already dealing with the difference while makes new software work as expected across x360/ x360w pads. [0] http://www.spinics.net/lists/linux-input/msg34421.html Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 67ab85a4fd0e..bd669c1ff380 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -435,7 +435,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08); input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01); input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02); - } else { + } + + /* + * This should be a simple else block. However historically + * xbox360w has mapped DPAD to buttons while xbox360 did not. This + * made no sense, but now we can not just switch back and have to + * support both behaviors. + */ + if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) || + xpad->xtype == XTYPE_XBOX360W) { input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); input_report_abs(dev, ABS_HAT0Y, @@ -1158,7 +1167,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { for (i = 0; xpad_btn_pad[i] >= 0; i++) __set_bit(xpad_btn_pad[i], input_dev->keybit); - } else { + } + + /* + * This should be a simple else block. However historically + * xbox360w has mapped DPAD to buttons while xbox360 did not. This + * made no sense, but now we can not just switch back and have to + * support both behaviors. + */ + if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) || + xpad->xtype == XTYPE_XBOX360W) { for (i = 0; xpad_abs_pad[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs_pad[i]); } -- cgit v1.2.3 From b8154002cbdfde1aed2f86bd27f5e2c7e832cabb Mon Sep 17 00:00:00 2001 From: "Pierre-Loup A. Griffais" Date: Sat, 10 Oct 2015 09:34:17 -0700 Subject: Input: xpad - move the input device creation to a new function To allow us to later create / destroy the input device from the urb callback, we need to initialize/ deinitialize the input device from a separate function. So pull that logic out now to make later patches more "obvious" as to what they do. Signed-off-by: "Pierre-Loup A. Griffais" Signed-off-by: Greg Kroah-Hartman Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 211 ++++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 92 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index bd669c1ff380..486db7a1d99a 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -342,6 +342,7 @@ struct usb_xpad { int mapping; /* map d-pad to buttons or to axes */ int xtype; /* type of xbox device */ int pad_nr; /* the order x360 pads were attached */ + const char *name; /* name of the device */ }; /* @@ -1060,91 +1061,36 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) } } -static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) +static void xpad_deinit_input(struct usb_xpad *xpad) +{ + xpad_led_disconnect(xpad); + input_unregister_device(xpad->dev); +} + +static int xpad_init_input(struct usb_xpad *xpad) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_xpad *xpad; struct input_dev *input_dev; - struct usb_endpoint_descriptor *ep_irq_in; - int ep_irq_in_idx; int i, error; - for (i = 0; xpad_device[i].idVendor; i++) { - if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && - (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) - break; - } - - if (xpad_device[i].xtype == XTYPE_XBOXONE && - intf->cur_altsetting->desc.bInterfaceNumber != 0) { - /* - * The Xbox One controller lists three interfaces all with the - * same interface class, subclass and protocol. Differentiate by - * interface number. - */ - return -ENODEV; - } - - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); input_dev = input_allocate_device(); - if (!xpad || !input_dev) { - error = -ENOMEM; - goto fail1; - } - - xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->idata_dma); - if (!xpad->idata) { - error = -ENOMEM; - goto fail1; - } - - xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->irq_in) { - error = -ENOMEM; - goto fail2; - } - - xpad->udev = udev; - xpad->intf = intf; - xpad->mapping = xpad_device[i].mapping; - xpad->xtype = xpad_device[i].xtype; - - if (xpad->xtype == XTYPE_UNKNOWN) { - if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { - if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) - xpad->xtype = XTYPE_XBOX360W; - else - xpad->xtype = XTYPE_XBOX360; - } else - xpad->xtype = XTYPE_XBOX; - - if (dpad_to_buttons) - xpad->mapping |= MAP_DPAD_TO_BUTTONS; - if (triggers_to_buttons) - xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; - if (sticks_to_null) - xpad->mapping |= MAP_STICKS_TO_NULL; - } + if (!input_dev) + return -ENOMEM; xpad->dev = input_dev; - usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); - strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); - - input_dev->name = xpad_device[i].name; + input_dev->name = xpad->name; input_dev->phys = xpad->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; + usb_to_input_id(xpad->udev, &input_dev->id); + input_dev->dev.parent = &xpad->intf->dev; input_set_drvdata(input_dev, xpad); input_dev->open = xpad_open; input_dev->close = xpad_close; - input_dev->evbit[0] = BIT_MASK(EV_KEY); + __set_bit(EV_KEY, input_dev->evbit); if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { - input_dev->evbit[0] |= BIT_MASK(EV_ABS); + __set_bit(EV_ABS, input_dev->evbit); /* set up axes */ for (i = 0; xpad_abs[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs[i]); @@ -1189,17 +1135,100 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); } - error = xpad_init_output(intf, xpad); - if (error) - goto fail3; - error = xpad_init_ff(xpad); if (error) - goto fail4; + goto err_free_input; error = xpad_led_probe(xpad); if (error) - goto fail5; + goto err_destroy_ff; + + error = input_register_device(xpad->dev); + if (error) + goto err_disconnect_led; + + return 0; + +err_disconnect_led: + xpad_led_disconnect(xpad); +err_destroy_ff: + input_ff_destroy(input_dev); +err_free_input: + input_free_device(input_dev); + return error; +} + +static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_xpad *xpad; + struct usb_endpoint_descriptor *ep_irq_in; + int ep_irq_in_idx; + int i, error; + + for (i = 0; xpad_device[i].idVendor; i++) { + if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && + (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) + break; + } + + if (xpad_device[i].xtype == XTYPE_XBOXONE && + intf->cur_altsetting->desc.bInterfaceNumber != 0) { + /* + * The Xbox One controller lists three interfaces all with the + * same interface class, subclass and protocol. Differentiate by + * interface number. + */ + return -ENODEV; + } + + xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); + if (!xpad) + return -ENOMEM; + + usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); + strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); + + xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->idata_dma); + if (!xpad->idata) { + error = -ENOMEM; + goto err_free_mem; + } + + xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); + if (!xpad->irq_in) { + error = -ENOMEM; + goto err_free_idata; + } + + xpad->udev = udev; + xpad->intf = intf; + xpad->mapping = xpad_device[i].mapping; + xpad->xtype = xpad_device[i].xtype; + xpad->name = xpad_device[i].name; + + if (xpad->xtype == XTYPE_UNKNOWN) { + if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { + if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) + xpad->xtype = XTYPE_XBOX360W; + else + xpad->xtype = XTYPE_XBOX360; + } else { + xpad->xtype = XTYPE_XBOX; + } + + if (dpad_to_buttons) + xpad->mapping |= MAP_DPAD_TO_BUTTONS; + if (triggers_to_buttons) + xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; + if (sticks_to_null) + xpad->mapping |= MAP_STICKS_TO_NULL; + } + + error = xpad_init_output(intf, xpad); + if (error) + goto err_free_in_urb; /* Xbox One controller has in/out endpoints swapped. */ ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0; @@ -1212,12 +1241,12 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - error = input_register_device(xpad->dev); - if (error) - goto fail6; - usb_set_intfdata(intf, xpad); + error = xpad_init_input(xpad); + if (error) + goto err_deinit_output; + if (xpad->xtype == XTYPE_XBOX360W) { /* * Submit the int URB immediately rather than waiting for open @@ -1229,20 +1258,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->dev = xpad->udev; error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); if (error) - goto fail7; + goto err_deinit_input; } - return 0; - fail7: input_unregister_device(input_dev); - input_dev = NULL; - fail6: xpad_led_disconnect(xpad); - fail5: if (input_dev) - input_ff_destroy(input_dev); - fail4: xpad_deinit_output(xpad); - fail3: usb_free_urb(xpad->irq_in); - fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - fail1: input_free_device(input_dev); +err_deinit_input: + xpad_deinit_input(xpad); +err_deinit_output: + xpad_deinit_output(xpad); +err_free_in_urb: + usb_free_urb(xpad->irq_in); +err_free_idata: + usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); +err_free_mem: kfree(xpad); return error; @@ -1252,8 +1280,7 @@ static void xpad_disconnect(struct usb_interface *intf) { struct usb_xpad *xpad = usb_get_intfdata (intf); - xpad_led_disconnect(xpad); - input_unregister_device(xpad->dev); + xpad_deinit_input(xpad); xpad_deinit_output(xpad); if (xpad->xtype == XTYPE_XBOX360W) { -- cgit v1.2.3 From aba54876bb38dde81abead1ed1936eb04fa30ca9 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 09:36:17 -0700 Subject: Input: xpad - query wireless controller state at init When we initialize the driver/device, we really don't know how many controllers are connected. So send a "query presence" command to the base-station. (Command discovered by Zachary Lund) Presence packet taken from: https://github.com/computerquip/xpad5 Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 486db7a1d99a..d382d48d6750 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -768,6 +768,33 @@ static void xpad_deinit_output(struct usb_xpad *xpad) } } +static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) +{ + int retval; + + mutex_lock(&xpad->odata_mutex); + + xpad->odata[0] = 0x08; + xpad->odata[1] = 0x00; + xpad->odata[2] = 0x0F; + xpad->odata[3] = 0xC0; + xpad->odata[4] = 0x00; + xpad->odata[5] = 0x00; + xpad->odata[6] = 0x00; + xpad->odata[7] = 0x00; + xpad->odata[8] = 0x00; + xpad->odata[9] = 0x00; + xpad->odata[10] = 0x00; + xpad->odata[11] = 0x00; + xpad->irq_out->transfer_buffer_length = 12; + + retval = usb_submit_urb(xpad->irq_out, GFP_KERNEL); + + mutex_unlock(&xpad->odata_mutex); + + return retval; +} + #ifdef CONFIG_JOYSTICK_XPAD_FF static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { @@ -1259,9 +1286,22 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); if (error) goto err_deinit_input; + + /* + * Send presence packet. + * This will force the controller to resend connection packets. + * This is useful in the case we activate the module after the + * adapter has been plugged in, as it won't automatically + * send us info about the controllers. + */ + error = xpad_inquiry_pad_presence(xpad); + if (error) + goto err_kill_in_urb; } return 0; +err_kill_in_urb: + usb_kill_urb(xpad->irq_in); err_deinit_input: xpad_deinit_input(xpad); err_deinit_output: -- cgit v1.2.3 From 027c71bbae3a6eeff00c11d1b708593a5c790314 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Tue, 13 Oct 2015 23:13:55 -0700 Subject: Input: improve autorepeat initialization Add new function input_enable_softrepeat() that allows drivers to initialize their own values for input_dev->rep[REP_DELAY] and input_dev->rep[REP_PERIOD], but also use the software autorepeat functionality from input.c. For example, a HID driver could do: static void xyz_input_configured(struct hid_device *hid, struct hid_input *hidinput) { input_enable_softrepeat(hidinput->input, 400, 100); } static struct hid_driver xyz_driver = { .input_configured = xyz_input_configured, } Signed-off-by: Petri Gynther Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 25 +++++++++++++++++++------ include/linux/input.h | 2 ++ 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index 5391abd28b27..880605959aa6 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -2044,6 +2044,23 @@ static void devm_input_device_unregister(struct device *dev, void *res) __input_unregister_device(input); } +/** + * input_enable_softrepeat - enable software autorepeat + * @dev: input device + * @delay: repeat delay + * @period: repeat period + * + * Enable software autorepeat on the input device. + */ +void input_enable_softrepeat(struct input_dev *dev, int delay, int period) +{ + dev->timer.data = (unsigned long) dev; + dev->timer.function = input_repeat_key; + dev->rep[REP_DELAY] = delay; + dev->rep[REP_PERIOD] = period; +} +EXPORT_SYMBOL(input_enable_softrepeat); + /** * input_register_device - register device with input core * @dev: device to be registered @@ -2108,12 +2125,8 @@ int input_register_device(struct input_dev *dev) * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. */ - if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) { - dev->timer.data = (long) dev; - dev->timer.function = input_repeat_key; - dev->rep[REP_DELAY] = 250; - dev->rep[REP_PERIOD] = 33; - } + if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) + input_enable_softrepeat(dev, 250, 33); if (!dev->getkeycode) dev->getkeycode = input_default_getkeycode; diff --git a/include/linux/input.h b/include/linux/input.h index 82ce323b9986..1e967694e9a5 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -469,6 +469,8 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke); int input_set_keycode(struct input_dev *dev, const struct input_keymap_entry *ke); +void input_enable_softrepeat(struct input_dev *dev, int delay, int period); + extern struct class input_class; /** -- cgit v1.2.3 From 47ec6e5a5f57f96d7d382e2d9f8dc5a5bdb45259 Mon Sep 17 00:00:00 2001 From: Sylvain Rochet Date: Tue, 13 Oct 2015 23:24:36 -0700 Subject: Input: rotary_encoder - add wake up support This patch adds wake up support to GPIO rotary encoders. Signed-off-by: Sylvain Rochet Reviewed-by: Johan Hovold Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/rotary-encoder.txt | 1 + Documentation/input/rotary-encoder.txt | 1 + drivers/input/misc/rotary_encoder.c | 37 ++++++++++++++++++++++ include/linux/rotary_encoder.h | 1 + 4 files changed, 40 insertions(+) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt index 331549593ed5..891ddba2d792 100644 --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt @@ -15,6 +15,7 @@ Optional properties: - rotary-encoder,rollover: Automatic rollove when the rotary value becomes greater than the specified steps or smaller than 0. For absolute axis only. - rotary-encoder,half-period: Makes the driver work on half-period mode. +- wakeup-source: Boolean, rotary encoder can wake up the system. See Documentation/input/rotary-encoder.txt for more information. diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt index 5737e3590adb..bddbee188624 100644 --- a/Documentation/input/rotary-encoder.txt +++ b/Documentation/input/rotary-encoder.txt @@ -109,6 +109,7 @@ static struct rotary_encoder_platform_data my_rotary_encoder_info = { .inverted_a = 0, .inverted_b = 0, .half_period = false, + .wakeup_source = false, }; static struct platform_device rotary_encoder_device = { diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index f27f81ee84ed..d1665544e109 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -26,6 +26,7 @@ #include #include #include +#include #define DRV_NAME "rotary-encoder" @@ -180,6 +181,8 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic "rotary-encoder,rollover", NULL); pdata->half_period = !!of_get_property(np, "rotary-encoder,half-period", NULL); + pdata->wakeup_source = !!of_get_property(np, + "wakeup-source", NULL); return pdata; } @@ -280,6 +283,8 @@ static int rotary_encoder_probe(struct platform_device *pdev) goto exit_free_irq_b; } + device_init_wakeup(&pdev->dev, pdata->wakeup_source); + platform_set_drvdata(pdev, encoder); return 0; @@ -306,6 +311,8 @@ static int rotary_encoder_remove(struct platform_device *pdev) struct rotary_encoder *encoder = platform_get_drvdata(pdev); const struct rotary_encoder_platform_data *pdata = encoder->pdata; + device_init_wakeup(&pdev->dev, false); + free_irq(encoder->irq_a, encoder); free_irq(encoder->irq_b, encoder); gpio_free(pdata->gpio_a); @@ -320,11 +327,41 @@ static int rotary_encoder_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int rotary_encoder_suspend(struct device *dev) +{ + struct rotary_encoder *encoder = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) { + enable_irq_wake(encoder->irq_a); + enable_irq_wake(encoder->irq_b); + } + + return 0; +} + +static int rotary_encoder_resume(struct device *dev) +{ + struct rotary_encoder *encoder = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) { + disable_irq_wake(encoder->irq_a); + disable_irq_wake(encoder->irq_b); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops, + rotary_encoder_suspend, rotary_encoder_resume); + static struct platform_driver rotary_encoder_driver = { .probe = rotary_encoder_probe, .remove = rotary_encoder_remove, .driver = { .name = DRV_NAME, + .pm = &rotary_encoder_pm_ops, .of_match_table = of_match_ptr(rotary_encoder_of_match), } }; diff --git a/include/linux/rotary_encoder.h b/include/linux/rotary_encoder.h index 3f594dce5716..b33f2d2a708f 100644 --- a/include/linux/rotary_encoder.h +++ b/include/linux/rotary_encoder.h @@ -11,6 +11,7 @@ struct rotary_encoder_platform_data { bool relative_axis; bool rollover; bool half_period; + bool wakeup_source; }; #endif /* __ROTARY_ENCODER_H__ */ -- cgit v1.2.3 From 881d824569aa2df75175aa882ada0c1e48212de3 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 13 Oct 2015 23:31:39 -0700 Subject: Input: pixcir_i2c_ts - remove wakeirq related code from pixcir driver With commit 3fffd1283927 ("i2c: allow specifying separate wakeup interrupt in device tree") wakeirq is managed by i2c-core, so remove wakeirq related code from pixcir_i2c_ts driver. Signed-off-by: Vignesh R Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 91621725bfb5..4b961ad9f0b5 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -377,8 +377,6 @@ static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev) goto unlock; } } - - enable_irq_wake(client->irq); } else if (input->users) { ret = pixcir_stop(ts); } @@ -399,7 +397,6 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev) mutex_lock(&input->mutex); if (device_may_wakeup(&client->dev)) { - disable_irq_wake(client->irq); if (!input->users) { ret = pixcir_stop(ts); @@ -564,14 +561,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, return error; i2c_set_clientdata(client, tsdata); - device_init_wakeup(&client->dev, 1); - - return 0; -} - -static int pixcir_i2c_ts_remove(struct i2c_client *client) -{ - device_init_wakeup(&client->dev, 0); return 0; } @@ -609,7 +598,6 @@ static struct i2c_driver pixcir_i2c_ts_driver = { .of_match_table = of_match_ptr(pixcir_of_match), }, .probe = pixcir_i2c_ts_probe, - .remove = pixcir_i2c_ts_remove, .id_table = pixcir_i2c_ts_id, }; -- cgit v1.2.3 From 6f29d3b2777ae32e995d45247c8234d83894b953 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 14 Oct 2015 16:44:35 -0700 Subject: Input: gpio_keys_polled - add support for abs/rel axis This changAdd support for EV_ABS / EV_REL events to the gpio-keys-polled driver. The driver already allows specifying what type of events (key / rel / abs) a button generates when pressed, but for rel / abs axis we also need to specify which value this specific gpio represents. One use case is digital joysticks / direction-pads which are hooked up to gpio, in this case we've left and right buttons which we want to map to EV_ABS, ABS_X and we want generate events for left with a value of -1 and for right with a value of +1 (and similar for up / down and ABS_Y). Signed-off-by: Hans de Goede Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/gpio-keys-polled.txt | 9 ++- drivers/input/keyboard/gpio_keys_polled.c | 88 +++++++++++++++++++--- 2 files changed, 87 insertions(+), 10 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/gpio-keys-polled.txt b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt index 5b91f5a3bd5c..97e2467181e9 100644 --- a/Documentation/devicetree/bindings/input/gpio-keys-polled.txt +++ b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt @@ -13,11 +13,18 @@ Subnode properties: - gpios: OF device-tree gpio specification. - label: Descriptive name of the key. - - linux,code: Keycode to emit. + - linux,code: Key / Axis code to emit. Optional subnode-properties: - linux,input-type: Specify event type this button/key generates. If not specified defaults to <1> == EV_KEY. + - linux,input-value: If linux,input-type is EV_ABS or EV_REL then this + value is sent for events this button generates when pressed. + EV_ABS/EV_REL axis will generate an event with a value of 0 when + all buttons with linux,input-type == type and linux,code == axis + are released. This value is interpreted as a signed 32 bit value, + e.g. to make a button generate a value of -1 use: + linux,input-value = <0xffffffff>; /* -1 */ - debounce-interval: Debouncing interval time in milliseconds. If not specified defaults to 5. - wakeup-source: Boolean, button can wake-up the system. diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 870cfa6e2c44..62bdb1d48c49 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -40,10 +40,36 @@ struct gpio_keys_polled_dev { struct input_polled_dev *poll_dev; struct device *dev; const struct gpio_keys_platform_data *pdata; + unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)]; + unsigned long abs_axis_seen[BITS_TO_LONGS(ABS_CNT)]; struct gpio_keys_button_data data[0]; }; -static void gpio_keys_polled_check_state(struct input_dev *input, +static void gpio_keys_button_event(struct input_polled_dev *dev, + struct gpio_keys_button *button, + int state) +{ + struct gpio_keys_polled_dev *bdev = dev->private; + struct input_dev *input = dev->input; + unsigned int type = button->type ?: EV_KEY; + + if (type == EV_REL) { + if (state) { + input_event(input, type, button->code, button->value); + __set_bit(button->code, bdev->rel_axis_seen); + } + } else if (type == EV_ABS) { + if (state) { + input_event(input, type, button->code, button->value); + __set_bit(button->code, bdev->abs_axis_seen); + } + } else { + input_event(input, type, button->code, state); + input_sync(input); + } +} + +static void gpio_keys_polled_check_state(struct input_polled_dev *dev, struct gpio_keys_button *button, struct gpio_keys_button_data *bdata) { @@ -54,11 +80,9 @@ static void gpio_keys_polled_check_state(struct input_dev *input, else state = !!gpiod_get_value(button->gpiod); - if (state != bdata->last_state) { - unsigned int type = button->type ?: EV_KEY; + gpio_keys_button_event(dev, button, state); - input_event(input, type, button->code, state); - input_sync(input); + if (state != bdata->last_state) { bdata->count = 0; bdata->last_state = state; } @@ -71,15 +95,33 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev) struct input_dev *input = dev->input; int i; + memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen)); + memset(bdev->abs_axis_seen, 0, sizeof(bdev->abs_axis_seen)); + for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button_data *bdata = &bdev->data[i]; - if (bdata->count < bdata->threshold) + if (bdata->count < bdata->threshold) { bdata->count++; - else - gpio_keys_polled_check_state(input, &pdata->buttons[i], + gpio_keys_button_event(dev, &pdata->buttons[i], + bdata->last_state); + } else { + gpio_keys_polled_check_state(dev, &pdata->buttons[i], bdata); + } + } + + for_each_set_bit(i, input->relbit, REL_CNT) { + if (!test_bit(i, bdev->rel_axis_seen)) + input_event(input, EV_REL, i, 0); + } + + for_each_set_bit(i, input->absbit, ABS_CNT) { + if (!test_bit(i, bdev->abs_axis_seen)) + input_event(input, EV_ABS, i, 0); } + + input_sync(input); } static void gpio_keys_polled_open(struct input_polled_dev *dev) @@ -152,6 +194,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct &button->type)) button->type = EV_KEY; + if (fwnode_property_read_u32(child, "linux,input-value", + (u32 *)&button->value)) + button->value = 1; + button->wakeup = fwnode_property_read_bool(child, "wakeup-source") || /* legacy name */ @@ -168,6 +214,25 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct return pdata; } +static void gpio_keys_polled_set_abs_params(struct input_dev *input, + const struct gpio_keys_platform_data *pdata, unsigned int code) +{ + int i, min = 0, max = 0; + + for (i = 0; i < pdata->nbuttons; i++) { + struct gpio_keys_button *button = &pdata->buttons[i]; + + if (button->type != EV_ABS || button->code != code) + continue; + + if (button->value < min) + min = button->value; + if (button->value > max) + max = button->value; + } + input_set_abs_params(input, code, min, max, 0, 0); +} + static const struct of_device_id gpio_keys_polled_of_match[] = { { .compatible = "gpio-keys-polled", }, { }, @@ -274,6 +339,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) pdata->poll_interval); input_set_capability(input, type, button->code); + if (type == EV_ABS) + gpio_keys_polled_set_abs_params(input, pdata, + button->code); } bdev->poll_dev = poll_dev; @@ -290,9 +358,11 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) /* report initial state of the buttons */ for (i = 0; i < pdata->nbuttons; i++) - gpio_keys_polled_check_state(input, &pdata->buttons[i], + gpio_keys_polled_check_state(poll_dev, &pdata->buttons[i], &bdev->data[i]); + input_sync(input); + return 0; } -- cgit v1.2.3 From 33b96d934902f96e901b72ac18bbc47afad1ac20 Mon Sep 17 00:00:00 2001 From: Elias Vanderstuyft Date: Wed, 14 Oct 2015 17:29:37 -0700 Subject: Input: document and check on implicitly defined FF_MAX_EFFECTS There is an undocumented upper bound for the total number of ff effects: FF_GAIN (= 96). This can be found as follows: - user: write(EV_FF, effect_id, iterations) calls kernel: ff->playback(effect_id, ...): starts effect "effect_id" - user: write(EV_FF, FF_GAIN, gain) calls kernel: ff->set_gain(gain, ...): sets gain A collision occurs when effect_id equals FF_GAIN. According to input_ff_event(), FF_GAIN is the smallest value where a collision occurs. Therefore the greatest safe value for effect_id is FF_GAIN - 1, and thus the total number of effects should never exceed FF_GAIN. Define FF_MAX_EFFECTS as FF_GAIN and check on this limit in ff-core. Signed-off-by: Elias Vanderstuyft Signed-off-by: Dmitry Torokhov --- drivers/input/ff-core.c | 5 +++++ include/uapi/linux/input.h | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index eab56c0aacd5..8f2042432c85 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -318,6 +318,11 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects) return -EINVAL; } + if (max_effects > FF_MAX_EFFECTS) { + dev_err(&dev->dev, "cannot allocate more than FF_MAX_EFFECTS effects\n"); + return -EINVAL; + } + ff_dev_size = sizeof(struct ff_device) + max_effects * sizeof(struct file *); if (ff_dev_size < max_effects) /* overflow */ diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index a8e74b45dbe2..4f9f2a0f5573 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -414,6 +414,14 @@ struct ff_effect { #define FF_GAIN 0x60 #define FF_AUTOCENTER 0x61 +/* + * ff->playback(effect_id = FF_GAIN) is the first effect_id to + * cause a collision with another ff method, in this case ff->set_gain(). + * Therefore the greatest safe value for effect_id is FF_GAIN - 1, + * and thus the total number of effects should never exceed FF_GAIN. + */ +#define FF_MAX_EFFECTS FF_GAIN + #define FF_MAX 0x7f #define FF_CNT (FF_MAX+1) -- cgit v1.2.3 From 648b15cb79e90d80f7b53d0184bdb14132a03754 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 13 Oct 2015 23:37:28 -0700 Subject: Input: rotary-encoder - use of_property_read_bool This commit makes uses of_property_read_bool() to read boolean properties. This is just cosmetic cleanup. Signed-off-by: Ben Gamari Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index d1665544e109..962f9e86310b 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -175,14 +175,12 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic pdata->gpio_b = of_get_gpio_flags(np, 1, &flags); pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW; - pdata->relative_axis = !!of_get_property(np, - "rotary-encoder,relative-axis", NULL); - pdata->rollover = !!of_get_property(np, - "rotary-encoder,rollover", NULL); - pdata->half_period = !!of_get_property(np, - "rotary-encoder,half-period", NULL); - pdata->wakeup_source = !!of_get_property(np, - "wakeup-source", NULL); + pdata->relative_axis = + of_property_read_bool(np, "rotary-encoder,relative-axis"); + pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover"); + pdata->half_period = + of_property_read_bool(np, "rotary-encoder,half-period"); + pdata->wakeup_source = of_property_read_bool(np, "wakeup-source"); return pdata; } -- cgit v1.2.3 From 3a341a4c30d427fd05617087db1564a595f65093 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 13 Oct 2015 23:39:50 -0700 Subject: Input: rotary-encoder - add support for quarter-period mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some encoders have both outputs low in stable states, others also have a stable state with both outputs high (half-period mode) and some have a stable state in all steps (quarter-period mode). The driver used to support the former states and with this change it can also support the later. This commit also deprecates the 'half-period' property and introduces a new property 'steps-per-period'. This property specifies the number of steps (stable states) produced by the rotary encoder for each GPIO period. Signed-off-by: Guido Martínez Signed-off-by: Ezequiel Garcia Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/rotary-encoder.txt | 11 ++- Documentation/input/rotary-encoder.txt | 8 +- drivers/input/misc/rotary_encoder.c | 86 ++++++++++++++++++++-- include/linux/rotary_encoder.h | 2 +- 4 files changed, 98 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt index 891ddba2d792..de99cbbbf6da 100644 --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt @@ -14,9 +14,18 @@ Optional properties: device, hence no steps need to be passed. - rotary-encoder,rollover: Automatic rollove when the rotary value becomes greater than the specified steps or smaller than 0. For absolute axis only. -- rotary-encoder,half-period: Makes the driver work on half-period mode. +- rotary-encoder,steps-per-period: Number of steps (stable states) per period. + The values have the following meaning: + 1: Full-period mode (default) + 2: Half-period mode + 4: Quarter-period mode - wakeup-source: Boolean, rotary encoder can wake up the system. +Deprecated properties: +- rotary-encoder,half-period: Makes the driver work on half-period mode. + This property is deprecated. Instead, a 'steps-per-period ' value should + be used, such as "rotary-encoder,steps-per-period = <2>". + See Documentation/input/rotary-encoder.txt for more information. Example: diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt index bddbee188624..46a74f0c551a 100644 --- a/Documentation/input/rotary-encoder.txt +++ b/Documentation/input/rotary-encoder.txt @@ -9,8 +9,9 @@ peripherals with two wires. The outputs are phase-shifted by 90 degrees and by triggering on falling and rising edges, the turn direction can be determined. -Some encoders have both outputs low in stable states, whereas others also have -a stable state with both outputs high (half-period mode). +Some encoders have both outputs low in stable states, others also have +a stable state with both outputs high (half-period mode) and some have +a stable state in all steps (quarter-period mode). The phase diagram of these two outputs look like this: @@ -32,6 +33,9 @@ The phase diagram of these two outputs look like this: |<-->| one step (half-period mode) + |<>| + one step (quarter-period mode) + For more information, please see https://en.wikipedia.org/wiki/Rotary_encoder diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 962f9e86310b..8aee71986430 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -143,6 +143,55 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id) +{ + struct rotary_encoder *encoder = dev_id; + unsigned char sum; + int state; + + state = rotary_encoder_get_state(encoder->pdata); + + /* + * We encode the previous and the current state using a byte. + * The previous state in the MSB nibble, the current state in the LSB + * nibble. Then use a table to decide the direction of the turn. + */ + sum = (encoder->last_stable << 4) + state; + switch (sum) { + case 0x31: + case 0x10: + case 0x02: + case 0x23: + encoder->dir = 0; /* clockwise */ + break; + + case 0x13: + case 0x01: + case 0x20: + case 0x32: + encoder->dir = 1; /* counter-clockwise */ + break; + + default: + /* + * Ignore all other values. This covers the case when the + * state didn't change (a spurious interrupt) and the + * cases where the state changed by two steps, making it + * impossible to tell the direction. + * + * In either case, don't report any event and save the + * state for later. + */ + goto out; + } + + rotary_encoder_report_event(encoder); + +out: + encoder->last_stable = state; + return IRQ_HANDLED; +} + #ifdef CONFIG_OF static const struct of_device_id rotary_encoder_of_match[] = { { .compatible = "rotary-encoder", }, @@ -157,6 +206,7 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic struct device_node *np = dev->of_node; struct rotary_encoder_platform_data *pdata; enum of_gpio_flags flags; + int error; if (!of_id || !np) return NULL; @@ -178,8 +228,23 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic pdata->relative_axis = of_property_read_bool(np, "rotary-encoder,relative-axis"); pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover"); - pdata->half_period = - of_property_read_bool(np, "rotary-encoder,half-period"); + + error = of_property_read_u32(np, "rotary-encoder,steps-per-period", + &pdata->steps_per_period); + if (error) { + /* + * The 'half-period' property has been deprecated, you must use + * 'steps-per-period' and set an appropriate value, but we still + * need to parse it to maintain compatibility. + */ + if (of_property_read_bool(np, "rotary-encoder,half-period")) { + pdata->steps_per_period = 2; + } else { + /* Fallback to one step per period behavior */ + pdata->steps_per_period = 1; + } + } + pdata->wakeup_source = of_property_read_bool(np, "wakeup-source"); return pdata; @@ -251,12 +316,23 @@ static int rotary_encoder_probe(struct platform_device *pdev) encoder->irq_a = gpio_to_irq(pdata->gpio_a); encoder->irq_b = gpio_to_irq(pdata->gpio_b); - /* request the IRQs */ - if (pdata->half_period) { + switch (pdata->steps_per_period) { + case 4: + handler = &rotary_encoder_quarter_period_irq; + encoder->last_stable = rotary_encoder_get_state(pdata); + break; + case 2: handler = &rotary_encoder_half_period_irq; encoder->last_stable = rotary_encoder_get_state(pdata); - } else { + break; + case 1: handler = &rotary_encoder_irq; + break; + default: + dev_err(dev, "'%d' is not a valid steps-per-period value\n", + pdata->steps_per_period); + err = -EINVAL; + goto exit_free_gpio_b; } err = request_irq(encoder->irq_a, handler, diff --git a/include/linux/rotary_encoder.h b/include/linux/rotary_encoder.h index b33f2d2a708f..fe3dc64e5aeb 100644 --- a/include/linux/rotary_encoder.h +++ b/include/linux/rotary_encoder.h @@ -8,9 +8,9 @@ struct rotary_encoder_platform_data { unsigned int gpio_b; unsigned int inverted_a; unsigned int inverted_b; + unsigned int steps_per_period; bool relative_axis; bool rollover; - bool half_period; bool wakeup_source; }; -- cgit v1.2.3 From c789f1fb07e7c5acc04342cb2e2412aa71cd6c18 Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Fri, 16 Oct 2015 15:34:05 -0700 Subject: Input: edt-ft5x06 - use max support points to determine how much to read Calculate the amount of data that needs to be read for the specified max number of support points. If the maximum number of support points changes then the amount that is read from the touch screen controller should reflect this. Signed-off-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index a8640c7b6713..a76bc486936c 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -168,9 +168,9 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) struct edt_ft5x06_ts_data *tsdata = dev_id; struct device *dev = &tsdata->client->dev; u8 cmd; - u8 rdbuf[29]; + u8 rdbuf[31]; int i, type, x, y, id; - int offset, tplen, datalen; + int offset, tplen, datalen, crclen; int error; switch (tsdata->version) { @@ -178,14 +178,14 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) cmd = 0xf9; /* tell the controller to send touch data */ offset = 5; /* where the actual touch data starts */ tplen = 4; /* data comes in so called frames */ - datalen = 26; /* how much bytes to listen for */ + crclen = 1; /* length of the crc data */ break; case M09: cmd = 0x02; offset = 1; tplen = 6; - datalen = 29; + crclen = 0; break; default: @@ -193,6 +193,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) } memset(rdbuf, 0, sizeof(rdbuf)); + datalen = tplen * MAX_SUPPORT_POINTS + offset + crclen; error = edt_ft5x06_ts_readwrite(tsdata->client, sizeof(cmd), &cmd, -- cgit v1.2.3 From b1d2a3ecb9cbf932a875a59f12f0f44841f29c30 Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Fri, 16 Oct 2015 15:34:16 -0700 Subject: Input: edt-ft5x06 - add support for different max support points Update the code so that the maximum supported points aren't hard coded but can be changed. Set the maximum support points based on the data passed along side the compatible field. Signed-off-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 38 ++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index a76bc486936c..98766f2a8c4f 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -38,8 +38,7 @@ #include #include #include - -#define MAX_SUPPORT_POINTS 5 +#include #define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_REPORT_RATE 0x08 @@ -105,6 +104,7 @@ struct edt_ft5x06_ts_data { int gain; int offset; int report_rate; + int max_support_points; char name[EDT_NAME_LEN]; @@ -112,6 +112,10 @@ struct edt_ft5x06_ts_data { enum edt_ver version; }; +struct edt_i2c_chip_data { + int max_support_points; +}; + static int edt_ft5x06_ts_readwrite(struct i2c_client *client, u16 wr_len, u8 *wr_buf, u16 rd_len, u8 *rd_buf) @@ -193,7 +197,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) } memset(rdbuf, 0, sizeof(rdbuf)); - datalen = tplen * MAX_SUPPORT_POINTS + offset + crclen; + datalen = tplen * tsdata->max_support_points + offset + crclen; error = edt_ft5x06_ts_readwrite(tsdata->client, sizeof(cmd), &cmd, @@ -218,7 +222,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) goto out; } - for (i = 0; i < MAX_SUPPORT_POINTS; i++) { + for (i = 0; i < tsdata->max_support_points; i++) { u8 *buf = &rdbuf[i * tplen + offset]; bool down; @@ -874,6 +878,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { + const struct edt_i2c_chip_data *chip_data; struct edt_ft5x06_ts_data *tsdata; struct input_dev *input; unsigned long irq_flags; @@ -888,6 +893,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return -ENOMEM; } + chip_data = of_device_get_match_data(&client->dev); + if (!chip_data) + chip_data = (const struct edt_i2c_chip_data *)id->driver_data; + if (!chip_data || !chip_data->max_support_points) { + dev_err(&client->dev, "invalid or missing chip data\n"); + return -EINVAL; + } + + tsdata->max_support_points = chip_data->max_support_points; + tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(tsdata->reset_gpio)) { @@ -953,7 +968,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, touchscreen_parse_properties(input, true); - error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, INPUT_MT_DIRECT); + error = input_mt_init_slots(input, tsdata->max_support_points, + INPUT_MT_DIRECT); if (error) { dev_err(&client->dev, "Unable to init MT slots.\n"); return error; @@ -1032,17 +1048,21 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); +static const struct edt_i2c_chip_data edt_ft5x06_data = { + .max_support_points = 5, +}; + static const struct i2c_device_id edt_ft5x06_ts_id[] = { - { "edt-ft5x06", 0, }, + { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); #ifdef CONFIG_OF static const struct of_device_id edt_ft5x06_of_match[] = { - { .compatible = "edt,edt-ft5206", }, - { .compatible = "edt,edt-ft5306", }, - { .compatible = "edt,edt-ft5406", }, + { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data }, + { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data }, + { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); -- cgit v1.2.3 From af33e0ad1bf6e065f05a68f177b99202935ed2cf Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Fri, 16 Oct 2015 15:34:26 -0700 Subject: Input: edt-ft5x06 - add support for FT5506 FT5506 is essentially the same as other FT5x06 devices other than supporting 10 support points. Signed-off-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/touchscreen/edt-ft5x06.txt | 2 ++ drivers/input/touchscreen/edt-ft5x06.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index bedd7ddc56aa..f99528da1b1d 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -5,6 +5,7 @@ There are 3 variants of the chip for various touch panel sizes FT5206GE1 2.8" .. 3.8" FT5306DE4 4.3" .. 7" FT5406EE8 7" .. 8.9" +FT5506EEG 7" .. 8.9" The software interface is identical for all those chips, so that currently there is no need for the driver to distinguish between the @@ -17,6 +18,7 @@ Required properties: - compatible: "edt,edt-ft5206" or: "edt,edt-ft5306" or: "edt,edt-ft5406" + or: "edt,edt-ft5506" - reg: I2C slave address of the chip (0x38) - interrupt-parent: a phandle pointing to the interrupt controller diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 98766f2a8c4f..214d8a08a469 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -172,7 +172,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) struct edt_ft5x06_ts_data *tsdata = dev_id; struct device *dev = &tsdata->client->dev; u8 cmd; - u8 rdbuf[31]; + u8 rdbuf[61]; int i, type, x, y, id; int offset, tplen, datalen, crclen; int error; @@ -1052,8 +1052,13 @@ static const struct edt_i2c_chip_data edt_ft5x06_data = { .max_support_points = 5, }; +static const struct edt_i2c_chip_data edt_ft5506_data = { + .max_support_points = 10, +}; + static const struct i2c_device_id edt_ft5x06_ts_id[] = { { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data }, + { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); @@ -1063,6 +1068,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = { { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, + { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); -- cgit v1.2.3 From 9378c0251c7ac4b247177fb0c292a025ca1b751c Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Fri, 16 Oct 2015 15:34:41 -0700 Subject: Input: edt-ft5x06 - work around FT5506 firmware bug In the touchscreen controller ISR, reading the tsc starting from register 0x2 causes the tsc to infrequently update the detected finger's x and y coordinate. The irq pin toggles at a fast rate to indicate touch events are happening. However, the tsc on average updates the touch point's x and y value every ~100 ms which is much slower than the advertised rate of 100+ Hz. This leads to multiple reads within this ~100 ms time window returning the same value. Example: X: 10 , Y: 30 X: 10 , Y: 30 X: 10, Y: 30 .. // After 100 ms X: 300, Y: 300 X: 300, y: 300 .. // After 100 ms X: 1743, Y: 621 X: 1743, Y: 621 For some reason if instead of starting to read at register 0x2 you start reading at register 0x0 this issue isn't seen. This seems like a quirk only seen in the EDT FT5506 so to fix this issue simply adjust the code to start reading from 0x0. Technically this isn't wrong so no regressions should be seen with other touchscreen controllers supported by this driver. Signed-off-by: Franklin S Cooper Jr Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 214d8a08a469..0b0f8c17f3f7 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -172,7 +172,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) struct edt_ft5x06_ts_data *tsdata = dev_id; struct device *dev = &tsdata->client->dev; u8 cmd; - u8 rdbuf[61]; + u8 rdbuf[63]; int i, type, x, y, id; int offset, tplen, datalen, crclen; int error; @@ -186,8 +186,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) break; case M09: - cmd = 0x02; - offset = 1; + cmd = 0x0; + offset = 3; tplen = 6; crclen = 0; break; -- cgit v1.2.3 From fbe6a3114471cccaeaeabfa56937731503ece545 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Mon, 19 Oct 2015 00:06:58 -0700 Subject: Input: xpad - fix clash of presence handling with LED setting Do not call xpad_identify_controller at init with wireless devices: it conflicts with the already sent presence packet and will be called by xpad360w_process_packet as needed anyway. Signed-off-by: Pavel Rojtberg Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index d382d48d6750..fd4100d56d8c 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -1001,8 +1001,15 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (error) goto err_free_id; - /* Light up the segment corresponding to controller number */ - xpad_identify_controller(xpad); + if (xpad->xtype == XTYPE_XBOX360) { + /* + * Light up the segment corresponding to controller + * number on wired devices. On wireless we'll do that + * when they respond to "presence" packet. + */ + xpad_identify_controller(xpad); + } + return 0; err_free_id: -- cgit v1.2.3 From 2e9776e0c82b4bbf7d50fd6669080ab691156cea Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 20 Oct 2015 09:40:42 -0700 Subject: Input: nomadik-ske-keypad - fix a trivial typo s/regsiter/register/ Signed-off-by: Geliang Tang Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/nomadik-ske-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index c7d5b1666fc3..8567ee47761e 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -54,7 +54,7 @@ /** * struct ske_keypad - data structure used by keypad driver * @irq: irq no - * @reg_base: ske regsiters base address + * @reg_base: ske registers base address * @input: pointer to input device object * @board: keypad platform device * @keymap: matrix scan code table for keycodes -- cgit v1.2.3 From ba564e789761368b44be1362ace576831778d371 Mon Sep 17 00:00:00 2001 From: WEN Pingbo Date: Sun, 18 Oct 2015 16:33:47 -0700 Subject: Input: hp_sdc_rtc - fix y2038 problem in proc_show hp_sdc_rtc_proc_show() use timeval to store the time, which will overflow in 2038. This patch fixes this problem by replacing timeval with timespec64. hp_sdc_rtc_proc_show() only output string, so that userspace will work normally if we apply this patch. Not all timer in i8042 have y2038 risk(handshake, match timer, etc), Replacements in those timer are just for consistency. Signed-off-by: WEN Pingbo Reviewed-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/misc/hp_sdc_rtc.c | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index 45e0e3e55de2..1c8c56efc995 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c @@ -198,7 +198,7 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg) /* Read the i8042 real-time clock */ -static inline int hp_sdc_rtc_read_rt(struct timeval *res) { +static inline int hp_sdc_rtc_read_rt(struct timespec64 *res) { int64_t raw; uint32_t tenms; unsigned int days; @@ -209,15 +209,15 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) { tenms = (uint32_t)raw & 0xffffff; days = (unsigned int)(raw >> 24) & 0xffff; - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100) + days * 86400; + res->tv_nsec = (long)(tenms % 100) * 10000 * 1000; + res->tv_sec = (tenms / 100) + (time64_t)days * 86400; return 0; } /* Read the i8042 fast handshake timer */ -static inline int hp_sdc_rtc_read_fhs(struct timeval *res) { +static inline int hp_sdc_rtc_read_fhs(struct timespec64 *res) { int64_t raw; unsigned int tenms; @@ -226,15 +226,15 @@ static inline int hp_sdc_rtc_read_fhs(struct timeval *res) { tenms = (unsigned int)raw & 0xffff; - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); + res->tv_nsec = (long)(tenms % 100) * 10000 * 1000; + res->tv_sec = (time64_t)(tenms / 100); return 0; } /* Read the i8042 match timer (a.k.a. alarm) */ -static inline int hp_sdc_rtc_read_mt(struct timeval *res) { +static inline int hp_sdc_rtc_read_mt(struct timespec64 *res) { int64_t raw; uint32_t tenms; @@ -243,15 +243,15 @@ static inline int hp_sdc_rtc_read_mt(struct timeval *res) { tenms = (uint32_t)raw & 0xffffff; - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); + res->tv_nsec = (long)(tenms % 100) * 10000 * 1000; + res->tv_sec = (time64_t)(tenms / 100); return 0; } /* Read the i8042 delay timer */ -static inline int hp_sdc_rtc_read_dt(struct timeval *res) { +static inline int hp_sdc_rtc_read_dt(struct timespec64 *res) { int64_t raw; uint32_t tenms; @@ -260,15 +260,15 @@ static inline int hp_sdc_rtc_read_dt(struct timeval *res) { tenms = (uint32_t)raw & 0xffffff; - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); + res->tv_nsec = (long)(tenms % 100) * 10000 * 1000; + res->tv_sec = (time64_t)(tenms / 100); return 0; } /* Read the i8042 cycle timer (a.k.a. periodic) */ -static inline int hp_sdc_rtc_read_ct(struct timeval *res) { +static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) { int64_t raw; uint32_t tenms; @@ -277,8 +277,8 @@ static inline int hp_sdc_rtc_read_ct(struct timeval *res) { tenms = (uint32_t)raw & 0xffffff; - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); + res->tv_nsec = (long)(tenms % 100) * 10000 * 1000; + res->tv_sec = (time64_t)(tenms / 100); return 0; } @@ -433,7 +433,7 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v) #define YN(bit) ("no") #define NY(bit) ("yes") struct rtc_time tm; - struct timeval tv; + struct timespec64 tv; memset(&tm, 0, sizeof(struct rtc_time)); @@ -452,36 +452,36 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v) if (hp_sdc_rtc_read_rt(&tv)) { seq_puts(m, "i8042 rtc\t: READ FAILED!\n"); } else { - seq_printf(m, "i8042 rtc\t: %ld.%02d seconds\n", - tv.tv_sec, (int)tv.tv_usec/1000); + seq_printf(m, "i8042 rtc\t: %lld.%02ld seconds\n", + (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L); } if (hp_sdc_rtc_read_fhs(&tv)) { seq_puts(m, "handshake\t: READ FAILED!\n"); } else { - seq_printf(m, "handshake\t: %ld.%02d seconds\n", - tv.tv_sec, (int)tv.tv_usec/1000); + seq_printf(m, "handshake\t: %lld.%02ld seconds\n", + (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L); } if (hp_sdc_rtc_read_mt(&tv)) { seq_puts(m, "alarm\t\t: READ FAILED!\n"); } else { - seq_printf(m, "alarm\t\t: %ld.%02d seconds\n", - tv.tv_sec, (int)tv.tv_usec/1000); + seq_printf(m, "alarm\t\t: %lld.%02ld seconds\n", + (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L); } if (hp_sdc_rtc_read_dt(&tv)) { seq_puts(m, "delay\t\t: READ FAILED!\n"); } else { - seq_printf(m, "delay\t\t: %ld.%02d seconds\n", - tv.tv_sec, (int)tv.tv_usec/1000); + seq_printf(m, "delay\t\t: %lld.%02ld seconds\n", + (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L); } if (hp_sdc_rtc_read_ct(&tv)) { seq_puts(m, "periodic\t: READ FAILED!\n"); } else { - seq_printf(m, "periodic\t: %ld.%02d seconds\n", - tv.tv_sec, (int)tv.tv_usec/1000); + seq_printf(m, "periodic\t: %lld.%02ld seconds\n", + (s64)tv.tv_sec, (long)tv.tv_nsec/1000000L); } seq_printf(m, -- cgit v1.2.3 From ec7aa963bf81803b70b7da71bf79943ae5b9c531 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Mon, 19 Oct 2015 09:42:21 -0700 Subject: Input: xen - check return value of xenbus_printf Internally, xenbus_printf uses memory allocation, so it can fail under memory pressure, leaving the input device configured as absolute with the backend supplying relative coordinates. Signed-off-by: Insu Yun Reviewed-by: Julien Grall Signed-off-by: Dmitry Torokhov --- drivers/input/misc/xen-kbdfront.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 23d0549539d4..0a9ad2cfb55c 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -129,8 +129,14 @@ static int xenkbd_probe(struct xenbus_device *dev, if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0) abs = 0; - if (abs) - xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1"); + if (abs) { + ret = xenbus_printf(XBT_NIL, dev->nodename, + "request-abs-pointer", "1"); + if (ret) { + pr_warning("xenkbd: can't request abs-pointer"); + abs = 0; + } + } /* keyboard */ kbd = input_allocate_device(); -- cgit v1.2.3 From b42a1148de452ab1a3ee15caac2960a063e28f03 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 22 Oct 2015 23:38:40 -0700 Subject: Input: tegra-kbc - enable support for the standard "wakeup-source" property Though the tegra-kbc driver should/will continue to support the legacy "nvidia,wakeup-source" property to enable keyboard as the wakeup source, we need to add support for the new standard property "wakeup-source". This patch adds support for "wakeup-source" property in addition to the existing "nvidia,wakeup-source" property. Signed-off-by: Sudeep Holla Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index f97c73bd14f8..f80c72d4ac8f 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -517,7 +517,8 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) if (of_find_property(np, "nvidia,needs-ghost-filter", NULL)) kbc->use_ghost_filter = true; - if (of_find_property(np, "nvidia,wakeup-source", NULL)) + if (of_property_read_bool(np, "wakeup-source") || + of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */ kbc->wakeup = true; if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { -- cgit v1.2.3 From 8ad165e9228208b3ec21b5714c06c691b2236850 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 26 Oct 2015 01:36:00 -0700 Subject: Input: tegra-kbc - drop use of IRQF_NO_SUSPEND flag The driver handles wakeup irq correctly using device_init_wakeup and enable_irq_wake. There's no need to use IRQF_NO_SUSPEND while registering the interrupt. This patch removes the use of IRQF_NO_SUSPEND flag. Signed-off-by: Sudeep Holla Acked-by: Thierry Reding Acked-by: Laxman Dewangan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index f80c72d4ac8f..acc5394afb03 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -706,7 +706,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) input_set_drvdata(kbc->idev, kbc); err = devm_request_irq(&pdev->dev, kbc->irq, tegra_kbc_isr, - IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); + IRQF_TRIGGER_HIGH, pdev->name, kbc); if (err) { dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); return err; -- cgit v1.2.3 From 05f216ddca08728fcb7b1eb3808159b81b48c124 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Sun, 25 Oct 2015 13:49:29 -0700 Subject: Input: e3x0-button - update Kconfig description The driver is now used for the entire USRP e3xx series, this commit fixes the description that will be displayed in the menu accordingly. Signed-off-by: Moritz Fischer Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index d1ef61c2decd..d6d16fa78281 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -94,11 +94,11 @@ config INPUT_BMA150 module will be called bma150. config INPUT_E3X0_BUTTON - tristate "NI Ettus Research USRP E3x0 Button support." + tristate "NI Ettus Research USRP E3xx Button support." default n help Say Y here to enable support for the NI Ettus Research - USRP E3x0 Button. + USRP E3xx Button. To compile this driver as a module, choose M here: the module will be called e3x0_button. -- cgit v1.2.3 From 9ace41adb46e36e0709983702230d3602210c171 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 26 Oct 2015 01:45:01 -0700 Subject: Input: snvs_pwrkey - remove duplicated semicolon Remove the unneded semicolon since it is clearly a typo error. Signed-off-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/snvs_pwrkey.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index 78fd24ca3813..9adf13a5864a 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -110,8 +110,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) if (!pdata) return -ENOMEM; - pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");; - + pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap"); if (!pdata->snvs) { dev_err(&pdev->dev, "Can't get snvs syscon\n"); return -ENODEV; -- cgit v1.2.3 From 06a16293f71927f756dcf37558a79c0b05a91641 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sat, 24 Oct 2015 16:20:18 -0700 Subject: Input: evdev - add event-mask API Hardware manufacturers group keys in the weirdest way possible. This may cause a power-key to be grouped together with normal keyboard keys and thus be reported on the same kernel interface. However, user-space is often only interested in specific sets of events. For instance, daemons dealing with system-reboot (like systemd-logind) listen for KEY_POWER, but are not interested in any main keyboard keys. Usually, power keys are reported via separate interfaces, however, some i8042 boards report it in the AT matrix. To avoid waking up those system daemons on each key-press, we had two ideas: - split off KEY_POWER into a separate interface unconditionally - allow filtering a specific set of events on evdev FDs Splitting of KEY_POWER is a rather weird way to deal with this and may break backwards-compatibility. It is also specific to KEY_POWER and might be required for other stuff, too. Moreover, we might end up with a huge set of input-devices just to have them properly split. Hence, this patchset implements the second idea: An event-mask to specify which events you're interested in. Two ioctls allow setting this mask for each event-type. If not set, all events are reported. The type==0 entry is used same as in EVIOCGBIT to set the actual EV_* mask of filtered events. This way, you have a two-level filter. We are heavily forward-compatible to new event-types and event-codes. So new user-space will be able to run on an old kernel which doesn't know the given event-codes or event-types. Signed-off-by: David Herrmann Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 234 ++++++++++++++++++++++++++++++++++++++++++++- include/uapi/linux/input.h | 60 ++++++++++++ 2 files changed, 292 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 08d496411f75..6b10f5b29218 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -58,10 +58,55 @@ struct evdev_client { struct list_head node; int clk_type; bool revoked; + unsigned long *evmasks[EV_CNT]; unsigned int bufsize; struct input_event buffer[]; }; +static size_t evdev_get_mask_cnt(unsigned int type) +{ + static const size_t counts[EV_CNT] = { + /* EV_SYN==0 is EV_CNT, _not_ SYN_CNT, see EVIOCGBIT */ + [EV_SYN] = EV_CNT, + [EV_KEY] = KEY_CNT, + [EV_REL] = REL_CNT, + [EV_ABS] = ABS_CNT, + [EV_MSC] = MSC_CNT, + [EV_SW] = SW_CNT, + [EV_LED] = LED_CNT, + [EV_SND] = SND_CNT, + [EV_FF] = FF_CNT, + }; + + return (type < EV_CNT) ? counts[type] : 0; +} + +/* requires the buffer lock to be held */ +static bool __evdev_is_filtered(struct evdev_client *client, + unsigned int type, + unsigned int code) +{ + unsigned long *mask; + size_t cnt; + + /* EV_SYN and unknown codes are never filtered */ + if (type == EV_SYN || type >= EV_CNT) + return false; + + /* first test whether the type is filtered */ + mask = client->evmasks[0]; + if (mask && !test_bit(type, mask)) + return true; + + /* unknown values are never filtered */ + cnt = evdev_get_mask_cnt(type); + if (!cnt || code >= cnt) + return false; + + mask = client->evmasks[type]; + return mask && !test_bit(code, mask); +} + /* flush queued events of type @type, caller must hold client->buffer_lock */ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) { @@ -226,12 +271,21 @@ static void evdev_pass_values(struct evdev_client *client, spin_lock(&client->buffer_lock); for (v = vals; v != vals + count; v++) { + if (__evdev_is_filtered(client, v->type, v->code)) + continue; + + if (v->type == EV_SYN && v->code == SYN_REPORT) { + /* drop empty SYN_REPORT */ + if (client->packet_head == client->head) + continue; + + wakeup = true; + } + event.type = v->type; event.code = v->code; event.value = v->value; __pass_event(client, &event); - if (v->type == EV_SYN && v->code == SYN_REPORT) - wakeup = true; } spin_unlock(&client->buffer_lock); @@ -410,6 +464,7 @@ static int evdev_release(struct inode *inode, struct file *file) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; + unsigned int i; mutex_lock(&evdev->mutex); evdev_ungrab(evdev, client); @@ -417,6 +472,9 @@ static int evdev_release(struct inode *inode, struct file *file) evdev_detach_client(evdev, client); + for (i = 0; i < EV_CNT; ++i) + kfree(client->evmasks[i]); + kvfree(client); evdev_close_device(evdev); @@ -627,7 +685,46 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit, return len; } + +static int bits_from_user(unsigned long *bits, unsigned int maxbit, + unsigned int maxlen, const void __user *p, int compat) +{ + int len, i; + + if (compat) { + if (maxlen % sizeof(compat_long_t)) + return -EINVAL; + + len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t); + if (len > maxlen) + len = maxlen; + + for (i = 0; i < len / sizeof(compat_long_t); i++) + if (copy_from_user((compat_long_t *) bits + + i + 1 - ((i % 2) << 1), + (compat_long_t __user *) p + i, + sizeof(compat_long_t))) + return -EFAULT; + if (i % 2) + *((compat_long_t *) bits + i - 1) = 0; + + } else { + if (maxlen % sizeof(long)) + return -EINVAL; + + len = BITS_TO_LONGS(maxbit) * sizeof(long); + if (len > maxlen) + len = maxlen; + + if (copy_from_user(bits, p, len)) + return -EFAULT; + } + + return len; +} + #else + static int bits_to_user(unsigned long *bits, unsigned int maxbit, unsigned int maxlen, void __user *p, int compat) { @@ -640,6 +737,24 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit, return copy_to_user(p, bits, len) ? -EFAULT : len; } + +static int bits_from_user(unsigned long *bits, unsigned int maxbit, + unsigned int maxlen, const void __user *p, int compat) +{ + size_t chunk_size = compat ? sizeof(compat_long_t) : sizeof(long); + int len; + + if (maxlen % chunk_size) + return -EINVAL; + + len = compat ? BITS_TO_LONGS_COMPAT(maxbit) : BITS_TO_LONGS(maxbit); + len *= chunk_size; + if (len > maxlen) + len = maxlen; + + return copy_from_user(bits, p, len) ? -EFAULT : len; +} + #endif /* __BIG_ENDIAN */ #else @@ -655,6 +770,21 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit, return copy_to_user(p, bits, len) ? -EFAULT : len; } +static int bits_from_user(unsigned long *bits, unsigned int maxbit, + unsigned int maxlen, const void __user *p, int compat) +{ + int len; + + if (maxlen % sizeof(long)) + return -EINVAL; + + len = BITS_TO_LONGS(maxbit) * sizeof(long); + if (len > maxlen) + len = maxlen; + + return copy_from_user(bits, p, len) ? -EFAULT : len; +} + #endif /* CONFIG_COMPAT */ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) @@ -849,6 +979,81 @@ static int evdev_revoke(struct evdev *evdev, struct evdev_client *client, return 0; } +/* must be called with evdev-mutex held */ +static int evdev_set_mask(struct evdev_client *client, + unsigned int type, + const void __user *codes, + u32 codes_size, + int compat) +{ + unsigned long flags, *mask, *oldmask; + size_t cnt; + int error; + + /* we allow unknown types and 'codes_size > size' for forward-compat */ + cnt = evdev_get_mask_cnt(type); + if (!cnt) + return 0; + + mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL); + if (!mask) + return -ENOMEM; + + error = bits_from_user(mask, cnt - 1, codes_size, codes, compat); + if (error < 0) { + kfree(mask); + return error; + } + + spin_lock_irqsave(&client->buffer_lock, flags); + oldmask = client->evmasks[type]; + client->evmasks[type] = mask; + spin_unlock_irqrestore(&client->buffer_lock, flags); + + kfree(oldmask); + + return 0; +} + +/* must be called with evdev-mutex held */ +static int evdev_get_mask(struct evdev_client *client, + unsigned int type, + void __user *codes, + u32 codes_size, + int compat) +{ + unsigned long *mask; + size_t cnt, size, xfer_size; + int i; + int error; + + /* we allow unknown types and 'codes_size > size' for forward-compat */ + cnt = evdev_get_mask_cnt(type); + size = sizeof(unsigned long) * BITS_TO_LONGS(cnt); + xfer_size = min_t(size_t, codes_size, size); + + if (cnt > 0) { + mask = client->evmasks[type]; + if (mask) { + error = bits_to_user(mask, cnt - 1, + xfer_size, codes, compat); + if (error < 0) + return error; + } else { + /* fake mask with all bits set */ + for (i = 0; i < xfer_size; i++) + if (put_user(0xffU, (u8 __user *)codes + i)) + return -EFAULT; + } + } + + if (xfer_size < codes_size) + if (clear_user(codes + xfer_size, codes_size - xfer_size)) + return -EFAULT; + + return 0; +} + static long evdev_do_ioctl(struct file *file, unsigned int cmd, void __user *p, int compat_mode) { @@ -856,6 +1061,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct evdev *evdev = client->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; + struct input_mask mask; struct ff_effect effect; int __user *ip = (int __user *)p; unsigned int i, t, u, v; @@ -917,6 +1123,30 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, else return evdev_revoke(evdev, client, file); + case EVIOCGMASK: { + void __user *codes_ptr; + + if (copy_from_user(&mask, p, sizeof(mask))) + return -EFAULT; + + codes_ptr = (void __user *)(unsigned long)mask.codes_ptr; + return evdev_get_mask(client, + mask.type, codes_ptr, mask.codes_size, + compat_mode); + } + + case EVIOCSMASK: { + const void __user *codes_ptr; + + if (copy_from_user(&mask, p, sizeof(mask))) + return -EFAULT; + + codes_ptr = (const void __user *)(unsigned long)mask.codes_ptr; + return evdev_set_mask(client, + mask.type, codes_ptr, mask.codes_size, + compat_mode); + } + case EVIOCSCLOCKID: if (copy_from_user(&i, p, sizeof(unsigned int))) return -EFAULT; diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index 4f9f2a0f5573..2758687300b4 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -98,6 +98,12 @@ struct input_keymap_entry { __u8 scancode[32]; }; +struct input_mask { + __u32 type; + __u32 codes_size; + __u64 codes_ptr; +}; + #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ #define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ @@ -155,6 +161,60 @@ struct input_keymap_entry { #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ #define EVIOCREVOKE _IOW('E', 0x91, int) /* Revoke device access */ +/** + * EVIOCGMASK - Retrieve current event mask + * + * This ioctl allows user to retrieve the current event mask for specific + * event type. The argument must be of type "struct input_mask" and + * specifies the event type to query, the address of the receive buffer and + * the size of the receive buffer. + * + * The event mask is a per-client mask that specifies which events are + * forwarded to the client. Each event code is represented by a single bit + * in the event mask. If the bit is set, the event is passed to the client + * normally. Otherwise, the event is filtered and will never be queued on + * the client's receive buffer. + * + * Event masks do not affect global state of the input device. They only + * affect the file descriptor they are applied to. + * + * The default event mask for a client has all bits set, i.e. all events + * are forwarded to the client. If the kernel is queried for an unknown + * event type or if the receive buffer is larger than the number of + * event codes known to the kernel, the kernel returns all zeroes for those + * codes. + * + * At maximum, codes_size bytes are copied. + * + * This ioctl may fail with ENODEV in case the file is revoked, EFAULT + * if the receive-buffer points to invalid memory, or EINVAL if the kernel + * does not implement the ioctl. + */ +#define EVIOCGMASK _IOR('E', 0x92, struct input_mask) /* Get event-masks */ + +/** + * EVIOCSMASK - Set event mask + * + * This ioctl is the counterpart to EVIOCGMASK. Instead of receiving the + * current event mask, this changes the client's event mask for a specific + * type. See EVIOCGMASK for a description of event-masks and the + * argument-type. + * + * This ioctl provides full forward compatibility. If the passed event type + * is unknown to the kernel, or if the number of event codes specified in + * the mask is bigger than what is known to the kernel, the ioctl is still + * accepted and applied. However, any unknown codes are left untouched and + * stay cleared. That means, the kernel always filters unknown codes + * regardless of what the client requests. If the new mask doesn't cover + * all known event-codes, all remaining codes are automatically cleared and + * thus filtered. + * + * This ioctl may fail with ENODEV in case the file is revoked. EFAULT is + * returned if the receive-buffer points to invalid memory. EINVAL is returned + * if the kernel does not implement the ioctl. + */ +#define EVIOCSMASK _IOW('E', 0x93, struct input_mask) /* Set event-masks */ + #define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */ /* -- cgit v1.2.3 From 5523662edd4fe937267053c2018b75be2ac17860 Mon Sep 17 00:00:00 2001 From: Stephen Chandler Paul Date: Sat, 24 Oct 2015 13:10:29 -0700 Subject: Input: add userio module Debugging input devices, specifically laptop touchpads, can be tricky without having the physical device handy. Here we try to remedy that with userio. This module allows an application to connect to a character device provided by the kernel, and emulate any serio device. In combination with userspace programs that can record PS/2 devices and replay them through the /dev/userio device, this allows developers to debug driver issues on the PS/2 level with devices simply by requesting a recording from the user experiencing the issue without having to have the physical hardware in front of them. Signed-off-by: Stephen Chandler Paul Reviewed-by: David Herrmann Signed-off-by: Dmitry Torokhov --- Documentation/input/userio.txt | 70 ++++++++++ MAINTAINERS | 6 + drivers/input/serio/Kconfig | 14 ++ drivers/input/serio/Makefile | 1 + drivers/input/serio/userio.c | 285 +++++++++++++++++++++++++++++++++++++++++ include/linux/miscdevice.h | 1 + include/uapi/linux/userio.h | 44 +++++++ 7 files changed, 421 insertions(+) create mode 100644 Documentation/input/userio.txt create mode 100644 drivers/input/serio/userio.c create mode 100644 include/uapi/linux/userio.h (limited to 'drivers/input') diff --git a/Documentation/input/userio.txt b/Documentation/input/userio.txt new file mode 100644 index 000000000000..0880c0f447a6 --- /dev/null +++ b/Documentation/input/userio.txt @@ -0,0 +1,70 @@ + The userio Protocol + (c) 2015 Stephen Chandler Paul + Sponsored by Red Hat +-------------------------------------------------------------------------------- + +1. Introduction +~~~~~~~~~~~~~~~ + This module is intended to try to make the lives of input driver developers +easier by allowing them to test various serio devices (mainly the various +touchpads found on laptops) without having to have the physical device in front +of them. userio accomplishes this by allowing any privileged userspace program +to directly interact with the kernel's serio driver and control a virtual serio +port from there. + +2. Usage overview +~~~~~~~~~~~~~~~~~ + In order to interact with the userio kernel module, one simply opens the +/dev/userio character device in their applications. Commands are sent to the +kernel module by writing to the device, and any data received from the serio +driver is read as-is from the /dev/userio device. All of the structures and +macros you need to interact with the device are defined in and +. + +3. Command Structure +~~~~~~~~~~~~~~~~~~~~ + The struct used for sending commands to /dev/userio is as follows: + + struct userio_cmd { + __u8 type; + __u8 data; + }; + + "type" describes the type of command that is being sent. This can be any one +of the USERIO_CMD macros defined in . "data" is the argument +that goes along with the command. In the event that the command doesn't have an +argument, this field can be left untouched and will be ignored by the kernel. +Each command should be sent by writing the struct directly to the character +device. In the event that the command you send is invalid, an error will be +returned by the character device and a more descriptive error will be printed +to the kernel log. Only one command can be sent at a time, any additional data +written to the character device after the initial command will be ignored. + To close the virtual serio port, just close /dev/userio. + +4. Commands +~~~~~~~~~~~ + +4.1 USERIO_CMD_REGISTER +~~~~~~~~~~~~~~~~~~~~~~~ + Registers the port with the serio driver and begins transmitting data back and +forth. Registration can only be performed once a port type is set with +USERIO_CMD_SET_PORT_TYPE. Has no argument. + +4.2 USERIO_CMD_SET_PORT_TYPE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Sets the type of port we're emulating, where "data" is the port type being +set. Can be any of the macros from . For example: SERIO_8042 +would set the port type to be a normal PS/2 port. + +4.3 USERIO_CMD_SEND_INTERRUPT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Sends an interrupt through the virtual serio port to the serio driver, where +"data" is the interrupt data being sent. + +5. Userspace tools +~~~~~~~~~~~~~~~~~~ + The userio userspace tools are able to record PS/2 devices using some of the +debugging information from i8042, and play back the devices on /dev/userio. The +latest version of these tools can be found at: + + https://github.com/Lyude/ps2emu diff --git a/MAINTAINERS b/MAINTAINERS index 797236befd27..ba59bd7b3557 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11100,6 +11100,12 @@ S: Maintained F: drivers/media/v4l2-core/videobuf2-* F: include/media/videobuf2-* +VIRTUAL SERIO DEVICE DRIVER +M: Stephen Chandler Paul +S: Maintained +F: drivers/input/serio/userio.c +F: include/uapi/linux/userio.h + VIRTIO CONSOLE DRIVER M: Amit Shah L: virtualization@lists.linux-foundation.org diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 200841b77edb..c3d05b4d3118 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -292,4 +292,18 @@ config SERIO_SUN4I_PS2 To compile this driver as a module, choose M here: the module will be called sun4i-ps2. +config USERIO + tristate "User space serio port driver support" + help + Say Y here if you want to support user level drivers for serio + subsystem accessible under char device 10:240 - /dev/userio. Using + this facility userspace programs can implement serio ports that + will be used by the standard in-kernel serio consumer drivers, + such as psmouse and atkbd. + + To compile this driver as a module, choose M here: the module will be + called userio. + + If you are unsure, say N. + endif diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index c600089b7a34..2374ef9b33d7 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o +obj-$(CONFIG_USERIO) += userio.o diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c new file mode 100644 index 000000000000..df1fd41860ac --- /dev/null +++ b/drivers/input/serio/userio.c @@ -0,0 +1,285 @@ +/* + * userio kernel serio device emulation module + * Copyright (C) 2015 Red Hat + * Copyright (C) 2015 Stephen Chandler Paul + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USERIO_NAME "userio" +#define USERIO_BUFSIZE 16 + +static struct miscdevice userio_misc; + +struct userio_device { + struct serio *serio; + struct mutex mutex; + + bool running; + + u8 head; + u8 tail; + + spinlock_t buf_lock; + unsigned char buf[USERIO_BUFSIZE]; + + wait_queue_head_t waitq; +}; + +/** + * userio_device_write - Write data from serio to a userio device in userspace + * @id: The serio port for the userio device + * @val: The data to write to the device + */ +static int userio_device_write(struct serio *id, unsigned char val) +{ + struct userio_device *userio = id->port_data; + unsigned long flags; + + spin_lock_irqsave(&userio->buf_lock, flags); + + userio->buf[userio->head] = val; + userio->head = (userio->head + 1) % USERIO_BUFSIZE; + + if (userio->head == userio->tail) + dev_warn(userio_misc.this_device, + "Buffer overflowed, userio client isn't keeping up"); + + spin_unlock_irqrestore(&userio->buf_lock, flags); + + wake_up_interruptible(&userio->waitq); + + return 0; +} + +static int userio_char_open(struct inode *inode, struct file *file) +{ + struct userio_device *userio; + + userio = kzalloc(sizeof(struct userio_device), GFP_KERNEL); + if (!userio) + return -ENOMEM; + + mutex_init(&userio->mutex); + spin_lock_init(&userio->buf_lock); + init_waitqueue_head(&userio->waitq); + + userio->serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!userio->serio) { + kfree(userio); + return -ENOMEM; + } + + userio->serio->write = userio_device_write; + userio->serio->port_data = userio; + + file->private_data = userio; + + return 0; +} + +static int userio_char_release(struct inode *inode, struct file *file) +{ + struct userio_device *userio = file->private_data; + + if (userio->running) { + /* + * Don't free the serio port here, serio_unregister_port() + * does it for us. + */ + serio_unregister_port(userio->serio); + } else { + kfree(userio->serio); + } + + kfree(userio); + + return 0; +} + +static ssize_t userio_char_read(struct file *file, char __user *user_buffer, + size_t count, loff_t *ppos) +{ + struct userio_device *userio = file->private_data; + int error; + size_t nonwrap_len, copylen; + unsigned char buf[USERIO_BUFSIZE]; + unsigned long flags; + + /* + * By the time we get here, the data that was waiting might have + * been taken by another thread. Grab the buffer lock and check if + * there's still any data waiting, otherwise repeat this process + * until we have data (unless the file descriptor is non-blocking + * of course). + */ + for (;;) { + spin_lock_irqsave(&userio->buf_lock, flags); + + nonwrap_len = CIRC_CNT_TO_END(userio->head, + userio->tail, + USERIO_BUFSIZE); + copylen = min(nonwrap_len, count); + if (copylen) { + memcpy(buf, &userio->buf[userio->tail], copylen); + userio->tail = (userio->tail + copylen) % + USERIO_BUFSIZE; + } + + spin_unlock_irqrestore(&userio->buf_lock, flags); + + if (nonwrap_len) + break; + + /* buffer was/is empty */ + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + /* + * count == 0 is special - no IO is done but we check + * for error conditions (see above). + */ + if (count == 0) + return 0; + + error = wait_event_interruptible(userio->waitq, + userio->head != userio->tail); + if (error) + return error; + } + + if (copylen) + if (copy_to_user(user_buffer, buf, copylen)) + return -EFAULT; + + return copylen; +} + +static ssize_t userio_char_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct userio_device *userio = file->private_data; + struct userio_cmd cmd; + int error; + + if (count != sizeof(cmd)) { + dev_warn(userio_misc.this_device, "Invalid payload size\n"); + return -EINVAL; + } + + if (copy_from_user(&cmd, buffer, sizeof(cmd))) + return -EFAULT; + + error = mutex_lock_interruptible(&userio->mutex); + if (error) + return error; + + switch (cmd.type) { + case USERIO_CMD_REGISTER: + if (!userio->serio->id.type) { + dev_warn(userio_misc.this_device, + "No port type given on /dev/userio\n"); + + error = -EINVAL; + goto out; + } + + if (userio->running) { + dev_warn(userio_misc.this_device, + "Begin command sent, but we're already running\n"); + error = -EBUSY; + goto out; + } + + userio->running = true; + serio_register_port(userio->serio); + break; + + case USERIO_CMD_SET_PORT_TYPE: + if (userio->running) { + dev_warn(userio_misc.this_device, + "Can't change port type on an already running userio instance\n"); + error = -EBUSY; + goto out; + } + + userio->serio->id.type = cmd.data; + break; + + case USERIO_CMD_SEND_INTERRUPT: + if (!userio->running) { + dev_warn(userio_misc.this_device, + "The device must be registered before sending interrupts\n"); + error = -ENODEV; + goto out; + } + + serio_interrupt(userio->serio, cmd.data, 0); + break; + + default: + error = -EOPNOTSUPP; + goto out; + } + +out: + mutex_unlock(&userio->mutex); + return error ?: count; +} + +static unsigned int userio_char_poll(struct file *file, poll_table *wait) +{ + struct userio_device *userio = file->private_data; + + poll_wait(file, &userio->waitq, wait); + + if (userio->head != userio->tail) + return POLLIN | POLLRDNORM; + + return 0; +} + +static const struct file_operations userio_fops = { + .owner = THIS_MODULE, + .open = userio_char_open, + .release = userio_char_release, + .read = userio_char_read, + .write = userio_char_write, + .poll = userio_char_poll, + .llseek = no_llseek, +}; + +static struct miscdevice userio_misc = { + .fops = &userio_fops, + .minor = USERIO_MINOR, + .name = USERIO_NAME, +}; +module_driver(userio_misc, misc_register, misc_deregister); + +MODULE_ALIAS_MISCDEV(USERIO_MINOR); +MODULE_ALIAS("devname:" USERIO_NAME); + +MODULE_AUTHOR("Stephen Chandler Paul "); +MODULE_DESCRIPTION("Virtual Serio Device Support"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 81f6e427ba6b..543037465973 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -49,6 +49,7 @@ #define LOOP_CTRL_MINOR 237 #define VHOST_NET_MINOR 238 #define UHID_MINOR 239 +#define USERIO_MINOR 240 #define MISC_DYNAMIC_MINOR 255 struct device; diff --git a/include/uapi/linux/userio.h b/include/uapi/linux/userio.h new file mode 100644 index 000000000000..37d147f0a13a --- /dev/null +++ b/include/uapi/linux/userio.h @@ -0,0 +1,44 @@ +/* + * userio: virtual serio device support + * Copyright (C) 2015 Red Hat + * Copyright (C) 2015 Lyude (Stephen Chandler Paul) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License for more + * details. + * + * This is the public header used for user-space communication with the userio + * driver. __attribute__((__packed__)) is used for all structs to keep ABI + * compatibility between all architectures. + */ + +#ifndef _USERIO_H +#define _USERIO_H + +#include + +enum userio_cmd_type { + USERIO_CMD_REGISTER = 0, + USERIO_CMD_SET_PORT_TYPE = 1, + USERIO_CMD_SEND_INTERRUPT = 2 +}; + +/* + * userio Commands + * All commands sent to /dev/userio are encoded using this structure. The type + * field should contain a USERIO_CMD* value that indicates what kind of command + * is being sent to userio. The data field should contain the accompanying + * argument for the command, if there is one. + */ +struct userio_cmd { + __u8 type; + __u8 data; +} __attribute__((__packed__)); + +#endif /* !_USERIO_H */ -- cgit v1.2.3 From bf5f18d708802737fa0db6306f6b9148f85b2efd Mon Sep 17 00:00:00 2001 From: Aniroop Mathur Date: Fri, 30 Oct 2015 04:15:37 -0700 Subject: Input: evdev - fix bug in checking duplicate clock change request clk_type and clkid stores different predefined clock identification values so they cannot be compared for checking duplicate clock change request. Therefore, lets fix it to avoid unexpected results. Signed-off-by: Aniroop Mathur Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6b10f5b29218..e9ae3d500a55 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -56,7 +56,7 @@ struct evdev_client { struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; - int clk_type; + unsigned int clk_type; bool revoked; unsigned long *evmasks[EV_CNT]; unsigned int bufsize; @@ -191,37 +191,39 @@ static void evdev_queue_syn_dropped(struct evdev_client *client) static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) { unsigned long flags; - - if (client->clk_type == clkid) - return 0; + unsigned int clk_type; switch (clkid) { case CLOCK_REALTIME: - client->clk_type = EV_CLK_REAL; + clk_type = EV_CLK_REAL; break; case CLOCK_MONOTONIC: - client->clk_type = EV_CLK_MONO; + clk_type = EV_CLK_MONO; break; case CLOCK_BOOTTIME: - client->clk_type = EV_CLK_BOOT; + clk_type = EV_CLK_BOOT; break; default: return -EINVAL; } - /* - * Flush pending events and queue SYN_DROPPED event, - * but only if the queue is not empty. - */ - spin_lock_irqsave(&client->buffer_lock, flags); + if (client->clk_type != clk_type) { + client->clk_type = clk_type; - if (client->head != client->tail) { - client->packet_head = client->head = client->tail; - __evdev_queue_syn_dropped(client); - } + /* + * Flush pending events and queue SYN_DROPPED event, + * but only if the queue is not empty. + */ + spin_lock_irqsave(&client->buffer_lock, flags); - spin_unlock_irqrestore(&client->buffer_lock, flags); + if (client->head != client->tail) { + client->packet_head = client->head = client->tail; + __evdev_queue_syn_dropped(client); + } + + spin_unlock_irqrestore(&client->buffer_lock, flags); + } return 0; } -- cgit v1.2.3