Merge branch 'akpm' (aka "Andrew's patch-bomb")
Andrew elucidates: - First installmeant of MM. We have a HUGE number of MM patches this time. It's crazy. - MAINTAINERS updates - backlight updates - leds - checkpatch updates - misc ELF stuff - rtc updates - reiserfs - procfs - some misc other bits * akpm: (124 commits) user namespace: make signal.c respect user namespaces workqueue: make alloc_workqueue() take printf fmt and args for name procfs: add hidepid= and gid= mount options procfs: parse mount options procfs: introduce the /proc/<pid>/map_files/ directory procfs: make proc_get_link to use dentry instead of inode signal: add block_sigmask() for adding sigmask to current->blocked sparc: make SA_NOMASK a synonym of SA_NODEFER reiserfs: don't lock root inode searching reiserfs: don't lock journal_init() reiserfs: delay reiserfs lock until journal initialization reiserfs: delete comments referring to the BKL drivers/rtc/interface.c: fix alarm rollover when day or month is out-of-range drivers/rtc/rtc-twl.c: add DT support for RTC inside twl4030/twl6030 drivers/rtc/: remove redundant spi driver bus initialization drivers/rtc/rtc-jz4740.c: make jz4740_rtc_driver static drivers/rtc/rtc-mc13xxx.c: make mc13xxx_rtc_idtable static rtc: convert drivers/rtc/* to use module_platform_driver() drivers/rtc/rtc-wm831x.c: convert to devm_kzalloc() drivers/rtc/rtc-wm831x.c: remove unused period IRQ handler ...
This commit is contained in:
Коммит
40ba587923
|
@ -0,0 +1,12 @@
|
|||
What: Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
|
||||
Date: Oct 2011
|
||||
KernelVersion: 3.0
|
||||
Contact: Mark Godfrey <mark.godfrey@stericsson.com>
|
||||
Description: The rtc_calibration attribute allows the userspace to
|
||||
calibrate the AB8500.s 32KHz Real Time Clock.
|
||||
Every 60 seconds the AB8500 will correct the RTC's value
|
||||
by adding to it the value of this attribute.
|
||||
The range of the attribute is -127 to +127 in units of
|
||||
30.5 micro-seconds (half-parts-per-million of the 32KHz clock)
|
||||
Users: The /vendor/st-ericsson/base_utilities/core/rtc_calibration
|
||||
daemon uses this interface.
|
|
@ -0,0 +1,12 @@
|
|||
* TI twl RTC
|
||||
|
||||
The TWL family (twl4030/6030) contains a RTC.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be twl4030-rtc
|
||||
|
||||
Examples:
|
||||
|
||||
rtc@0 {
|
||||
compatible = "ti,twl4030-rtc";
|
||||
};
|
|
@ -41,6 +41,8 @@ Table of Contents
|
|||
3.5 /proc/<pid>/mountinfo - Information about mounts
|
||||
3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
|
||||
|
||||
4 Configuring procfs
|
||||
4.1 Mount options
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Preface
|
||||
|
@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value
|
|||
is limited in size compared to the cmdline value, so writing anything longer
|
||||
then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated
|
||||
comm value.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Configuring procfs
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
4.1 Mount options
|
||||
---------------------
|
||||
|
||||
The following mount options are supported:
|
||||
|
||||
hidepid= Set /proc/<pid>/ access mode.
|
||||
gid= Set the group authorized to learn processes information.
|
||||
|
||||
hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories
|
||||
(default).
|
||||
|
||||
hidepid=1 means users may not access any /proc/<pid>/ directories but their
|
||||
own. Sensitive files like cmdline, sched*, status are now protected against
|
||||
other users. This makes it impossible to learn whether any user runs
|
||||
specific program (given the program doesn't reveal itself by its behaviour).
|
||||
As an additional bonus, as /proc/<pid>/cmdline is unaccessible for other users,
|
||||
poorly written programs passing sensitive information via program arguments are
|
||||
now protected against local eavesdroppers.
|
||||
|
||||
hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be fully invisible to other
|
||||
users. It doesn't mean that it hides a fact whether a process with a specific
|
||||
pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"),
|
||||
but it hides process' uid and gid, which may be learned by stat()'ing
|
||||
/proc/<pid>/ otherwise. It greatly complicates an intruder's task of gathering
|
||||
information about running processes, whether some daemon runs with elevated
|
||||
privileges, whether other user runs some sensitive program, whether other users
|
||||
run any program at all, etc.
|
||||
|
||||
gid= defines a group authorized to learn processes information otherwise
|
||||
prohibited by hidepid=. If you use some daemon like identd which needs to learn
|
||||
information about processes information, just add identd to this group.
|
||||
|
|
|
@ -628,6 +628,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
no_debug_objects
|
||||
[KNL] Disable object debugging
|
||||
|
||||
debug_guardpage_minorder=
|
||||
[KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
|
||||
parameter allows control of the order of pages that will
|
||||
be intentionally kept free (and hence protected) by the
|
||||
buddy allocator. Bigger value increase the probability
|
||||
of catching random memory corruption, but reduce the
|
||||
amount of memory for normal system use. The maximum
|
||||
possible value is MAX_ORDER/2. Setting this parameter
|
||||
to 1 or 2 should be enough to identify most random
|
||||
memory corruption problems caused by bugs in kernel or
|
||||
driver code when a CPU writes to (or reads from) a
|
||||
random memory location. Note that there exists a class
|
||||
of memory corruptions problems caused by buggy H/W or
|
||||
F/W or by drivers badly programing DMA (basically when
|
||||
memory is written at bus level and the CPU MMU is
|
||||
bypassed) which are not detectable by
|
||||
CONFIG_DEBUG_PAGEALLOC, hence this option will not help
|
||||
tracking down these problems.
|
||||
|
||||
debugpat [X86] Enable PAT debugging
|
||||
|
||||
decnet.addr= [HW,NET]
|
||||
|
|
|
@ -40,8 +40,8 @@ but the call_site can usually be used to extrapolate that information.
|
|||
==================
|
||||
mm_page_alloc page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s
|
||||
mm_page_alloc_zone_locked page=%p pfn=%lu order=%u migratetype=%d cpu=%d percpu_refill=%d
|
||||
mm_page_free_direct page=%p pfn=%lu order=%d
|
||||
mm_pagevec_free page=%p pfn=%lu order=%d cold=%d
|
||||
mm_page_free page=%p pfn=%lu order=%d
|
||||
mm_page_free_batched page=%p pfn=%lu order=%d cold=%d
|
||||
|
||||
These four events deal with page allocation and freeing. mm_page_alloc is
|
||||
a simple indicator of page allocator activity. Pages may be allocated from
|
||||
|
@ -53,13 +53,13 @@ amounts of activity imply high activity on the zone->lock. Taking this lock
|
|||
impairs performance by disabling interrupts, dirtying cache lines between
|
||||
CPUs and serialising many CPUs.
|
||||
|
||||
When a page is freed directly by the caller, the mm_page_free_direct event
|
||||
When a page is freed directly by the caller, the only mm_page_free event
|
||||
is triggered. Significant amounts of activity here could indicate that the
|
||||
callers should be batching their activities.
|
||||
|
||||
When pages are freed using a pagevec, the mm_pagevec_free is
|
||||
triggered. Broadly speaking, pages are taken off the LRU lock in bulk and
|
||||
freed in batch with a pagevec. Significant amounts of activity here could
|
||||
When pages are freed in batch, the also mm_page_free_batched is triggered.
|
||||
Broadly speaking, pages are taken off the LRU lock in bulk and
|
||||
freed in batch with a page list. Significant amounts of activity here could
|
||||
indicate that the system is under memory pressure and can also indicate
|
||||
contention on the zone->lru_lock.
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ use Getopt::Long;
|
|||
|
||||
# Tracepoint events
|
||||
use constant MM_PAGE_ALLOC => 1;
|
||||
use constant MM_PAGE_FREE_DIRECT => 2;
|
||||
use constant MM_PAGEVEC_FREE => 3;
|
||||
use constant MM_PAGE_FREE => 2;
|
||||
use constant MM_PAGE_FREE_BATCHED => 3;
|
||||
use constant MM_PAGE_PCPU_DRAIN => 4;
|
||||
use constant MM_PAGE_ALLOC_ZONE_LOCKED => 5;
|
||||
use constant MM_PAGE_ALLOC_EXTFRAG => 6;
|
||||
|
@ -223,10 +223,10 @@ EVENT_PROCESS:
|
|||
# Perl Switch() sucks majorly
|
||||
if ($tracepoint eq "mm_page_alloc") {
|
||||
$perprocesspid{$process_pid}->{MM_PAGE_ALLOC}++;
|
||||
} elsif ($tracepoint eq "mm_page_free_direct") {
|
||||
$perprocesspid{$process_pid}->{MM_PAGE_FREE_DIRECT}++;
|
||||
} elsif ($tracepoint eq "mm_pagevec_free") {
|
||||
$perprocesspid{$process_pid}->{MM_PAGEVEC_FREE}++;
|
||||
} elsif ($tracepoint eq "mm_page_free") {
|
||||
$perprocesspid{$process_pid}->{MM_PAGE_FREE}++
|
||||
} elsif ($tracepoint eq "mm_page_free_batched") {
|
||||
$perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}++;
|
||||
} elsif ($tracepoint eq "mm_page_pcpu_drain") {
|
||||
$perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}++;
|
||||
$perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED}++;
|
||||
|
@ -336,8 +336,8 @@ sub dump_stats {
|
|||
$process_pid,
|
||||
$stats{$process_pid}->{MM_PAGE_ALLOC},
|
||||
$stats{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED},
|
||||
$stats{$process_pid}->{MM_PAGE_FREE_DIRECT},
|
||||
$stats{$process_pid}->{MM_PAGEVEC_FREE},
|
||||
$stats{$process_pid}->{MM_PAGE_FREE},
|
||||
$stats{$process_pid}->{MM_PAGE_FREE_BATCHED},
|
||||
$stats{$process_pid}->{MM_PAGE_PCPU_DRAIN},
|
||||
$stats{$process_pid}->{HIGH_PCPU_DRAINS},
|
||||
$stats{$process_pid}->{HIGH_PCPU_REFILLS},
|
||||
|
@ -364,8 +364,8 @@ sub aggregate_perprocesspid() {
|
|||
|
||||
$perprocess{$process}->{MM_PAGE_ALLOC} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC};
|
||||
$perprocess{$process}->{MM_PAGE_ALLOC_ZONE_LOCKED} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED};
|
||||
$perprocess{$process}->{MM_PAGE_FREE_DIRECT} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_DIRECT};
|
||||
$perprocess{$process}->{MM_PAGEVEC_FREE} += $perprocesspid{$process_pid}->{MM_PAGEVEC_FREE};
|
||||
$perprocess{$process}->{MM_PAGE_FREE} += $perprocesspid{$process_pid}->{MM_PAGE_FREE};
|
||||
$perprocess{$process}->{MM_PAGE_FREE_BATCHED} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED};
|
||||
$perprocess{$process}->{MM_PAGE_PCPU_DRAIN} += $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN};
|
||||
$perprocess{$process}->{HIGH_PCPU_DRAINS} += $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS};
|
||||
$perprocess{$process}->{HIGH_PCPU_REFILLS} += $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS};
|
||||
|
|
|
@ -93,14 +93,14 @@ By specifying the -a switch and analysing sleep, the system-wide events
|
|||
for a duration of time can be examined.
|
||||
|
||||
$ perf stat -a \
|
||||
-e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
|
||||
-e kmem:mm_pagevec_free \
|
||||
-e kmem:mm_page_alloc -e kmem:mm_page_free \
|
||||
-e kmem:mm_page_free_batched \
|
||||
sleep 10
|
||||
Performance counter stats for 'sleep 10':
|
||||
|
||||
9630 kmem:mm_page_alloc
|
||||
2143 kmem:mm_page_free_direct
|
||||
7424 kmem:mm_pagevec_free
|
||||
2143 kmem:mm_page_free
|
||||
7424 kmem:mm_page_free_batched
|
||||
|
||||
10.002577764 seconds time elapsed
|
||||
|
||||
|
@ -119,15 +119,15 @@ basis using set_ftrace_pid.
|
|||
Events can be activated and tracked for the duration of a process on a local
|
||||
basis using PCL such as follows.
|
||||
|
||||
$ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
|
||||
-e kmem:mm_pagevec_free ./hackbench 10
|
||||
$ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free \
|
||||
-e kmem:mm_page_free_batched ./hackbench 10
|
||||
Time: 0.909
|
||||
|
||||
Performance counter stats for './hackbench 10':
|
||||
|
||||
17803 kmem:mm_page_alloc
|
||||
12398 kmem:mm_page_free_direct
|
||||
4827 kmem:mm_pagevec_free
|
||||
12398 kmem:mm_page_free
|
||||
4827 kmem:mm_page_free_batched
|
||||
|
||||
0.973913387 seconds time elapsed
|
||||
|
||||
|
@ -146,8 +146,8 @@ to know what the standard deviation is. By and large, this is left to the
|
|||
performance analyst to do it by hand. In the event that the discrete event
|
||||
occurrences are useful to the performance analyst, then perf can be used.
|
||||
|
||||
$ perf stat --repeat 5 -e kmem:mm_page_alloc -e kmem:mm_page_free_direct
|
||||
-e kmem:mm_pagevec_free ./hackbench 10
|
||||
$ perf stat --repeat 5 -e kmem:mm_page_alloc -e kmem:mm_page_free
|
||||
-e kmem:mm_page_free_batched ./hackbench 10
|
||||
Time: 0.890
|
||||
Time: 0.895
|
||||
Time: 0.915
|
||||
|
@ -157,8 +157,8 @@ occurrences are useful to the performance analyst, then perf can be used.
|
|||
Performance counter stats for './hackbench 10' (5 runs):
|
||||
|
||||
16630 kmem:mm_page_alloc ( +- 3.542% )
|
||||
11486 kmem:mm_page_free_direct ( +- 4.771% )
|
||||
4730 kmem:mm_pagevec_free ( +- 2.325% )
|
||||
11486 kmem:mm_page_free ( +- 4.771% )
|
||||
4730 kmem:mm_page_free_batched ( +- 2.325% )
|
||||
|
||||
0.982653002 seconds time elapsed ( +- 1.448% )
|
||||
|
||||
|
@ -168,15 +168,15 @@ aggregation of discrete events, then a script would need to be developed.
|
|||
Using --repeat, it is also possible to view how events are fluctuating over
|
||||
time on a system-wide basis using -a and sleep.
|
||||
|
||||
$ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
|
||||
-e kmem:mm_pagevec_free \
|
||||
$ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free \
|
||||
-e kmem:mm_page_free_batched \
|
||||
-a --repeat 10 \
|
||||
sleep 1
|
||||
Performance counter stats for 'sleep 1' (10 runs):
|
||||
|
||||
1066 kmem:mm_page_alloc ( +- 26.148% )
|
||||
182 kmem:mm_page_free_direct ( +- 5.464% )
|
||||
890 kmem:mm_pagevec_free ( +- 30.079% )
|
||||
182 kmem:mm_page_free ( +- 5.464% )
|
||||
890 kmem:mm_page_free_batched ( +- 30.079% )
|
||||
|
||||
1.002251757 seconds time elapsed ( +- 0.005% )
|
||||
|
||||
|
@ -220,8 +220,8 @@ were generating events within the kernel. To begin this sort of analysis, the
|
|||
data must be recorded. At the time of writing, this required root:
|
||||
|
||||
$ perf record -c 1 \
|
||||
-e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
|
||||
-e kmem:mm_pagevec_free \
|
||||
-e kmem:mm_page_alloc -e kmem:mm_page_free \
|
||||
-e kmem:mm_page_free_batched \
|
||||
./hackbench 10
|
||||
Time: 0.894
|
||||
[ perf record: Captured and wrote 0.733 MB perf.data (~32010 samples) ]
|
||||
|
@ -260,8 +260,8 @@ noticed that X was generating an insane amount of page allocations so let's look
|
|||
at it:
|
||||
|
||||
$ perf record -c 1 -f \
|
||||
-e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
|
||||
-e kmem:mm_pagevec_free \
|
||||
-e kmem:mm_page_alloc -e kmem:mm_page_free \
|
||||
-e kmem:mm_page_free_batched \
|
||||
-p `pidof X`
|
||||
|
||||
This was interrupted after a few seconds and
|
||||
|
|
49
MAINTAINERS
49
MAINTAINERS
|
@ -342,7 +342,7 @@ S: Supported
|
|||
F: drivers/mfd/adp5520.c
|
||||
F: drivers/video/backlight/adp5520_bl.c
|
||||
F: drivers/leds/leds-adp5520.c
|
||||
F: drivers/gpio/adp5520-gpio.c
|
||||
F: drivers/gpio/gpio-adp5520.c
|
||||
F: drivers/input/keyboard/adp5520-keys.c
|
||||
|
||||
ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
|
||||
|
@ -351,7 +351,7 @@ L: device-drivers-devel@blackfin.uclinux.org
|
|||
W: http://wiki.analog.com/ADP5588
|
||||
S: Supported
|
||||
F: drivers/input/keyboard/adp5588-keys.c
|
||||
F: drivers/gpio/adp5588-gpio.c
|
||||
F: drivers/gpio/gpio-adp5588.c
|
||||
|
||||
ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863)
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
|
@ -914,7 +914,6 @@ M: Lennert Buytenhek <kernel@wantstofly.org>
|
|||
M: Nicolas Pitre <nico@fluxnic.net>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Odd Fixes
|
||||
F: arch/arm/mach-loki/
|
||||
F: arch/arm/mach-kirkwood/
|
||||
F: arch/arm/mach-mv78xx0/
|
||||
F: arch/arm/mach-orion5x/
|
||||
|
@ -1076,8 +1075,8 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: arch/arm/mach-s5pv210/mach-aquila.c
|
||||
F: arch/arm/mach-s5pv210/mach-goni.c
|
||||
F: arch/arm/mach-exynos4/mach-universal_c210.c
|
||||
F: arch/arm/mach-exynos4/mach-nuri.c
|
||||
F: arch/arm/mach-exynos/mach-universal_c210.c
|
||||
F: arch/arm/mach-exynos/mach-nuri.c
|
||||
|
||||
ARM/SAMSUNG S5P SERIES FIMC SUPPORT
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
|
@ -1105,7 +1104,6 @@ M: Tomasz Stanislawski <t.stanislaws@samsung.com>
|
|||
L: linux-arm-kernel@lists.infradead.org
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/arm/plat-s5p/dev-tv.c
|
||||
F: drivers/media/video/s5p-tv/
|
||||
|
||||
ARM/SHMOBILE ARM ARCHITECTURE
|
||||
|
@ -1140,14 +1138,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|||
W: http://www.mcuos.com
|
||||
S: Maintained
|
||||
F: arch/arm/mach-w90x900/
|
||||
F: arch/arm/mach-nuc93x/
|
||||
F: drivers/input/keyboard/w90p910_keypad.c
|
||||
F: drivers/input/touchscreen/w90p910_ts.c
|
||||
F: drivers/watchdog/nuc900_wdt.c
|
||||
F: drivers/net/ethernet/nuvoton/w90p910_ether.c
|
||||
F: drivers/mtd/nand/nuc900_nand.c
|
||||
F: drivers/rtc/rtc-nuc900.c
|
||||
F: drivers/spi/spi_nuc900.c
|
||||
F: drivers/spi/spi-nuc900.c
|
||||
F: drivers/usb/host/ehci-w90x900.c
|
||||
F: drivers/video/nuc900fb.c
|
||||
|
||||
|
@ -1172,7 +1169,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: arch/arm/mach-ux500/
|
||||
F: drivers/dma/ste_dma40*
|
||||
F: drivers/mfd/ab3550*
|
||||
F: drivers/mfd/abx500*
|
||||
F: drivers/mfd/ab8500*
|
||||
F: drivers/mfd/stmpe*
|
||||
|
@ -1352,7 +1348,7 @@ F: drivers/net/ethernet/cadence/
|
|||
ATMEL SPI DRIVER
|
||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
S: Supported
|
||||
F: drivers/spi/atmel_spi.*
|
||||
F: drivers/spi/spi-atmel.*
|
||||
|
||||
ATMEL USBA UDC DRIVER
|
||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
|
@ -1491,7 +1487,7 @@ M: Sonic Zhang <sonic.zhang@analog.com>
|
|||
L: uclinux-dist-devel@blackfin.uclinux.org
|
||||
W: http://blackfin.uclinux.org
|
||||
S: Supported
|
||||
F: drivers/tty/serial/bfin_5xx.c
|
||||
F: drivers/tty/serial/bfin_uart.c
|
||||
|
||||
BLACKFIN WATCHDOG DRIVER
|
||||
M: Mike Frysinger <vapier.adi@gmail.com>
|
||||
|
@ -1621,7 +1617,7 @@ BT8XXGPIO DRIVER
|
|||
M: Michael Buesch <m@bues.ch>
|
||||
W: http://bu3sch.de/btgpio.php
|
||||
S: Maintained
|
||||
F: drivers/gpio/bt8xxgpio.c
|
||||
F: drivers/gpio/gpio-bt8xx.c
|
||||
|
||||
BTRFS FILE SYSTEM
|
||||
M: Chris Mason <chris.mason@oracle.com>
|
||||
|
@ -1662,7 +1658,7 @@ L: linux-media@vger.kernel.org
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
|
||||
S: Maintained
|
||||
F: Documentation/video4linux/cafe_ccic
|
||||
F: drivers/media/video/cafe_ccic*
|
||||
F: drivers/media/video/marvell-ccic/
|
||||
|
||||
CAIF NETWORK LAYER
|
||||
M: Sjur Braendeland <sjur.brandeland@stericsson.com>
|
||||
|
@ -2100,7 +2096,7 @@ DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
|
|||
L: netdev@vger.kernel.org
|
||||
S: Orphan
|
||||
F: Documentation/networking/dmfe.txt
|
||||
F: drivers/net/ethernet/tulip/dmfe.c
|
||||
F: drivers/net/ethernet/dec/tulip/dmfe.c
|
||||
|
||||
DC390/AM53C974 SCSI driver
|
||||
M: Kurt Garloff <garloff@suse.de>
|
||||
|
@ -2173,6 +2169,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
|||
S: Maintained
|
||||
F: drivers/usb/dwc3/
|
||||
|
||||
DEVICE FREQUENCY (DEVFREQ)
|
||||
M: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/devfreq/
|
||||
|
||||
DEVICE NUMBER REGISTRY
|
||||
M: Torben Mathiasen <device@lanana.org>
|
||||
W: http://lanana.org/docs/device-list/index.html
|
||||
|
@ -2910,7 +2913,7 @@ GRETH 10/100/1G Ethernet MAC device driver
|
|||
M: Kristoffer Glembo <kristoffer@gaisler.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/greth*
|
||||
F: drivers/net/ethernet/aeroflex/
|
||||
|
||||
GSPCA FINEPIX SUBDRIVER
|
||||
M: Frank Zago <frank@zago.net>
|
||||
|
@ -3860,8 +3863,7 @@ L: keyrings@linux-nfs.org
|
|||
S: Supported
|
||||
F: Documentation/security/keys-trusted-encrypted.txt
|
||||
F: include/keys/encrypted-type.h
|
||||
F: security/keys/encrypted.c
|
||||
F: security/keys/encrypted.h
|
||||
F: security/keys/encrypted-keys/
|
||||
|
||||
KGDB / KDB /debug_core
|
||||
M: Jason Wessel <jason.wessel@windriver.com>
|
||||
|
@ -5313,7 +5315,7 @@ T: git git://git.linaro.org/people/ycmiao/pxa-linux.git
|
|||
S: Maintained
|
||||
F: arch/arm/mach-pxa/
|
||||
F: drivers/pcmcia/pxa2xx*
|
||||
F: drivers/spi/pxa2xx*
|
||||
F: drivers/spi/spi-pxa2xx*
|
||||
F: drivers/usb/gadget/pxa2*
|
||||
F: include/sound/pxa2xx-lib.h
|
||||
F: sound/arm/pxa*
|
||||
|
@ -5795,13 +5797,14 @@ L: linux-mmc@vger.kernel.org
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
|
||||
S: Maintained
|
||||
F: drivers/mmc/host/sdhci.*
|
||||
F: drivers/mmc/host/sdhci-pltfm.[ch]
|
||||
|
||||
SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
|
||||
M: Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
L: linux-mmc@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/mmc/host/sdhci-of.*
|
||||
F: drivers/mmc/host/sdhci-pltfm.[ch]
|
||||
|
||||
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
|
||||
M: Ben Dooks <ben-linux@fluff.org>
|
||||
|
@ -6180,9 +6183,7 @@ M: Viresh Kumar <viresh.kumar@st.com>
|
|||
W: http://www.st.com/spear
|
||||
S: Maintained
|
||||
F: arch/arm/mach-spear*/clock.c
|
||||
F: arch/arm/mach-spear*/include/mach/clkdev.h
|
||||
F: arch/arm/plat-spear/clock.c
|
||||
F: arch/arm/plat-spear/include/plat/clkdev.h
|
||||
F: arch/arm/plat-spear/include/plat/clock.h
|
||||
|
||||
SPEAR PAD MULTIPLEXING SUPPORT
|
||||
|
@ -6306,7 +6307,7 @@ STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
|
|||
M: Jarod Wilson <jarod@wilsonet.com>
|
||||
W: http://www.lirc.org/
|
||||
S: Odd Fixes
|
||||
F: drivers/staging/lirc/
|
||||
F: drivers/staging/media/lirc/
|
||||
|
||||
STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
|
||||
M: Julian Andres Klode <jak@jak-linux.org>
|
||||
|
@ -6342,7 +6343,7 @@ F: drivers/staging/sm7xx/
|
|||
STAGING - SOFTLOGIC 6x10 MPEG CODEC
|
||||
M: Ben Collins <bcollins@bluecherry.net>
|
||||
S: Odd Fixes
|
||||
F: drivers/staging/solo6x10/
|
||||
F: drivers/staging/media/solo6x10/
|
||||
|
||||
STAGING - SPEAKUP CONSOLE SPEECH DRIVER
|
||||
M: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
@ -6645,7 +6646,7 @@ TULIP NETWORK DRIVERS
|
|||
M: Grant Grundler <grundler@parisc-linux.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/tulip/
|
||||
F: drivers/net/ethernet/dec/tulip/
|
||||
|
||||
TUN/TAP driver
|
||||
M: Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
|
|
|
@ -16,6 +16,7 @@ config ARM
|
|||
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
|
||||
select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
|
||||
select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
|
||||
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZO
|
||||
|
|
|
@ -16,6 +16,7 @@ config MIPS
|
|||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||
select RTC_LIB if !MACH_LOONGSON
|
||||
select GENERIC_ATOMIC64 if !64BIT
|
||||
select HAVE_DMA_ATTRS
|
||||
|
|
|
@ -143,10 +143,11 @@ struct sigstack {
|
|||
#define SA_ONSTACK _SV_SSTACK
|
||||
#define SA_RESTART _SV_INTR
|
||||
#define SA_ONESHOT _SV_RESET
|
||||
#define SA_NOMASK 0x20u
|
||||
#define SA_NODEFER 0x20u
|
||||
#define SA_NOCLDWAIT 0x100u
|
||||
#define SA_SIGINFO 0x200u
|
||||
|
||||
#define SA_NOMASK SA_NODEFER
|
||||
|
||||
#define SIG_BLOCK 0x01 /* for blocking signals */
|
||||
#define SIG_UNBLOCK 0x02 /* for unblocking signals */
|
||||
|
|
|
@ -62,6 +62,7 @@ config X86
|
|||
select ANON_INODES
|
||||
select HAVE_ARCH_KMEMCHECK
|
||||
select HAVE_USER_RETURN_NOTIFIER
|
||||
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_TEXT_POKE_SMP
|
||||
select HAVE_GENERIC_HARDIRQS
|
||||
|
|
|
@ -682,7 +682,6 @@ static int
|
|||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t blocked;
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
|
@ -733,10 +732,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
|||
*/
|
||||
regs->flags &= ~X86_EFLAGS_TF;
|
||||
|
||||
sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&blocked, sig);
|
||||
set_current_blocked(&blocked);
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
tracehook_signal_handler(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
|
|
|
@ -388,6 +388,14 @@ config LEDS_RENESAS_TPU
|
|||
pin function. The latter to support brightness control.
|
||||
Brightness control is supported but hardware blinking is not.
|
||||
|
||||
config LEDS_TCA6507
|
||||
tristate "LED Support for TCA6507 I2C chip"
|
||||
depends on LEDS_CLASS && I2C
|
||||
help
|
||||
This option enables support for LEDs connected to TC6507
|
||||
LED driver chips accessed via the I2C bus.
|
||||
Driver support brightness control and hardware-assisted blinking.
|
||||
|
||||
config LEDS_TRIGGERS
|
||||
bool "LED Trigger support"
|
||||
depends on LEDS_CLASS
|
||||
|
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
|
|||
obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
|
||||
obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
|
||||
obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
|
||||
obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
|
||||
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
|
||||
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
|
||||
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
|
||||
|
|
|
@ -238,17 +238,7 @@ static struct platform_driver pm860x_led_driver = {
|
|||
.remove = pm860x_led_remove,
|
||||
};
|
||||
|
||||
static int __devinit pm860x_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&pm860x_led_driver);
|
||||
}
|
||||
module_init(pm860x_led_init);
|
||||
|
||||
static void __devexit pm860x_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pm860x_led_driver);
|
||||
}
|
||||
module_exit(pm860x_led_exit);
|
||||
module_platform_driver(pm860x_led_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LED driver for Marvell PM860x");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
|
|
|
@ -213,17 +213,7 @@ static struct platform_driver adp5520_led_driver = {
|
|||
.remove = __devexit_p(adp5520_led_remove),
|
||||
};
|
||||
|
||||
static int __init adp5520_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&adp5520_led_driver);
|
||||
}
|
||||
module_init(adp5520_led_init);
|
||||
|
||||
static void __exit adp5520_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&adp5520_led_driver);
|
||||
}
|
||||
module_exit(adp5520_led_exit);
|
||||
module_platform_driver(adp5520_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
|
||||
MODULE_DESCRIPTION("LEDS ADP5520(01) Driver");
|
||||
|
|
|
@ -118,18 +118,7 @@ static struct platform_driver ams_delta_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init ams_delta_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&ams_delta_led_driver);
|
||||
}
|
||||
|
||||
static void __exit ams_delta_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ams_delta_led_driver);
|
||||
}
|
||||
|
||||
module_init(ams_delta_led_init);
|
||||
module_exit(ams_delta_led_exit);
|
||||
module_platform_driver(ams_delta_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
|
||||
MODULE_DESCRIPTION("Amstrad Delta LED driver");
|
||||
|
|
|
@ -179,21 +179,9 @@ static struct platform_driver asic3_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:leds-asic3");
|
||||
|
||||
static int __init asic3_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&asic3_led_driver);
|
||||
}
|
||||
|
||||
static void __exit asic3_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&asic3_led_driver);
|
||||
}
|
||||
|
||||
module_init(asic3_led_init);
|
||||
module_exit(asic3_led_exit);
|
||||
module_platform_driver(asic3_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
|
||||
MODULE_DESCRIPTION("HTC ASIC3 LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:leds-asic3");
|
||||
|
|
|
@ -134,29 +134,18 @@ static int __exit pwmled_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:leds-atmel-pwm");
|
||||
|
||||
static struct platform_driver pwmled_driver = {
|
||||
.driver = {
|
||||
.name = "leds-atmel-pwm",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
/* REVISIT add suspend() and resume() methods */
|
||||
.probe = pwmled_probe,
|
||||
.remove = __exit_p(pwmled_remove),
|
||||
};
|
||||
|
||||
static int __init modinit(void)
|
||||
{
|
||||
return platform_driver_probe(&pwmled_driver, pwmled_probe);
|
||||
}
|
||||
module_init(modinit);
|
||||
|
||||
static void __exit modexit(void)
|
||||
{
|
||||
platform_driver_unregister(&pwmled_driver);
|
||||
}
|
||||
module_exit(modexit);
|
||||
module_platform_driver(pwmled_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:leds-atmel-pwm");
|
||||
|
|
|
@ -688,8 +688,7 @@ static int __devinit bd2802_probe(struct i2c_client *client,
|
|||
i2c_set_clientdata(client, led);
|
||||
|
||||
/* Configure RESET GPIO (L: RESET, H: RESET cancel) */
|
||||
gpio_request(pdata->reset_gpio, "RGB_RESETB");
|
||||
gpio_direction_output(pdata->reset_gpio, 1);
|
||||
gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, "RGB_RESETB");
|
||||
|
||||
/* Tacss = min 0.1ms */
|
||||
udelay(100);
|
||||
|
@ -813,17 +812,7 @@ static struct i2c_driver bd2802_i2c_driver = {
|
|||
.id_table = bd2802_id,
|
||||
};
|
||||
|
||||
static int __init bd2802_init(void)
|
||||
{
|
||||
return i2c_add_driver(&bd2802_i2c_driver);
|
||||
}
|
||||
module_init(bd2802_init);
|
||||
|
||||
static void __exit bd2802_exit(void)
|
||||
{
|
||||
i2c_del_driver(&bd2802_i2c_driver);
|
||||
}
|
||||
module_exit(bd2802_exit);
|
||||
module_i2c_driver(bd2802_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
|
||||
MODULE_DESCRIPTION("BD2802 LED driver");
|
||||
|
|
|
@ -75,9 +75,6 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:cobalt-qube-leds");
|
||||
|
||||
static struct platform_driver cobalt_qube_led_driver = {
|
||||
.probe = cobalt_qube_led_probe,
|
||||
.remove = __devexit_p(cobalt_qube_led_remove),
|
||||
|
@ -87,19 +84,9 @@ static struct platform_driver cobalt_qube_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init cobalt_qube_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&cobalt_qube_led_driver);
|
||||
}
|
||||
|
||||
static void __exit cobalt_qube_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&cobalt_qube_led_driver);
|
||||
}
|
||||
|
||||
module_init(cobalt_qube_led_init);
|
||||
module_exit(cobalt_qube_led_exit);
|
||||
module_platform_driver(cobalt_qube_led_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Front LED support for Cobalt Server");
|
||||
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
|
||||
MODULE_ALIAS("platform:cobalt-qube-leds");
|
||||
|
|
|
@ -158,17 +158,7 @@ static struct platform_driver da903x_led_driver = {
|
|||
.remove = __devexit_p(da903x_led_remove),
|
||||
};
|
||||
|
||||
static int __init da903x_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&da903x_led_driver);
|
||||
}
|
||||
module_init(da903x_led_init);
|
||||
|
||||
static void __exit da903x_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&da903x_led_driver);
|
||||
}
|
||||
module_exit(da903x_led_exit);
|
||||
module_platform_driver(da903x_led_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
|
||||
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
|
||||
|
|
|
@ -131,18 +131,7 @@ static struct spi_driver dac124s085_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init dac124s085_leds_init(void)
|
||||
{
|
||||
return spi_register_driver(&dac124s085_driver);
|
||||
}
|
||||
|
||||
static void __exit dac124s085_leds_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&dac124s085_driver);
|
||||
}
|
||||
|
||||
module_init(dac124s085_leds_init);
|
||||
module_exit(dac124s085_leds_exit);
|
||||
module_spi_driver(dac124s085_driver);
|
||||
|
||||
MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
|
||||
MODULE_DESCRIPTION("DAC124S085 LED driver");
|
||||
|
|
|
@ -224,20 +224,7 @@ static struct platform_driver fsg_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
static int __init fsg_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&fsg_led_driver);
|
||||
}
|
||||
|
||||
static void __exit fsg_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&fsg_led_driver);
|
||||
}
|
||||
|
||||
|
||||
module_init(fsg_led_init);
|
||||
module_exit(fsg_led_exit);
|
||||
module_platform_driver(fsg_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
|
||||
MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
|
||||
|
|
|
@ -293,21 +293,9 @@ static struct platform_driver gpio_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:leds-gpio");
|
||||
|
||||
static int __init gpio_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&gpio_led_driver);
|
||||
}
|
||||
|
||||
static void __exit gpio_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&gpio_led_driver);
|
||||
}
|
||||
|
||||
module_init(gpio_led_init);
|
||||
module_exit(gpio_led_exit);
|
||||
module_platform_driver(gpio_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>");
|
||||
MODULE_DESCRIPTION("GPIO LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:leds-gpio");
|
||||
|
|
|
@ -79,9 +79,6 @@ static int hp6xxled_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:hp6xx-led");
|
||||
|
||||
static struct platform_driver hp6xxled_driver = {
|
||||
.probe = hp6xxled_probe,
|
||||
.remove = hp6xxled_remove,
|
||||
|
@ -91,19 +88,9 @@ static struct platform_driver hp6xxled_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init hp6xxled_init(void)
|
||||
{
|
||||
return platform_driver_register(&hp6xxled_driver);
|
||||
}
|
||||
|
||||
static void __exit hp6xxled_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&hp6xxled_driver);
|
||||
}
|
||||
|
||||
module_init(hp6xxled_init);
|
||||
module_exit(hp6xxled_exit);
|
||||
module_platform_driver(hp6xxled_driver);
|
||||
|
||||
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
|
||||
MODULE_DESCRIPTION("HP Jornada 6xx LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:hp6xx-led");
|
||||
|
|
|
@ -457,18 +457,7 @@ static struct i2c_driver lm3530_i2c_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init lm3530_init(void)
|
||||
{
|
||||
return i2c_add_driver(&lm3530_i2c_driver);
|
||||
}
|
||||
|
||||
static void __exit lm3530_exit(void)
|
||||
{
|
||||
i2c_del_driver(&lm3530_i2c_driver);
|
||||
}
|
||||
|
||||
module_init(lm3530_init);
|
||||
module_exit(lm3530_exit);
|
||||
module_i2c_driver(lm3530_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Back Light driver for LM3530");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -453,18 +453,7 @@ static struct i2c_driver lp3944_driver = {
|
|||
.id_table = lp3944_id,
|
||||
};
|
||||
|
||||
static int __init lp3944_module_init(void)
|
||||
{
|
||||
return i2c_add_driver(&lp3944_driver);
|
||||
}
|
||||
|
||||
static void __exit lp3944_module_exit(void)
|
||||
{
|
||||
i2c_del_driver(&lp3944_driver);
|
||||
}
|
||||
|
||||
module_init(lp3944_module_init);
|
||||
module_exit(lp3944_module_exit);
|
||||
module_i2c_driver(lp3944_driver);
|
||||
|
||||
MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
|
||||
MODULE_DESCRIPTION("LP3944 Fun Light Chip");
|
||||
|
|
|
@ -797,25 +797,7 @@ static struct i2c_driver lp5521_driver = {
|
|||
.id_table = lp5521_id,
|
||||
};
|
||||
|
||||
static int __init lp5521_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&lp5521_driver);
|
||||
|
||||
if (ret < 0)
|
||||
printk(KERN_ALERT "Adding lp5521 driver failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit lp5521_exit(void)
|
||||
{
|
||||
i2c_del_driver(&lp5521_driver);
|
||||
}
|
||||
|
||||
module_init(lp5521_init);
|
||||
module_exit(lp5521_exit);
|
||||
module_i2c_driver(lp5521_driver);
|
||||
|
||||
MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo");
|
||||
MODULE_DESCRIPTION("LP5521 LED engine");
|
||||
|
|
|
@ -870,8 +870,6 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver lp5523_driver;
|
||||
|
||||
static int __devinit lp5523_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -1021,25 +1019,7 @@ static struct i2c_driver lp5523_driver = {
|
|||
.id_table = lp5523_id,
|
||||
};
|
||||
|
||||
static int __init lp5523_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&lp5523_driver);
|
||||
|
||||
if (ret < 0)
|
||||
printk(KERN_ALERT "Adding lp5523 driver failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit lp5523_exit(void)
|
||||
{
|
||||
i2c_del_driver(&lp5523_driver);
|
||||
}
|
||||
|
||||
module_init(lp5523_init);
|
||||
module_exit(lp5523_exit);
|
||||
module_i2c_driver(lp5523_driver);
|
||||
|
||||
MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
|
||||
MODULE_DESCRIPTION("LP5523 LED engine");
|
||||
|
|
|
@ -199,21 +199,9 @@ static struct platform_driver lt3593_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:leds-lt3593");
|
||||
|
||||
static int __init lt3593_led_init(void)
|
||||
{
|
||||
return platform_driver_register(<3593_led_driver);
|
||||
}
|
||||
|
||||
static void __exit lt3593_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(<3593_led_driver);
|
||||
}
|
||||
|
||||
module_init(lt3593_led_init);
|
||||
module_exit(lt3593_led_exit);
|
||||
module_platform_driver(lt3593_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
|
||||
MODULE_DESCRIPTION("LED driver for LT3593 controllers");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:leds-lt3593");
|
||||
|
|
|
@ -275,7 +275,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) {
|
||||
if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) {
|
||||
dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -385,17 +385,7 @@ static struct platform_driver mc13783_led_driver = {
|
|||
.remove = __devexit_p(mc13783_led_remove),
|
||||
};
|
||||
|
||||
static int __init mc13783_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&mc13783_led_driver);
|
||||
}
|
||||
module_init(mc13783_led_init);
|
||||
|
||||
static void __exit mc13783_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mc13783_led_driver);
|
||||
}
|
||||
module_exit(mc13783_led_exit);
|
||||
module_platform_driver(mc13783_led_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
|
||||
MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
|
||||
|
|
|
@ -81,35 +81,23 @@ static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
|
|||
|
||||
/* Configure address GPIOs. */
|
||||
for (i = 0; i < gpio_ext->num_addr; i++) {
|
||||
err = gpio_request(gpio_ext->addr[i], "GPIO extension addr");
|
||||
err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW,
|
||||
"GPIO extension addr");
|
||||
if (err)
|
||||
goto err_free_addr;
|
||||
err = gpio_direction_output(gpio_ext->addr[i], 0);
|
||||
if (err) {
|
||||
gpio_free(gpio_ext->addr[i]);
|
||||
goto err_free_addr;
|
||||
}
|
||||
}
|
||||
/* Configure data GPIOs. */
|
||||
for (i = 0; i < gpio_ext->num_data; i++) {
|
||||
err = gpio_request(gpio_ext->data[i], "GPIO extension data");
|
||||
err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW,
|
||||
"GPIO extension data");
|
||||
if (err)
|
||||
goto err_free_data;
|
||||
err = gpio_direction_output(gpio_ext->data[i], 0);
|
||||
if (err) {
|
||||
gpio_free(gpio_ext->data[i]);
|
||||
goto err_free_data;
|
||||
}
|
||||
}
|
||||
/* Configure "enable select" GPIO. */
|
||||
err = gpio_request(gpio_ext->enable, "GPIO extension enable");
|
||||
err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW,
|
||||
"GPIO extension enable");
|
||||
if (err)
|
||||
goto err_free_data;
|
||||
err = gpio_direction_output(gpio_ext->enable, 0);
|
||||
if (err) {
|
||||
gpio_free(gpio_ext->enable);
|
||||
goto err_free_data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -429,21 +417,10 @@ static struct platform_driver netxbig_led_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
MODULE_ALIAS("platform:leds-netxbig");
|
||||
|
||||
static int __init netxbig_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&netxbig_led_driver);
|
||||
}
|
||||
|
||||
static void __exit netxbig_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&netxbig_led_driver);
|
||||
}
|
||||
|
||||
module_init(netxbig_led_init);
|
||||
module_exit(netxbig_led_exit);
|
||||
module_platform_driver(netxbig_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
|
||||
MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:leds-netxbig");
|
||||
|
|
|
@ -323,21 +323,10 @@ static struct platform_driver ns2_led_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
MODULE_ALIAS("platform:leds-ns2");
|
||||
|
||||
static int __init ns2_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&ns2_led_driver);
|
||||
}
|
||||
|
||||
static void __exit ns2_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ns2_led_driver);
|
||||
}
|
||||
|
||||
module_init(ns2_led_init);
|
||||
module_exit(ns2_led_exit);
|
||||
module_platform_driver(ns2_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
|
||||
MODULE_DESCRIPTION("Network Space v2 LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:leds-ns2");
|
||||
|
|
|
@ -489,20 +489,8 @@ static int pca9532_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init pca9532_init(void)
|
||||
{
|
||||
return i2c_add_driver(&pca9532_driver);
|
||||
}
|
||||
|
||||
static void __exit pca9532_exit(void)
|
||||
{
|
||||
i2c_del_driver(&pca9532_driver);
|
||||
}
|
||||
module_i2c_driver(pca9532_driver);
|
||||
|
||||
MODULE_AUTHOR("Riku Voipio");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("PCA 9532 LED dimmer");
|
||||
|
||||
module_init(pca9532_init);
|
||||
module_exit(pca9532_exit);
|
||||
|
||||
|
|
|
@ -371,18 +371,7 @@ static struct i2c_driver pca955x_driver = {
|
|||
.id_table = pca955x_id,
|
||||
};
|
||||
|
||||
static int __init pca955x_leds_init(void)
|
||||
{
|
||||
return i2c_add_driver(&pca955x_driver);
|
||||
}
|
||||
|
||||
static void __exit pca955x_leds_exit(void)
|
||||
{
|
||||
i2c_del_driver(&pca955x_driver);
|
||||
}
|
||||
|
||||
module_init(pca955x_leds_init);
|
||||
module_exit(pca955x_leds_exit);
|
||||
module_i2c_driver(pca955x_driver);
|
||||
|
||||
MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
|
||||
MODULE_DESCRIPTION("PCA955x LED driver");
|
||||
|
|
|
@ -135,18 +135,7 @@ static struct platform_driver led_pwm_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init led_pwm_init(void)
|
||||
{
|
||||
return platform_driver_register(&led_pwm_driver);
|
||||
}
|
||||
|
||||
static void __exit led_pwm_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&led_pwm_driver);
|
||||
}
|
||||
|
||||
module_init(led_pwm_init);
|
||||
module_exit(led_pwm_exit);
|
||||
module_platform_driver(led_pwm_driver);
|
||||
|
||||
MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
|
||||
MODULE_DESCRIPTION("PWM LED driver for PXA");
|
||||
|
|
|
@ -57,21 +57,9 @@ static struct platform_driver rb532_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init rb532_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&rb532_led_driver);
|
||||
}
|
||||
|
||||
static void __exit rb532_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rb532_led_driver);
|
||||
}
|
||||
|
||||
module_init(rb532_led_init);
|
||||
module_exit(rb532_led_exit);
|
||||
|
||||
MODULE_ALIAS("platform:rb532-led");
|
||||
module_platform_driver(rb532_led_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("User LED support for Routerboard532");
|
||||
MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
|
||||
MODULE_ALIAS("platform:rb532-led");
|
||||
|
|
|
@ -229,17 +229,7 @@ static struct platform_driver regulator_led_driver = {
|
|||
.remove = __devexit_p(regulator_led_remove),
|
||||
};
|
||||
|
||||
static int __init regulator_led_init(void)
|
||||
{
|
||||
return platform_driver_register(®ulator_led_driver);
|
||||
}
|
||||
module_init(regulator_led_init);
|
||||
|
||||
static void __exit regulator_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(®ulator_led_driver);
|
||||
}
|
||||
module_exit(regulator_led_exit);
|
||||
module_platform_driver(regulator_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
|
||||
MODULE_DESCRIPTION("Regulator driven LED driver");
|
||||
|
|
|
@ -339,18 +339,7 @@ static struct platform_driver r_tpu_device_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static int __init r_tpu_init(void)
|
||||
{
|
||||
return platform_driver_register(&r_tpu_device_driver);
|
||||
}
|
||||
|
||||
static void __exit r_tpu_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&r_tpu_device_driver);
|
||||
}
|
||||
|
||||
module_init(r_tpu_init);
|
||||
module_exit(r_tpu_exit);
|
||||
module_platform_driver(r_tpu_device_driver);
|
||||
|
||||
MODULE_AUTHOR("Magnus Damm");
|
||||
MODULE_DESCRIPTION("Renesas TPU LED Driver");
|
||||
|
|
|
@ -121,18 +121,7 @@ static struct platform_driver s3c24xx_led_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init s3c24xx_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&s3c24xx_led_driver);
|
||||
}
|
||||
|
||||
static void __exit s3c24xx_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c24xx_led_driver);
|
||||
}
|
||||
|
||||
module_init(s3c24xx_led_init);
|
||||
module_exit(s3c24xx_led_exit);
|
||||
module_platform_driver(s3c24xx_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||
MODULE_DESCRIPTION("S3C24XX LED driver");
|
||||
|
|
|
@ -0,0 +1,779 @@
|
|||
/*
|
||||
* leds-tca6507
|
||||
*
|
||||
* The TCA6507 is a programmable LED controller that can drive 7
|
||||
* separate lines either by holding them low, or by pulsing them
|
||||
* with modulated width.
|
||||
* The modulation can be varied in a simple pattern to produce a blink or
|
||||
* double-blink.
|
||||
*
|
||||
* This driver can configure each line either as a 'GPIO' which is out-only
|
||||
* (no pull-up) or as an LED with variable brightness and hardware-assisted
|
||||
* blinking.
|
||||
*
|
||||
* Apart from OFF and ON there are three programmable brightness levels which
|
||||
* can be programmed from 0 to 15 and indicate how many 500usec intervals in
|
||||
* each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and
|
||||
* BANK1.
|
||||
*
|
||||
* There are two different blink rates that can be programmed, each with
|
||||
* separate time for rise, on, fall, off and second-off. Thus if 3 or more
|
||||
* different non-trivial rates are required, software must be used for the extra
|
||||
* rates. The two different blink rates must align with the two levels BANK0 and
|
||||
* BANK1.
|
||||
* This driver does not support double-blink so 'second-off' always matches
|
||||
* 'off'.
|
||||
*
|
||||
* Only 16 different times can be programmed in a roughly logarithmic scale from
|
||||
* 64ms to 16320ms. To be precise the possible times are:
|
||||
* 0, 64, 128, 192, 256, 384, 512, 768,
|
||||
* 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
|
||||
*
|
||||
* Times that cannot be closely matched with these must be
|
||||
* handled in software. This driver allows 12.5% error in matching.
|
||||
*
|
||||
* This driver does not allow rise/fall rates to be set explicitly. When trying
|
||||
* to match a given 'on' or 'off' period, an appropriate pair of 'change' and
|
||||
* 'hold' times are chosen to get a close match. If the target delay is even,
|
||||
* the 'change' number will be the smaller; if odd, the 'hold' number will be
|
||||
* the smaller.
|
||||
|
||||
* Choosing pairs of delays with 12.5% errors allows us to match delays in the
|
||||
* ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
|
||||
* 26% of the achievable sums can be matched by multiple pairings. For example
|
||||
* 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the
|
||||
* pairing with the least maximum - 768+768 in this case. Other pairings are
|
||||
* not available.
|
||||
*
|
||||
* Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
|
||||
* Access can be shared by multiple leds if they have the same level and
|
||||
* either same blink rates, or some don't blink.
|
||||
* When a led changes, it relinquishes access and tries again, so it might
|
||||
* lose access to hardware blink.
|
||||
* If a blink engine cannot be allocated, software blink is used.
|
||||
* If the desired brightness cannot be allocated, the closest available non-zero
|
||||
* brightness is used. As 'full' is always available, the worst case would be
|
||||
* to have two different blink rates at '1', with Max at '2', then other leds
|
||||
* will have to choose between '2' and '16'. Hopefully this is not likely.
|
||||
*
|
||||
* Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
|
||||
* and LEDs using the blink. It can only be reprogrammed when the appropriate
|
||||
* counter is zero. The MASTER level has a single usage count.
|
||||
*
|
||||
* Each Led has programmable 'on' and 'off' time as milliseconds. With each
|
||||
* there is a flag saying if it was explicitly requested or defaulted.
|
||||
* Similarly the banks know if each time was explicit or a default. Defaults
|
||||
* are permitted to be changed freely - they are not recognised when matching.
|
||||
*
|
||||
*
|
||||
* An led-tca6507 device must be provided with platform data. This data
|
||||
* lists for each output: the name, default trigger, and whether the signal
|
||||
* is being used as a GPiO rather than an led. 'struct led_plaform_data'
|
||||
* is used for this. If 'name' is NULL, the output isn't used. If 'flags'
|
||||
* is TCA6507_MAKE_CPIO, the output is a GPO.
|
||||
* The "struct led_platform_data" can be embedded in a
|
||||
* "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
|
||||
* and a 'setup' callback which is called once the GPiOs are available.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/leds-tca6507.h>
|
||||
|
||||
/* LED select registers determine the source that drives LED outputs */
|
||||
#define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */
|
||||
#define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */
|
||||
#define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */
|
||||
#define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */
|
||||
#define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */
|
||||
#define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */
|
||||
#define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */
|
||||
#define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */
|
||||
|
||||
enum {
|
||||
BANK0,
|
||||
BANK1,
|
||||
MASTER,
|
||||
};
|
||||
static int bank_source[3] = {
|
||||
TCA6507_LS_LED_PWM0,
|
||||
TCA6507_LS_LED_PWM1,
|
||||
TCA6507_LS_LED_MIR,
|
||||
};
|
||||
static int blink_source[2] = {
|
||||
TCA6507_LS_BLINK0,
|
||||
TCA6507_LS_BLINK1,
|
||||
};
|
||||
|
||||
/* PWM registers */
|
||||
#define TCA6507_REG_CNT 11
|
||||
|
||||
/*
|
||||
* 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output
|
||||
* owns one bit in each register
|
||||
*/
|
||||
#define TCA6507_FADE_ON 0x03
|
||||
#define TCA6507_FULL_ON 0x04
|
||||
#define TCA6507_FADE_OFF 0x05
|
||||
#define TCA6507_FIRST_OFF 0x06
|
||||
#define TCA6507_SECOND_OFF 0x07
|
||||
#define TCA6507_MAX_INTENSITY 0x08
|
||||
#define TCA6507_MASTER_INTENSITY 0x09
|
||||
#define TCA6507_INITIALIZE 0x0A
|
||||
|
||||
#define INIT_CODE 0x8
|
||||
|
||||
#define TIMECODES 16
|
||||
static int time_codes[TIMECODES] = {
|
||||
0, 64, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
|
||||
};
|
||||
|
||||
/* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */
|
||||
static inline int TO_LEVEL(int brightness)
|
||||
{
|
||||
return brightness >> 4;
|
||||
}
|
||||
|
||||
/* ...and convert back */
|
||||
static inline int TO_BRIGHT(int level)
|
||||
{
|
||||
if (level)
|
||||
return (level << 4) | 0xf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NUM_LEDS 7
|
||||
struct tca6507_chip {
|
||||
int reg_set; /* One bit per register where
|
||||
* a '1' means the register
|
||||
* should be written */
|
||||
u8 reg_file[TCA6507_REG_CNT];
|
||||
/* Bank 2 is Master Intensity and doesn't use times */
|
||||
struct bank {
|
||||
int level;
|
||||
int ontime, offtime;
|
||||
int on_dflt, off_dflt;
|
||||
int time_use, level_use;
|
||||
} bank[3];
|
||||
struct i2c_client *client;
|
||||
struct work_struct work;
|
||||
spinlock_t lock;
|
||||
|
||||
struct tca6507_led {
|
||||
struct tca6507_chip *chip;
|
||||
struct led_classdev led_cdev;
|
||||
int num;
|
||||
int ontime, offtime;
|
||||
int on_dflt, off_dflt;
|
||||
int bank; /* Bank used, or -1 */
|
||||
int blink; /* Set if hardware-blinking */
|
||||
} leds[NUM_LEDS];
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct gpio_chip gpio;
|
||||
const char *gpio_name[NUM_LEDS];
|
||||
int gpio_map[NUM_LEDS];
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct i2c_device_id tca6507_id[] = {
|
||||
{ "tca6507" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tca6507_id);
|
||||
|
||||
static int choose_times(int msec, int *c1p, int *c2p)
|
||||
{
|
||||
/*
|
||||
* Choose two timecodes which add to 'msec' as near as possible.
|
||||
* The first returned is the 'on' or 'off' time. The second is to be
|
||||
* used as a 'fade-on' or 'fade-off' time. If 'msec' is even,
|
||||
* the first will not be smaller than the second. If 'msec' is odd,
|
||||
* the first will not be larger than the second.
|
||||
* If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
|
||||
* otherwise return the sum that was achieved, plus 1 if the first is
|
||||
* smaller.
|
||||
* If two possibilities are equally good (e.g. 512+0, 256+256), choose
|
||||
* the first pair so there is more change-time visible (i.e. it is
|
||||
* softer).
|
||||
*/
|
||||
int c1, c2;
|
||||
int tmax = msec * 9 / 8;
|
||||
int tmin = msec * 7 / 8;
|
||||
int diff = 65536;
|
||||
|
||||
/* We start at '1' to ensure we never even think of choosing a
|
||||
* total time of '0'.
|
||||
*/
|
||||
for (c1 = 1; c1 < TIMECODES; c1++) {
|
||||
int t = time_codes[c1];
|
||||
if (t*2 < tmin)
|
||||
continue;
|
||||
if (t > tmax)
|
||||
break;
|
||||
for (c2 = 0; c2 <= c1; c2++) {
|
||||
int tt = t + time_codes[c2];
|
||||
int d;
|
||||
if (tt < tmin)
|
||||
continue;
|
||||
if (tt > tmax)
|
||||
break;
|
||||
/* This works! */
|
||||
d = abs(msec - tt);
|
||||
if (d >= diff)
|
||||
continue;
|
||||
/* Best yet */
|
||||
*c1p = c1;
|
||||
*c2p = c2;
|
||||
diff = d;
|
||||
if (d == 0)
|
||||
return msec;
|
||||
}
|
||||
}
|
||||
if (diff < 65536) {
|
||||
int actual;
|
||||
if (msec & 1) {
|
||||
c1 = *c2p;
|
||||
*c2p = *c1p;
|
||||
*c1p = c1;
|
||||
}
|
||||
actual = time_codes[*c1p] + time_codes[*c2p];
|
||||
if (*c1p < *c2p)
|
||||
return actual + 1;
|
||||
else
|
||||
return actual;
|
||||
}
|
||||
/* No close match */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the register file with the appropriate 3-bit state for
|
||||
* the given led.
|
||||
*/
|
||||
static void set_select(struct tca6507_chip *tca, int led, int val)
|
||||
{
|
||||
int mask = (1 << led);
|
||||
int bit;
|
||||
|
||||
for (bit = 0; bit < 3; bit++) {
|
||||
int n = tca->reg_file[bit] & ~mask;
|
||||
if (val & (1 << bit))
|
||||
n |= mask;
|
||||
if (tca->reg_file[bit] != n) {
|
||||
tca->reg_file[bit] = n;
|
||||
tca->reg_set |= (1 << bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the register file with the appropriate 4-bit code for
|
||||
* one bank or other. This can be used for timers, for levels, or
|
||||
* for initialisation.
|
||||
*/
|
||||
static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
|
||||
{
|
||||
int mask = 0xF;
|
||||
int n;
|
||||
if (bank) {
|
||||
mask <<= 4;
|
||||
new <<= 4;
|
||||
}
|
||||
n = tca->reg_file[reg] & ~mask;
|
||||
n |= new;
|
||||
if (tca->reg_file[reg] != n) {
|
||||
tca->reg_file[reg] = n;
|
||||
tca->reg_set |= 1 << reg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update brightness level. */
|
||||
static void set_level(struct tca6507_chip *tca, int bank, int level)
|
||||
{
|
||||
switch (bank) {
|
||||
case BANK0:
|
||||
case BANK1:
|
||||
set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
|
||||
break;
|
||||
case MASTER:
|
||||
set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
|
||||
break;
|
||||
}
|
||||
tca->bank[bank].level = level;
|
||||
}
|
||||
|
||||
/* Record all relevant time code for a given bank */
|
||||
static void set_times(struct tca6507_chip *tca, int bank)
|
||||
{
|
||||
int c1, c2;
|
||||
int result;
|
||||
|
||||
result = choose_times(tca->bank[bank].ontime, &c1, &c2);
|
||||
dev_dbg(&tca->client->dev,
|
||||
"Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
|
||||
c2, time_codes[c2], tca->bank[bank].ontime);
|
||||
set_code(tca, TCA6507_FADE_ON, bank, c2);
|
||||
set_code(tca, TCA6507_FULL_ON, bank, c1);
|
||||
tca->bank[bank].ontime = result;
|
||||
|
||||
result = choose_times(tca->bank[bank].offtime, &c1, &c2);
|
||||
dev_dbg(&tca->client->dev,
|
||||
"Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
|
||||
c2, time_codes[c2], tca->bank[bank].offtime);
|
||||
set_code(tca, TCA6507_FADE_OFF, bank, c2);
|
||||
set_code(tca, TCA6507_FIRST_OFF, bank, c1);
|
||||
set_code(tca, TCA6507_SECOND_OFF, bank, c1);
|
||||
tca->bank[bank].offtime = result;
|
||||
|
||||
set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
|
||||
}
|
||||
|
||||
/* Write all needed register of tca6507 */
|
||||
|
||||
static void tca6507_work(struct work_struct *work)
|
||||
{
|
||||
struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
|
||||
work);
|
||||
struct i2c_client *cl = tca->client;
|
||||
int set;
|
||||
u8 file[TCA6507_REG_CNT];
|
||||
int r;
|
||||
|
||||
spin_lock_irq(&tca->lock);
|
||||
set = tca->reg_set;
|
||||
memcpy(file, tca->reg_file, TCA6507_REG_CNT);
|
||||
tca->reg_set = 0;
|
||||
spin_unlock_irq(&tca->lock);
|
||||
|
||||
for (r = 0; r < TCA6507_REG_CNT; r++)
|
||||
if (set & (1<<r))
|
||||
i2c_smbus_write_byte_data(cl, r, file[r]);
|
||||
}
|
||||
|
||||
static void led_release(struct tca6507_led *led)
|
||||
{
|
||||
/* If led owns any resource, release it. */
|
||||
struct tca6507_chip *tca = led->chip;
|
||||
if (led->bank >= 0) {
|
||||
struct bank *b = tca->bank + led->bank;
|
||||
if (led->blink)
|
||||
b->time_use--;
|
||||
b->level_use--;
|
||||
}
|
||||
led->blink = 0;
|
||||
led->bank = -1;
|
||||
}
|
||||
|
||||
static int led_prepare(struct tca6507_led *led)
|
||||
{
|
||||
/* Assign this led to a bank, configuring that bank if necessary. */
|
||||
int level = TO_LEVEL(led->led_cdev.brightness);
|
||||
struct tca6507_chip *tca = led->chip;
|
||||
int c1, c2;
|
||||
int i;
|
||||
struct bank *b;
|
||||
int need_init = 0;
|
||||
|
||||
led->led_cdev.brightness = TO_BRIGHT(level);
|
||||
if (level == 0) {
|
||||
set_select(tca, led->num, TCA6507_LS_LED_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (led->ontime == 0 || led->offtime == 0) {
|
||||
/*
|
||||
* Just set the brightness, choosing first usable bank.
|
||||
* If none perfect, choose best.
|
||||
* Count backwards so we check MASTER bank first
|
||||
* to avoid wasting a timer.
|
||||
*/
|
||||
int best = -1;/* full-on */
|
||||
int diff = 15-level;
|
||||
|
||||
if (level == 15) {
|
||||
set_select(tca, led->num, TCA6507_LS_LED_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = MASTER; i >= BANK0; i--) {
|
||||
int d;
|
||||
if (tca->bank[i].level == level ||
|
||||
tca->bank[i].level_use == 0) {
|
||||
best = i;
|
||||
break;
|
||||
}
|
||||
d = abs(level - tca->bank[i].level);
|
||||
if (d < diff) {
|
||||
diff = d;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
if (best == -1) {
|
||||
/* Best brightness is full-on */
|
||||
set_select(tca, led->num, TCA6507_LS_LED_ON);
|
||||
led->led_cdev.brightness = LED_FULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tca->bank[best].level_use)
|
||||
set_level(tca, best, level);
|
||||
|
||||
tca->bank[best].level_use++;
|
||||
led->bank = best;
|
||||
set_select(tca, led->num, bank_source[best]);
|
||||
led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have on/off time so we need to try to allocate a timing bank.
|
||||
* First check if times are compatible with hardware and give up if
|
||||
* not.
|
||||
*/
|
||||
if (choose_times(led->ontime, &c1, &c2) < 0)
|
||||
return -EINVAL;
|
||||
if (choose_times(led->offtime, &c1, &c2) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = BANK0; i <= BANK1; i++) {
|
||||
if (tca->bank[i].level_use == 0)
|
||||
/* not in use - it is ours! */
|
||||
break;
|
||||
if (tca->bank[i].level != level)
|
||||
/* Incompatible level - skip */
|
||||
/* FIX: if timer matches we maybe should consider
|
||||
* this anyway...
|
||||
*/
|
||||
continue;
|
||||
|
||||
if (tca->bank[i].time_use == 0)
|
||||
/* Timer not in use, and level matches - use it */
|
||||
break;
|
||||
|
||||
if (!(tca->bank[i].on_dflt ||
|
||||
led->on_dflt ||
|
||||
tca->bank[i].ontime == led->ontime))
|
||||
/* on time is incompatible */
|
||||
continue;
|
||||
|
||||
if (!(tca->bank[i].off_dflt ||
|
||||
led->off_dflt ||
|
||||
tca->bank[i].offtime == led->offtime))
|
||||
/* off time is incompatible */
|
||||
continue;
|
||||
|
||||
/* looks like a suitable match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > BANK1)
|
||||
/* Nothing matches - how sad */
|
||||
return -EINVAL;
|
||||
|
||||
b = &tca->bank[i];
|
||||
if (b->level_use == 0)
|
||||
set_level(tca, i, level);
|
||||
b->level_use++;
|
||||
led->bank = i;
|
||||
|
||||
if (b->on_dflt ||
|
||||
!led->on_dflt ||
|
||||
b->time_use == 0) {
|
||||
b->ontime = led->ontime;
|
||||
b->on_dflt = led->on_dflt;
|
||||
need_init = 1;
|
||||
}
|
||||
|
||||
if (b->off_dflt ||
|
||||
!led->off_dflt ||
|
||||
b->time_use == 0) {
|
||||
b->offtime = led->offtime;
|
||||
b->off_dflt = led->off_dflt;
|
||||
need_init = 1;
|
||||
}
|
||||
|
||||
if (need_init)
|
||||
set_times(tca, i);
|
||||
|
||||
led->ontime = b->ontime;
|
||||
led->offtime = b->offtime;
|
||||
|
||||
b->time_use++;
|
||||
led->blink = 1;
|
||||
led->led_cdev.brightness = TO_BRIGHT(b->level);
|
||||
set_select(tca, led->num, blink_source[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int led_assign(struct tca6507_led *led)
|
||||
{
|
||||
struct tca6507_chip *tca = led->chip;
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tca->lock, flags);
|
||||
led_release(led);
|
||||
err = led_prepare(led);
|
||||
if (err) {
|
||||
/*
|
||||
* Can only fail on timer setup. In that case we need to
|
||||
* re-establish as steady level.
|
||||
*/
|
||||
led->ontime = 0;
|
||||
led->offtime = 0;
|
||||
led_prepare(led);
|
||||
}
|
||||
spin_unlock_irqrestore(&tca->lock, flags);
|
||||
|
||||
if (tca->reg_set)
|
||||
schedule_work(&tca->work);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tca6507_brightness_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
|
||||
led_cdev);
|
||||
led->led_cdev.brightness = brightness;
|
||||
led->ontime = 0;
|
||||
led->offtime = 0;
|
||||
led_assign(led);
|
||||
}
|
||||
|
||||
static int tca6507_blink_set(struct led_classdev *led_cdev,
|
||||
unsigned long *delay_on,
|
||||
unsigned long *delay_off)
|
||||
{
|
||||
struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
|
||||
led_cdev);
|
||||
|
||||
if (*delay_on == 0)
|
||||
led->on_dflt = 1;
|
||||
else if (delay_on != &led_cdev->blink_delay_on)
|
||||
led->on_dflt = 0;
|
||||
led->ontime = *delay_on;
|
||||
|
||||
if (*delay_off == 0)
|
||||
led->off_dflt = 1;
|
||||
else if (delay_off != &led_cdev->blink_delay_off)
|
||||
led->off_dflt = 0;
|
||||
led->offtime = *delay_off;
|
||||
|
||||
if (led->ontime == 0)
|
||||
led->ontime = 512;
|
||||
if (led->offtime == 0)
|
||||
led->offtime = 512;
|
||||
|
||||
if (led->led_cdev.brightness == LED_OFF)
|
||||
led->led_cdev.brightness = LED_FULL;
|
||||
if (led_assign(led) < 0) {
|
||||
led->ontime = 0;
|
||||
led->offtime = 0;
|
||||
led->led_cdev.brightness = LED_OFF;
|
||||
return -EINVAL;
|
||||
}
|
||||
*delay_on = led->ontime;
|
||||
*delay_off = led->offtime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
static void tca6507_gpio_set_value(struct gpio_chip *gc,
|
||||
unsigned offset, int val)
|
||||
{
|
||||
struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tca->lock, flags);
|
||||
/*
|
||||
* 'OFF' is floating high, and 'ON' is pulled down, so it has the
|
||||
* inverse sense of 'val'.
|
||||
*/
|
||||
set_select(tca, tca->gpio_map[offset],
|
||||
val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
|
||||
spin_unlock_irqrestore(&tca->lock, flags);
|
||||
if (tca->reg_set)
|
||||
schedule_work(&tca->work);
|
||||
}
|
||||
|
||||
static int tca6507_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned offset, int val)
|
||||
{
|
||||
tca6507_gpio_set_value(gc, offset, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tca6507_probe_gpios(struct i2c_client *client,
|
||||
struct tca6507_chip *tca,
|
||||
struct tca6507_platform_data *pdata)
|
||||
{
|
||||
int err;
|
||||
int i = 0;
|
||||
int gpios = 0;
|
||||
|
||||
for (i = 0; i < NUM_LEDS; i++)
|
||||
if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
|
||||
/* Configure as a gpio */
|
||||
tca->gpio_name[gpios] = pdata->leds.leds[i].name;
|
||||
tca->gpio_map[gpios] = i;
|
||||
gpios++;
|
||||
}
|
||||
|
||||
if (!gpios)
|
||||
return 0;
|
||||
|
||||
tca->gpio.label = "gpio-tca6507";
|
||||
tca->gpio.names = tca->gpio_name;
|
||||
tca->gpio.ngpio = gpios;
|
||||
tca->gpio.base = pdata->gpio_base;
|
||||
tca->gpio.owner = THIS_MODULE;
|
||||
tca->gpio.direction_output = tca6507_gpio_direction_output;
|
||||
tca->gpio.set = tca6507_gpio_set_value;
|
||||
tca->gpio.dev = &client->dev;
|
||||
err = gpiochip_add(&tca->gpio);
|
||||
if (err) {
|
||||
tca->gpio.ngpio = 0;
|
||||
return err;
|
||||
}
|
||||
if (pdata->setup)
|
||||
pdata->setup(tca->gpio.base, tca->gpio.ngpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tca6507_remove_gpio(struct tca6507_chip *tca)
|
||||
{
|
||||
if (tca->gpio.ngpio) {
|
||||
int err = gpiochip_remove(&tca->gpio);
|
||||
dev_err(&tca->client->dev, "%s failed, %d\n",
|
||||
"gpiochip_remove()", err);
|
||||
}
|
||||
}
|
||||
#else /* CONFIG_GPIOLIB */
|
||||
static int tca6507_probe_gpios(struct i2c_client *client,
|
||||
struct tca6507_chip *tca,
|
||||
struct tca6507_platform_data *pdata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static void tca6507_remove_gpio(struct tca6507_chip *tca)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
static int __devinit tca6507_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tca6507_chip *tca;
|
||||
struct i2c_adapter *adapter;
|
||||
struct tca6507_platform_data *pdata;
|
||||
int err;
|
||||
int i = 0;
|
||||
|
||||
adapter = to_i2c_adapter(client->dev.parent);
|
||||
pdata = client->dev.platform_data;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
|
||||
return -EIO;
|
||||
|
||||
if (!pdata || pdata->leds.num_leds != NUM_LEDS) {
|
||||
dev_err(&client->dev, "Need %d entries in platform-data list\n",
|
||||
NUM_LEDS);
|
||||
return -ENODEV;
|
||||
}
|
||||
err = -ENOMEM;
|
||||
tca = kzalloc(sizeof(*tca), GFP_KERNEL);
|
||||
if (!tca)
|
||||
goto exit;
|
||||
|
||||
tca->client = client;
|
||||
INIT_WORK(&tca->work, tca6507_work);
|
||||
spin_lock_init(&tca->lock);
|
||||
i2c_set_clientdata(client, tca);
|
||||
|
||||
for (i = 0; i < NUM_LEDS; i++) {
|
||||
struct tca6507_led *l = tca->leds + i;
|
||||
|
||||
l->chip = tca;
|
||||
l->num = i;
|
||||
if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
|
||||
l->led_cdev.name = pdata->leds.leds[i].name;
|
||||
l->led_cdev.default_trigger
|
||||
= pdata->leds.leds[i].default_trigger;
|
||||
l->led_cdev.brightness_set = tca6507_brightness_set;
|
||||
l->led_cdev.blink_set = tca6507_blink_set;
|
||||
l->bank = -1;
|
||||
err = led_classdev_register(&client->dev,
|
||||
&l->led_cdev);
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
err = tca6507_probe_gpios(client, tca, pdata);
|
||||
if (err)
|
||||
goto exit;
|
||||
/* set all registers to known state - zero */
|
||||
tca->reg_set = 0x7f;
|
||||
schedule_work(&tca->work);
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
while (i--)
|
||||
if (tca->leds[i].led_cdev.name)
|
||||
led_classdev_unregister(&tca->leds[i].led_cdev);
|
||||
cancel_work_sync(&tca->work);
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(tca);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit tca6507_remove(struct i2c_client *client)
|
||||
{
|
||||
int i;
|
||||
struct tca6507_chip *tca = i2c_get_clientdata(client);
|
||||
struct tca6507_led *tca_leds = tca->leds;
|
||||
|
||||
for (i = 0; i < NUM_LEDS; i++) {
|
||||
if (tca_leds[i].led_cdev.name)
|
||||
led_classdev_unregister(&tca_leds[i].led_cdev);
|
||||
}
|
||||
tca6507_remove_gpio(tca);
|
||||
cancel_work_sync(&tca->work);
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(tca);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver tca6507_driver = {
|
||||
.driver = {
|
||||
.name = "leds-tca6507",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tca6507_probe,
|
||||
.remove = __devexit_p(tca6507_remove),
|
||||
.id_table = tca6507_id,
|
||||
};
|
||||
|
||||
static int __init tca6507_leds_init(void)
|
||||
{
|
||||
return i2c_add_driver(&tca6507_driver);
|
||||
}
|
||||
|
||||
static void __exit tca6507_leds_exit(void)
|
||||
{
|
||||
i2c_del_driver(&tca6507_driver);
|
||||
}
|
||||
|
||||
module_init(tca6507_leds_init);
|
||||
module_exit(tca6507_leds_exit);
|
||||
|
||||
MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
|
||||
MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -237,7 +237,8 @@ static int wm831x_status_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL);
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
|
||||
GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&pdev->dev, drvdata);
|
||||
|
@ -300,7 +301,6 @@ static int wm831x_status_probe(struct platform_device *pdev)
|
|||
|
||||
err_led:
|
||||
led_classdev_unregister(&drvdata->cdev);
|
||||
kfree(drvdata);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
@ -311,7 +311,6 @@ static int wm831x_status_remove(struct platform_device *pdev)
|
|||
|
||||
device_remove_file(drvdata->cdev.dev, &dev_attr_src);
|
||||
led_classdev_unregister(&drvdata->cdev);
|
||||
kfree(drvdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -325,17 +324,7 @@ static struct platform_driver wm831x_status_driver = {
|
|||
.remove = wm831x_status_remove,
|
||||
};
|
||||
|
||||
static int __devinit wm831x_status_init(void)
|
||||
{
|
||||
return platform_driver_register(&wm831x_status_driver);
|
||||
}
|
||||
module_init(wm831x_status_init);
|
||||
|
||||
static void wm831x_status_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm831x_status_driver);
|
||||
}
|
||||
module_exit(wm831x_status_exit);
|
||||
module_platform_driver(wm831x_status_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("WM831x status LED driver");
|
||||
|
|
|
@ -227,7 +227,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
|
|||
goto err_isink;
|
||||
}
|
||||
|
||||
led = kzalloc(sizeof(*led), GFP_KERNEL);
|
||||
led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
|
||||
if (led == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_dcdc;
|
||||
|
@ -259,12 +259,10 @@ static int wm8350_led_probe(struct platform_device *pdev)
|
|||
|
||||
ret = led_classdev_register(&pdev->dev, &led->cdev);
|
||||
if (ret < 0)
|
||||
goto err_led;
|
||||
goto err_dcdc;
|
||||
|
||||
return 0;
|
||||
|
||||
err_led:
|
||||
kfree(led);
|
||||
err_dcdc:
|
||||
regulator_put(dcdc);
|
||||
err_isink:
|
||||
|
@ -281,7 +279,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
|
|||
wm8350_led_disable(led);
|
||||
regulator_put(led->dcdc);
|
||||
regulator_put(led->isink);
|
||||
kfree(led);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -295,17 +292,7 @@ static struct platform_driver wm8350_led_driver = {
|
|||
.shutdown = wm8350_led_shutdown,
|
||||
};
|
||||
|
||||
static int __devinit wm8350_led_init(void)
|
||||
{
|
||||
return platform_driver_register(&wm8350_led_driver);
|
||||
}
|
||||
module_init(wm8350_led_init);
|
||||
|
||||
static void wm8350_led_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm8350_led_driver);
|
||||
}
|
||||
module_exit(wm8350_led_exit);
|
||||
module_platform_driver(wm8350_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Brown");
|
||||
MODULE_DESCRIPTION("WM8350 LED driver");
|
||||
|
|
|
@ -228,11 +228,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|||
alarm->time.tm_hour = now.tm_hour;
|
||||
|
||||
/* For simplicity, only support date rollover for now */
|
||||
if (alarm->time.tm_mday == -1) {
|
||||
if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) {
|
||||
alarm->time.tm_mday = now.tm_mday;
|
||||
missing = day;
|
||||
}
|
||||
if (alarm->time.tm_mon == -1) {
|
||||
if ((unsigned)alarm->time.tm_mon >= 12) {
|
||||
alarm->time.tm_mon = now.tm_mon;
|
||||
if (missing == none)
|
||||
missing = month;
|
||||
|
|
|
@ -410,17 +410,7 @@ static struct platform_driver pm860x_rtc_driver = {
|
|||
.remove = __devexit_p(pm860x_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init pm860x_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&pm860x_rtc_driver);
|
||||
}
|
||||
module_init(pm860x_rtc_init);
|
||||
|
||||
static void __exit pm860x_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pm860x_rtc_driver);
|
||||
}
|
||||
module_exit(pm860x_rtc_exit);
|
||||
module_platform_driver(pm860x_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Marvell 88PM860x RTC driver");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
|
|
|
@ -90,7 +90,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
|
||||
/* Early AB8500 chips will not clear the rtc read request bit */
|
||||
if (abx500_get_chip_id(dev) == 0) {
|
||||
msleep(1);
|
||||
usleep_range(1000, 1000);
|
||||
} else {
|
||||
/* Wait for some cycles after enabling the rtc read in ab8500 */
|
||||
while (time_before(jiffies, timeout)) {
|
||||
|
@ -102,7 +102,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
if (!(value & RTC_READ_REQUEST))
|
||||
break;
|
||||
|
||||
msleep(1);
|
||||
usleep_range(1000, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,109 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
|||
return ab8500_rtc_irq_enable(dev, alarm->enabled);
|
||||
}
|
||||
|
||||
|
||||
static int ab8500_rtc_set_calibration(struct device *dev, int calibration)
|
||||
{
|
||||
int retval;
|
||||
u8 rtccal = 0;
|
||||
|
||||
/*
|
||||
* Check that the calibration value (which is in units of 0.5
|
||||
* parts-per-million) is in the AB8500's range for RtcCalibration
|
||||
* register. -128 (0x80) is not permitted because the AB8500 uses
|
||||
* a sign-bit rather than two's complement, so 0x80 is just another
|
||||
* representation of zero.
|
||||
*/
|
||||
if ((calibration < -127) || (calibration > 127)) {
|
||||
dev_err(dev, "RtcCalibration value outside permitted range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
|
||||
* so need to convert to this sort of representation before writing
|
||||
* into RtcCalibration register...
|
||||
*/
|
||||
if (calibration >= 0)
|
||||
rtccal = 0x7F & calibration;
|
||||
else
|
||||
rtccal = ~(calibration - 1) | 0x80;
|
||||
|
||||
retval = abx500_set_register_interruptible(dev, AB8500_RTC,
|
||||
AB8500_RTC_CALIB_REG, rtccal);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int ab8500_rtc_get_calibration(struct device *dev, int *calibration)
|
||||
{
|
||||
int retval;
|
||||
u8 rtccal = 0;
|
||||
|
||||
retval = abx500_get_register_interruptible(dev, AB8500_RTC,
|
||||
AB8500_RTC_CALIB_REG, &rtccal);
|
||||
if (retval >= 0) {
|
||||
/*
|
||||
* The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
|
||||
* so need to convert value from RtcCalibration register into
|
||||
* a two's complement signed value...
|
||||
*/
|
||||
if (rtccal & 0x80)
|
||||
*calibration = 0 - (rtccal & 0x7F);
|
||||
else
|
||||
*calibration = 0x7F & rtccal;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t ab8500_sysfs_store_rtc_calibration(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int retval;
|
||||
int calibration = 0;
|
||||
|
||||
if (sscanf(buf, " %i ", &calibration) != 1) {
|
||||
dev_err(dev, "Failed to store RTC calibration attribute\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
retval = ab8500_rtc_set_calibration(dev, calibration);
|
||||
|
||||
return retval ? retval : count;
|
||||
}
|
||||
|
||||
static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int retval = 0;
|
||||
int calibration = 0;
|
||||
|
||||
retval = ab8500_rtc_get_calibration(dev, &calibration);
|
||||
if (retval < 0) {
|
||||
dev_err(dev, "Failed to read RTC calibration attribute\n");
|
||||
sprintf(buf, "0\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%d\n", calibration);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR,
|
||||
ab8500_sysfs_show_rtc_calibration,
|
||||
ab8500_sysfs_store_rtc_calibration);
|
||||
|
||||
static int ab8500_sysfs_rtc_register(struct device *dev)
|
||||
{
|
||||
return device_create_file(dev, &dev_attr_rtc_calibration);
|
||||
}
|
||||
|
||||
static void ab8500_sysfs_rtc_unregister(struct device *dev)
|
||||
{
|
||||
device_remove_file(dev, &dev_attr_rtc_calibration);
|
||||
}
|
||||
|
||||
static irqreturn_t rtc_alarm_handler(int irq, void *data)
|
||||
{
|
||||
struct rtc_device *rtc = data;
|
||||
|
@ -295,7 +398,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
|
||||
/* Wait for reset by the PorRtc */
|
||||
msleep(1);
|
||||
usleep_range(1000, 5000);
|
||||
|
||||
err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC,
|
||||
AB8500_RTC_STAT_REG, &rtc_ctrl);
|
||||
|
@ -308,6 +411,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
|
||||
rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops,
|
||||
THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
|
@ -316,8 +421,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0,
|
||||
"ab8500-rtc", rtc);
|
||||
err = request_threaded_irq(irq, NULL, rtc_alarm_handler,
|
||||
IRQF_NO_SUSPEND, "ab8500-rtc", rtc);
|
||||
if (err < 0) {
|
||||
rtc_device_unregister(rtc);
|
||||
return err;
|
||||
|
@ -325,6 +430,13 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
|
||||
|
||||
err = ab8500_sysfs_rtc_register(&pdev->dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "sysfs RTC failed to register\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -333,6 +445,8 @@ static int __devexit ab8500_rtc_remove(struct platform_device *pdev)
|
|||
struct rtc_device *rtc = platform_get_drvdata(pdev);
|
||||
int irq = platform_get_irq_byname(pdev, "ALARM");
|
||||
|
||||
ab8500_sysfs_rtc_unregister(&pdev->dev);
|
||||
|
||||
free_irq(irq, rtc);
|
||||
rtc_device_unregister(rtc);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
@ -349,18 +463,8 @@ static struct platform_driver ab8500_rtc_driver = {
|
|||
.remove = __devexit_p(ab8500_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init ab8500_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&ab8500_rtc_driver);
|
||||
}
|
||||
module_platform_driver(ab8500_rtc_driver);
|
||||
|
||||
static void __exit ab8500_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ab8500_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(ab8500_rtc_init);
|
||||
module_exit(ab8500_rtc_exit);
|
||||
MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>");
|
||||
MODULE_DESCRIPTION("AB8500 RTC Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -456,18 +456,7 @@ static struct platform_driver bfin_rtc_driver = {
|
|||
.resume = bfin_rtc_resume,
|
||||
};
|
||||
|
||||
static int __init bfin_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&bfin_rtc_driver);
|
||||
}
|
||||
|
||||
static void __exit bfin_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&bfin_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(bfin_rtc_init);
|
||||
module_exit(bfin_rtc_exit);
|
||||
module_platform_driver(bfin_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver");
|
||||
MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
|
||||
|
|
|
@ -218,15 +218,4 @@ static struct platform_driver bq4802_driver = {
|
|||
.remove = __devexit_p(bq4802_remove),
|
||||
};
|
||||
|
||||
static int __init bq4802_init(void)
|
||||
{
|
||||
return platform_driver_register(&bq4802_driver);
|
||||
}
|
||||
|
||||
static void __exit bq4802_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&bq4802_driver);
|
||||
}
|
||||
|
||||
module_init(bq4802_init);
|
||||
module_exit(bq4802_exit);
|
||||
module_platform_driver(bq4802_driver);
|
||||
|
|
|
@ -164,7 +164,7 @@ static inline unsigned char cmos_read_bank2(unsigned char addr)
|
|||
static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
|
||||
{
|
||||
outb(addr, RTC_PORT(2));
|
||||
outb(val, RTC_PORT(2));
|
||||
outb(val, RTC_PORT(3));
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
@ -161,16 +161,6 @@ static struct platform_driver rtc_dm355evm_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init dm355evm_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&rtc_dm355evm_driver);
|
||||
}
|
||||
module_init(dm355evm_rtc_init);
|
||||
|
||||
static void __exit dm355evm_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rtc_dm355evm_driver);
|
||||
}
|
||||
module_exit(dm355evm_rtc_exit);
|
||||
module_platform_driver(rtc_dm355evm_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -396,21 +396,10 @@ static struct platform_driver ds1286_platform_driver = {
|
|||
.remove = __devexit_p(ds1286_remove),
|
||||
};
|
||||
|
||||
static int __init ds1286_init(void)
|
||||
{
|
||||
return platform_driver_register(&ds1286_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit ds1286_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ds1286_platform_driver);
|
||||
}
|
||||
module_platform_driver(ds1286_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
|
||||
MODULE_DESCRIPTION("DS1286 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_ALIAS("platform:rtc-ds1286");
|
||||
|
||||
module_init(ds1286_init);
|
||||
module_exit(ds1286_exit);
|
||||
|
|
|
@ -580,20 +580,7 @@ static struct platform_driver ds1511_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init
|
||||
ds1511_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&ds1511_rtc_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
ds1511_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ds1511_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(ds1511_rtc_init);
|
||||
module_exit(ds1511_rtc_exit);
|
||||
module_platform_driver(ds1511_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>");
|
||||
MODULE_DESCRIPTION("Dallas DS1511 RTC driver");
|
||||
|
|
|
@ -361,18 +361,7 @@ static struct platform_driver ds1553_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static __init int ds1553_init(void)
|
||||
{
|
||||
return platform_driver_register(&ds1553_rtc_driver);
|
||||
}
|
||||
|
||||
static __exit void ds1553_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ds1553_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(ds1553_init);
|
||||
module_exit(ds1553_exit);
|
||||
module_platform_driver(ds1553_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
|
||||
MODULE_DESCRIPTION("Dallas DS1553 RTC driver");
|
||||
|
|
|
@ -240,18 +240,7 @@ static struct platform_driver ds1742_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static __init int ds1742_init(void)
|
||||
{
|
||||
return platform_driver_register(&ds1742_rtc_driver);
|
||||
}
|
||||
|
||||
static __exit void ds1742_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ds1742_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(ds1742_init);
|
||||
module_exit(ds1742_exit);
|
||||
module_platform_driver(ds1742_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
|
||||
MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
|
||||
|
|
|
@ -345,7 +345,7 @@ static const struct dev_pm_ops jz4740_pm_ops = {
|
|||
#define JZ4740_RTC_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
struct platform_driver jz4740_rtc_driver = {
|
||||
static struct platform_driver jz4740_rtc_driver = {
|
||||
.probe = jz4740_rtc_probe,
|
||||
.remove = __devexit_p(jz4740_rtc_remove),
|
||||
.driver = {
|
||||
|
@ -355,17 +355,7 @@ struct platform_driver jz4740_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init jz4740_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&jz4740_rtc_driver);
|
||||
}
|
||||
module_init(jz4740_rtc_init);
|
||||
|
||||
static void __exit jz4740_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&jz4740_rtc_driver);
|
||||
}
|
||||
module_exit(jz4740_rtc_exit);
|
||||
module_platform_driver(jz4740_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -396,17 +396,7 @@ static struct platform_driver lpc32xx_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init lpc32xx_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&lpc32xx_rtc_driver);
|
||||
}
|
||||
module_init(lpc32xx_rtc_init);
|
||||
|
||||
static void __exit lpc32xx_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lpc32xx_rtc_driver);
|
||||
}
|
||||
module_exit(lpc32xx_rtc_exit);
|
||||
module_platform_driver(lpc32xx_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com");
|
||||
MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC");
|
||||
|
|
|
@ -200,7 +200,6 @@ static int __devexit m41t93_remove(struct spi_device *spi)
|
|||
static struct spi_driver m41t93_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-m41t93",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = m41t93_probe,
|
||||
|
|
|
@ -147,7 +147,6 @@ static int __devexit m41t94_remove(struct spi_device *spi)
|
|||
static struct spi_driver m41t94_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-m41t94",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = m41t94_probe,
|
||||
|
|
|
@ -216,21 +216,10 @@ static struct platform_driver m48t35_platform_driver = {
|
|||
.remove = __devexit_p(m48t35_remove),
|
||||
};
|
||||
|
||||
static int __init m48t35_init(void)
|
||||
{
|
||||
return platform_driver_register(&m48t35_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit m48t35_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&m48t35_platform_driver);
|
||||
}
|
||||
module_platform_driver(m48t35_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
|
||||
MODULE_DESCRIPTION("M48T35 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_ALIAS("platform:rtc-m48t35");
|
||||
|
||||
module_init(m48t35_init);
|
||||
module_exit(m48t35_exit);
|
||||
|
|
|
@ -530,18 +530,7 @@ static struct platform_driver m48t59_rtc_driver = {
|
|||
.remove = __devexit_p(m48t59_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init m48t59_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&m48t59_rtc_driver);
|
||||
}
|
||||
|
||||
static void __exit m48t59_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&m48t59_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(m48t59_rtc_init);
|
||||
module_exit(m48t59_rtc_exit);
|
||||
module_platform_driver(m48t59_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
|
||||
MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
|
||||
|
|
|
@ -185,21 +185,10 @@ static struct platform_driver m48t86_rtc_platform_driver = {
|
|||
.remove = __devexit_p(m48t86_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init m48t86_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&m48t86_rtc_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit m48t86_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&m48t86_rtc_platform_driver);
|
||||
}
|
||||
module_platform_driver(m48t86_rtc_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
||||
MODULE_DESCRIPTION("M48T86 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_ALIAS("platform:rtc-m48t86");
|
||||
|
||||
module_init(m48t86_rtc_init);
|
||||
module_exit(m48t86_rtc_exit);
|
||||
|
|
|
@ -154,7 +154,6 @@ static int __devexit max6902_remove(struct spi_device *spi)
|
|||
static struct spi_driver max6902_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-max6902",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max6902_probe,
|
||||
|
|
|
@ -299,17 +299,7 @@ static struct platform_driver max8925_rtc_driver = {
|
|||
.remove = __devexit_p(max8925_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init max8925_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&max8925_rtc_driver);
|
||||
}
|
||||
module_init(max8925_rtc_init);
|
||||
|
||||
static void __exit max8925_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&max8925_rtc_driver);
|
||||
}
|
||||
module_exit(max8925_rtc_exit);
|
||||
module_platform_driver(max8925_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
|
|
|
@ -327,17 +327,7 @@ static struct platform_driver max8998_rtc_driver = {
|
|||
.id_table = max8998_rtc_id,
|
||||
};
|
||||
|
||||
static int __init max8998_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&max8998_rtc_driver);
|
||||
}
|
||||
module_init(max8998_rtc_init);
|
||||
|
||||
static void __exit max8998_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&max8998_rtc_driver);
|
||||
}
|
||||
module_exit(max8998_rtc_exit);
|
||||
module_platform_driver(max8998_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
|
||||
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
|
||||
|
|
|
@ -399,7 +399,7 @@ static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct platform_device_id mc13xxx_rtc_idtable[] = {
|
||||
static const struct platform_device_id mc13xxx_rtc_idtable[] = {
|
||||
{
|
||||
.name = "mc13783-rtc",
|
||||
}, {
|
||||
|
|
|
@ -418,17 +418,7 @@ static struct platform_driver mpc5121_rtc_driver = {
|
|||
.remove = __devexit_p(mpc5121_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init mpc5121_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&mpc5121_rtc_driver);
|
||||
}
|
||||
module_init(mpc5121_rtc_init);
|
||||
|
||||
static void __exit mpc5121_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mpc5121_rtc_driver);
|
||||
}
|
||||
module_exit(mpc5121_rtc_exit);
|
||||
module_platform_driver(mpc5121_rtc_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>");
|
||||
|
|
|
@ -537,18 +537,7 @@ static struct platform_driver vrtc_mrst_platform_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static int __init vrtc_mrst_init(void)
|
||||
{
|
||||
return platform_driver_register(&vrtc_mrst_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit vrtc_mrst_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vrtc_mrst_platform_driver);
|
||||
}
|
||||
|
||||
module_init(vrtc_mrst_init);
|
||||
module_exit(vrtc_mrst_exit);
|
||||
module_platform_driver(vrtc_mrst_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Jacob Pan; Feng Tang");
|
||||
MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");
|
||||
|
|
|
@ -155,7 +155,6 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
|
|||
{
|
||||
struct rtc_time alarm_tm, now_tm;
|
||||
unsigned long now, time;
|
||||
int ret;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
||||
void __iomem *ioaddr = pdata->ioaddr;
|
||||
|
@ -168,21 +167,33 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
|
|||
alarm_tm.tm_hour = alrm->tm_hour;
|
||||
alarm_tm.tm_min = alrm->tm_min;
|
||||
alarm_tm.tm_sec = alrm->tm_sec;
|
||||
rtc_tm_to_time(&now_tm, &now);
|
||||
rtc_tm_to_time(&alarm_tm, &time);
|
||||
|
||||
if (time < now) {
|
||||
time += 60 * 60 * 24;
|
||||
rtc_time_to_tm(time, &alarm_tm);
|
||||
}
|
||||
|
||||
ret = rtc_tm_to_time(&alarm_tm, &time);
|
||||
|
||||
/* clear all the interrupt status bits */
|
||||
writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR);
|
||||
set_alarm_or_time(dev, MXC_RTC_ALARM, time);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
|
||||
unsigned int enabled)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
||||
void __iomem *ioaddr = pdata->ioaddr;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irq(&pdata->rtc->irq_lock);
|
||||
reg = readw(ioaddr + RTC_RTCIENR);
|
||||
|
||||
if (enabled)
|
||||
reg |= bit;
|
||||
else
|
||||
reg &= ~bit;
|
||||
|
||||
writew(reg, ioaddr + RTC_RTCIENR);
|
||||
spin_unlock_irq(&pdata->rtc->irq_lock);
|
||||
}
|
||||
|
||||
/* This function is the RTC interrupt service routine. */
|
||||
|
@ -199,13 +210,12 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
|
|||
/* clear interrupt sources */
|
||||
writew(status, ioaddr + RTC_RTCISR);
|
||||
|
||||
/* clear alarm interrupt if it has occurred */
|
||||
if (status & RTC_ALM_BIT)
|
||||
status &= ~RTC_ALM_BIT;
|
||||
|
||||
/* update irq data & counter */
|
||||
if (status & RTC_ALM_BIT)
|
||||
if (status & RTC_ALM_BIT) {
|
||||
events |= (RTC_AF | RTC_IRQF);
|
||||
/* RTC alarm should be one-shot */
|
||||
mxc_rtc_irq_enable(&pdev->dev, RTC_ALM_BIT, 0);
|
||||
}
|
||||
|
||||
if (status & RTC_1HZ_BIT)
|
||||
events |= (RTC_UF | RTC_IRQF);
|
||||
|
@ -213,9 +223,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
|
|||
if (status & PIT_ALL_ON)
|
||||
events |= (RTC_PF | RTC_IRQF);
|
||||
|
||||
if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm))
|
||||
rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm);
|
||||
|
||||
rtc_update_irq(pdata->rtc, 1, events);
|
||||
spin_unlock_irq(&pdata->rtc->irq_lock);
|
||||
|
||||
|
@ -242,26 +249,6 @@ static void mxc_rtc_release(struct device *dev)
|
|||
spin_unlock_irq(&pdata->rtc->irq_lock);
|
||||
}
|
||||
|
||||
static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
|
||||
unsigned int enabled)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
||||
void __iomem *ioaddr = pdata->ioaddr;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irq(&pdata->rtc->irq_lock);
|
||||
reg = readw(ioaddr + RTC_RTCIENR);
|
||||
|
||||
if (enabled)
|
||||
reg |= bit;
|
||||
else
|
||||
reg &= ~bit;
|
||||
|
||||
writew(reg, ioaddr + RTC_RTCIENR);
|
||||
spin_unlock_irq(&pdata->rtc->irq_lock);
|
||||
}
|
||||
|
||||
static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled);
|
||||
|
@ -290,6 +277,17 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
*/
|
||||
static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
|
||||
{
|
||||
/*
|
||||
* TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
|
||||
*/
|
||||
if (cpu_is_mx1()) {
|
||||
struct rtc_time tm;
|
||||
|
||||
rtc_time_to_tm(time, &tm);
|
||||
tm.tm_year = 70;
|
||||
rtc_tm_to_time(&tm, &time);
|
||||
}
|
||||
|
||||
/* Avoid roll-over from reading the different registers */
|
||||
do {
|
||||
set_alarm_or_time(dev, MXC_RTC_TIME, time);
|
||||
|
@ -324,21 +322,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
if (rtc_valid_tm(&alrm->time)) {
|
||||
if (alrm->time.tm_sec > 59 ||
|
||||
alrm->time.tm_hour > 23 ||
|
||||
alrm->time.tm_min > 59)
|
||||
return -EINVAL;
|
||||
|
||||
ret = rtc_update_alarm(dev, &alrm->time);
|
||||
} else {
|
||||
ret = rtc_valid_tm(&alrm->time);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtc_update_alarm(dev, &alrm->time);
|
||||
}
|
||||
|
||||
ret = rtc_update_alarm(dev, &alrm->time);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -424,6 +408,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
|
|||
pdata->irq = -1;
|
||||
}
|
||||
|
||||
if (pdata->irq >=0)
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
|
||||
THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
|
@ -459,9 +446,39 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mxc_rtc_suspend(struct device *dev)
|
||||
{
|
||||
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
enable_irq_wake(pdata->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_rtc_resume(struct device *dev)
|
||||
{
|
||||
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
disable_irq_wake(pdata->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops mxc_rtc_pm_ops = {
|
||||
.suspend = mxc_rtc_suspend,
|
||||
.resume = mxc_rtc_resume,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver mxc_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "mxc_rtc",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &mxc_rtc_pm_ops,
|
||||
#endif
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.remove = __exit_p(mxc_rtc_remove),
|
||||
|
|
|
@ -340,7 +340,6 @@ static int __devexit pcf2123_remove(struct spi_device *spi)
|
|||
static struct spi_driver pcf2123_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-pcf2123",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = pcf2123_probe,
|
||||
|
|
|
@ -294,17 +294,7 @@ static struct platform_driver pcf50633_rtc_driver = {
|
|||
.remove = __devexit_p(pcf50633_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init pcf50633_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&pcf50633_rtc_driver);
|
||||
}
|
||||
module_init(pcf50633_rtc_init);
|
||||
|
||||
static void __exit pcf50633_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pcf50633_rtc_driver);
|
||||
}
|
||||
module_exit(pcf50633_rtc_exit);
|
||||
module_platform_driver(pcf50633_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("PCF50633 RTC driver");
|
||||
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
|
||||
|
|
|
@ -532,17 +532,7 @@ static struct platform_driver pm8xxx_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init pm8xxx_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&pm8xxx_rtc_driver);
|
||||
}
|
||||
module_init(pm8xxx_rtc_init);
|
||||
|
||||
static void __exit pm8xxx_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pm8xxx_rtc_driver);
|
||||
}
|
||||
module_exit(pm8xxx_rtc_exit);
|
||||
module_platform_driver(pm8xxx_rtc_driver);
|
||||
|
||||
MODULE_ALIAS("platform:rtc-pm8xxx");
|
||||
MODULE_DESCRIPTION("PMIC8xxx RTC driver");
|
||||
|
|
|
@ -229,7 +229,6 @@ static int __devexit rs5c348_remove(struct spi_device *spi)
|
|||
static struct spi_driver rs5c348_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rs5c348",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rs5c348_probe,
|
||||
|
|
|
@ -673,21 +673,7 @@ static struct platform_driver s3c_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";
|
||||
|
||||
static int __init s3c_rtc_init(void)
|
||||
{
|
||||
printk(banner);
|
||||
return platform_driver_register(&s3c_rtc_driver);
|
||||
}
|
||||
|
||||
static void __exit s3c_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(s3c_rtc_init);
|
||||
module_exit(s3c_rtc_exit);
|
||||
module_platform_driver(s3c_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Samsung S3C RTC Driver");
|
||||
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||
|
|
|
@ -435,18 +435,7 @@ static struct platform_driver sa1100_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init sa1100_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&sa1100_rtc_driver);
|
||||
}
|
||||
|
||||
static void __exit sa1100_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sa1100_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(sa1100_rtc_init);
|
||||
module_exit(sa1100_rtc_exit);
|
||||
module_platform_driver(sa1100_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
|
||||
MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
|
||||
|
|
|
@ -516,17 +516,7 @@ static struct platform_driver spear_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&spear_rtc_driver);
|
||||
}
|
||||
module_init(rtc_init);
|
||||
|
||||
static void __exit rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&spear_rtc_driver);
|
||||
}
|
||||
module_exit(rtc_exit);
|
||||
module_platform_driver(spear_rtc_driver);
|
||||
|
||||
MODULE_ALIAS("platform:rtc-spear");
|
||||
MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
|
||||
|
|
|
@ -370,18 +370,7 @@ static struct platform_driver stk17ta8_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static __init int stk17ta8_init(void)
|
||||
{
|
||||
return platform_driver_register(&stk17ta8_rtc_driver);
|
||||
}
|
||||
|
||||
static __exit void stk17ta8_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&stk17ta8_rtc_driver);
|
||||
}
|
||||
|
||||
module_init(stk17ta8_init);
|
||||
module_exit(stk17ta8_exit);
|
||||
module_platform_driver(stk17ta8_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>");
|
||||
MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver");
|
||||
|
|
|
@ -276,18 +276,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init stmp3xxx_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&stmp3xxx_rtcdrv);
|
||||
}
|
||||
|
||||
static void __exit stmp3xxx_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&stmp3xxx_rtcdrv);
|
||||
}
|
||||
|
||||
module_init(stmp3xxx_rtc_init);
|
||||
module_exit(stmp3xxx_rtc_exit);
|
||||
module_platform_driver(stmp3xxx_rtcdrv);
|
||||
|
||||
MODULE_DESCRIPTION("STMP3xxx RTC Driver");
|
||||
MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
|
||||
|
|
|
@ -550,6 +550,11 @@ static int twl_rtc_resume(struct platform_device *pdev)
|
|||
#define twl_rtc_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id twl_rtc_of_match[] = {
|
||||
{.compatible = "ti,twl4030-rtc", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, twl_rtc_of_match);
|
||||
MODULE_ALIAS("platform:twl_rtc");
|
||||
|
||||
static struct platform_driver twl4030rtc_driver = {
|
||||
|
@ -559,8 +564,9 @@ static struct platform_driver twl4030rtc_driver = {
|
|||
.suspend = twl_rtc_suspend,
|
||||
.resume = twl_rtc_resume,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "twl_rtc",
|
||||
.owner = THIS_MODULE,
|
||||
.name = "twl_rtc",
|
||||
.of_match_table = twl_rtc_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -393,18 +393,7 @@ static struct platform_driver rtc_device_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static __init int v3020_init(void)
|
||||
{
|
||||
return platform_driver_register(&rtc_device_driver);
|
||||
}
|
||||
|
||||
static __exit void v3020_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rtc_device_driver);
|
||||
}
|
||||
|
||||
module_init(v3020_init);
|
||||
module_exit(v3020_exit);
|
||||
module_platform_driver(rtc_device_driver);
|
||||
|
||||
MODULE_DESCRIPTION("V3020 RTC");
|
||||
MODULE_AUTHOR("Raphael Assenat");
|
||||
|
|
|
@ -405,15 +405,4 @@ static struct platform_driver rtc_platform_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init vr41xx_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&rtc_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit vr41xx_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rtc_platform_driver);
|
||||
}
|
||||
|
||||
module_init(vr41xx_rtc_init);
|
||||
module_exit(vr41xx_rtc_exit);
|
||||
module_platform_driver(rtc_platform_driver);
|
||||
|
|
|
@ -311,17 +311,7 @@ static struct platform_driver vt8500_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init vt8500_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&vt8500_rtc_driver);
|
||||
}
|
||||
module_init(vt8500_rtc_init);
|
||||
|
||||
static void __exit vt8500_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vt8500_rtc_driver);
|
||||
}
|
||||
module_exit(vt8500_rtc_exit);
|
||||
module_platform_driver(vt8500_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
|
||||
MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)");
|
||||
|
|
|
@ -324,15 +324,6 @@ static irqreturn_t wm831x_alm_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t wm831x_per_irq(int irq, void *data)
|
||||
{
|
||||
struct wm831x_rtc *wm831x_rtc = data;
|
||||
|
||||
rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops wm831x_rtc_ops = {
|
||||
.read_time = wm831x_rtc_readtime,
|
||||
.set_mmss = wm831x_rtc_set_mmss,
|
||||
|
@ -405,11 +396,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_rtc *wm831x_rtc;
|
||||
int per_irq = platform_get_irq_byname(pdev, "PER");
|
||||
int alm_irq = platform_get_irq_byname(pdev, "ALM");
|
||||
int ret = 0;
|
||||
|
||||
wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL);
|
||||
wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL);
|
||||
if (wm831x_rtc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -433,14 +423,6 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq,
|
||||
IRQF_TRIGGER_RISING, "RTC period",
|
||||
wm831x_rtc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n",
|
||||
per_irq, ret);
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq,
|
||||
IRQF_TRIGGER_RISING, "RTC alarm",
|
||||
wm831x_rtc);
|
||||
|
@ -452,20 +434,16 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
kfree(wm831x_rtc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit wm831x_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev);
|
||||
int per_irq = platform_get_irq_byname(pdev, "PER");
|
||||
int alm_irq = platform_get_irq_byname(pdev, "ALM");
|
||||
|
||||
free_irq(alm_irq, wm831x_rtc);
|
||||
free_irq(per_irq, wm831x_rtc);
|
||||
rtc_device_unregister(wm831x_rtc->rtc);
|
||||
kfree(wm831x_rtc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -490,17 +468,7 @@ static struct platform_driver wm831x_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init wm831x_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&wm831x_rtc_driver);
|
||||
}
|
||||
module_init(wm831x_rtc_init);
|
||||
|
||||
static void __exit wm831x_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm831x_rtc_driver);
|
||||
}
|
||||
module_exit(wm831x_rtc_exit);
|
||||
module_platform_driver(wm831x_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs");
|
||||
|
|
|
@ -486,17 +486,7 @@ static struct platform_driver wm8350_rtc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init wm8350_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&wm8350_rtc_driver);
|
||||
}
|
||||
module_init(wm8350_rtc_init);
|
||||
|
||||
static void __exit wm8350_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm8350_rtc_driver);
|
||||
}
|
||||
module_exit(wm8350_rtc_exit);
|
||||
module_platform_driver(wm8350_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("RTC driver for the WM8350");
|
||||
|
|
|
@ -270,17 +270,7 @@ static struct platform_driver pm860x_backlight_driver = {
|
|||
.remove = pm860x_backlight_remove,
|
||||
};
|
||||
|
||||
static int __init pm860x_backlight_init(void)
|
||||
{
|
||||
return platform_driver_register(&pm860x_backlight_driver);
|
||||
}
|
||||
module_init(pm860x_backlight_init);
|
||||
|
||||
static void __exit pm860x_backlight_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pm860x_backlight_driver);
|
||||
}
|
||||
module_exit(pm860x_backlight_exit);
|
||||
module_platform_driver(pm860x_backlight_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
|
|
|
@ -280,14 +280,6 @@ config BACKLIGHT_WM831X
|
|||
If you have a backlight driven by the ISINK and DCDC of a
|
||||
WM831x PMIC say y to enable the backlight driver for it.
|
||||
|
||||
config BACKLIGHT_ADX
|
||||
tristate "Avionic Design Xanthos Backlight Driver"
|
||||
depends on ARCH_PXA_ADX
|
||||
default y
|
||||
help
|
||||
Say Y to enable the backlight driver on Avionic Design Xanthos-based
|
||||
boards.
|
||||
|
||||
config BACKLIGHT_ADP5520
|
||||
tristate "Backlight Driver for ADP5520/ADP5501 using WLED"
|
||||
depends on PMIC_ADP5520
|
||||
|
|
|
@ -32,7 +32,6 @@ obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
|
|||
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
|
||||
|
|
|
@ -384,17 +384,7 @@ static struct platform_driver adp5520_bl_driver = {
|
|||
.resume = adp5520_bl_resume,
|
||||
};
|
||||
|
||||
static int __init adp5520_bl_init(void)
|
||||
{
|
||||
return platform_driver_register(&adp5520_bl_driver);
|
||||
}
|
||||
module_init(adp5520_bl_init);
|
||||
|
||||
static void __exit adp5520_bl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&adp5520_bl_driver);
|
||||
}
|
||||
module_exit(adp5520_bl_exit);
|
||||
module_platform_driver(adp5520_bl_driver);
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
|
||||
MODULE_DESCRIPTION("ADP5520(01) Backlight Driver");
|
||||
|
|
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
* linux/drivers/video/backlight/adx.c
|
||||
*
|
||||
* Copyright (C) 2009 Avionic Design GmbH
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by Thierry Reding <thierry.reding@avionic-design.de>
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* register definitions */
|
||||
#define ADX_BACKLIGHT_CONTROL 0x00
|
||||
#define ADX_BACKLIGHT_CONTROL_ENABLE (1 << 0)
|
||||
#define ADX_BACKLIGHT_BRIGHTNESS 0x08
|
||||
#define ADX_BACKLIGHT_STATUS 0x10
|
||||
#define ADX_BACKLIGHT_ERROR 0x18
|
||||
|
||||
struct adxbl {
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
static int adx_backlight_update_status(struct backlight_device *bldev)
|
||||
{
|
||||
struct adxbl *bl = bl_get_data(bldev);
|
||||
u32 value;
|
||||
|
||||
value = bldev->props.brightness;
|
||||
writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS);
|
||||
|
||||
value = readl(bl->base + ADX_BACKLIGHT_CONTROL);
|
||||
|
||||
if (bldev->props.state & BL_CORE_FBBLANK)
|
||||
value &= ~ADX_BACKLIGHT_CONTROL_ENABLE;
|
||||
else
|
||||
value |= ADX_BACKLIGHT_CONTROL_ENABLE;
|
||||
|
||||
writel(value, bl->base + ADX_BACKLIGHT_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adx_backlight_get_brightness(struct backlight_device *bldev)
|
||||
{
|
||||
struct adxbl *bl = bl_get_data(bldev);
|
||||
u32 brightness;
|
||||
|
||||
brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS);
|
||||
return brightness & 0xff;
|
||||
}
|
||||
|
||||
static int adx_backlight_check_fb(struct backlight_device *bldev, struct fb_info *fb)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct backlight_ops adx_backlight_ops = {
|
||||
.options = 0,
|
||||
.update_status = adx_backlight_update_status,
|
||||
.get_brightness = adx_backlight_get_brightness,
|
||||
.check_fb = adx_backlight_check_fb,
|
||||
};
|
||||
|
||||
static int __devinit adx_backlight_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bldev;
|
||||
struct resource *res;
|
||||
struct adxbl *bl;
|
||||
int ret = 0;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = devm_request_mem_region(&pdev->dev, res->start,
|
||||
resource_size(res), res->name);
|
||||
if (!res) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL);
|
||||
if (!bl) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bl->base = devm_ioremap_nocache(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!bl->base) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = 0xff;
|
||||
bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
|
||||
bl, &adx_backlight_ops, &props);
|
||||
if (IS_ERR(bldev)) {
|
||||
ret = PTR_ERR(bldev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bldev->props.brightness = 0xff;
|
||||
bldev->props.power = FB_BLANK_UNBLANK;
|
||||
|
||||
platform_set_drvdata(pdev, bldev);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit adx_backlight_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bldev;
|
||||
int ret = 0;
|
||||
|
||||
bldev = platform_get_drvdata(pdev);
|
||||
bldev->props.power = FB_BLANK_UNBLANK;
|
||||
bldev->props.brightness = 0xff;
|
||||
backlight_update_status(bldev);
|
||||
backlight_device_unregister(bldev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int adx_backlight_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adx_backlight_resume(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define adx_backlight_suspend NULL
|
||||
#define adx_backlight_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver adx_backlight_driver = {
|
||||
.probe = adx_backlight_probe,
|
||||
.remove = __devexit_p(adx_backlight_remove),
|
||||
.suspend = adx_backlight_suspend,
|
||||
.resume = adx_backlight_resume,
|
||||
.driver = {
|
||||
.name = "adx-backlight",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init adx_backlight_init(void)
|
||||
{
|
||||
return platform_driver_register(&adx_backlight_driver);
|
||||
}
|
||||
|
||||
static void __exit adx_backlight_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&adx_backlight_driver);
|
||||
}
|
||||
|
||||
module_init(adx_backlight_init);
|
||||
module_exit(adx_backlight_exit);
|
||||
|
||||
MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
|
||||
MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -102,7 +102,7 @@ static void backlight_generate_event(struct backlight_device *bd,
|
|||
}
|
||||
|
||||
static ssize_t backlight_show_power(struct device *dev,
|
||||
struct device_attribute *attr,char *buf)
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
||||
|
@ -116,7 +116,7 @@ static ssize_t backlight_store_power(struct device *dev,
|
|||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
unsigned long power;
|
||||
|
||||
rc = strict_strtoul(buf, 0, &power);
|
||||
rc = kstrtoul(buf, 0, &power);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -150,7 +150,7 @@ static ssize_t backlight_store_brightness(struct device *dev,
|
|||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
unsigned long brightness;
|
||||
|
||||
rc = strict_strtoul(buf, 0, &brightness);
|
||||
rc = kstrtoul(buf, 0, &brightness);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -199,17 +199,7 @@ static struct platform_driver da903x_backlight_driver = {
|
|||
.remove = da903x_backlight_remove,
|
||||
};
|
||||
|
||||
static int __init da903x_backlight_init(void)
|
||||
{
|
||||
return platform_driver_register(&da903x_backlight_driver);
|
||||
}
|
||||
module_init(da903x_backlight_init);
|
||||
|
||||
static void __exit da903x_backlight_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&da903x_backlight_driver);
|
||||
}
|
||||
module_exit(da903x_backlight_exit);
|
||||
module_platform_driver(da903x_backlight_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
|
||||
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/backlight.h>
|
||||
|
@ -144,17 +143,7 @@ static struct platform_driver ep93xxbl_driver = {
|
|||
.resume = ep93xxbl_resume,
|
||||
};
|
||||
|
||||
static int __init ep93xxbl_init(void)
|
||||
{
|
||||
return platform_driver_register(&ep93xxbl_driver);
|
||||
}
|
||||
module_init(ep93xxbl_init);
|
||||
|
||||
static void __exit ep93xxbl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ep93xxbl_driver);
|
||||
}
|
||||
module_exit(ep93xxbl_exit);
|
||||
module_platform_driver(ep93xxbl_driver);
|
||||
|
||||
MODULE_DESCRIPTION("EP93xx Backlight Driver");
|
||||
MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
|
||||
|
|
|
@ -132,18 +132,7 @@ static struct platform_driver genericbl_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init genericbl_init(void)
|
||||
{
|
||||
return platform_driver_register(&genericbl_driver);
|
||||
}
|
||||
|
||||
static void __exit genericbl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&genericbl_driver);
|
||||
}
|
||||
|
||||
module_init(genericbl_init);
|
||||
module_exit(genericbl_exit);
|
||||
module_platform_driver(genericbl_driver);
|
||||
|
||||
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
|
||||
MODULE_DESCRIPTION("Generic Backlight Driver");
|
||||
|
|
|
@ -147,19 +147,8 @@ static struct platform_driver jornada_bl_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init jornada_bl_init(void)
|
||||
{
|
||||
return platform_driver_register(&jornada_bl_driver);
|
||||
}
|
||||
|
||||
static void __exit jornada_bl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&jornada_bl_driver);
|
||||
}
|
||||
module_platform_driver(jornada_bl_driver);
|
||||
|
||||
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
|
||||
MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(jornada_bl_init);
|
||||
module_exit(jornada_bl_exit);
|
||||
|
|
|
@ -135,19 +135,8 @@ static struct platform_driver jornada_lcd_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init jornada_lcd_init(void)
|
||||
{
|
||||
return platform_driver_register(&jornada_lcd_driver);
|
||||
}
|
||||
|
||||
static void __exit jornada_lcd_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&jornada_lcd_driver);
|
||||
}
|
||||
module_platform_driver(jornada_lcd_driver);
|
||||
|
||||
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
|
||||
MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(jornada_lcd_init);
|
||||
module_exit(jornada_lcd_exit);
|
||||
|
|
|
@ -97,19 +97,16 @@ static ssize_t lcd_store_power(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
char *endp;
|
||||
struct lcd_device *ld = to_lcd_device(dev);
|
||||
int power = simple_strtoul(buf, &endp, 0);
|
||||
size_t size = endp - buf;
|
||||
unsigned long power;
|
||||
|
||||
if (isspace(*endp))
|
||||
size++;
|
||||
if (size != count)
|
||||
return -EINVAL;
|
||||
rc = kstrtoul(buf, 0, &power);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->set_power) {
|
||||
pr_debug("lcd: set power to %d\n", power);
|
||||
pr_debug("lcd: set power to %lu\n", power);
|
||||
ld->ops->set_power(ld, power);
|
||||
rc = count;
|
||||
}
|
||||
|
@ -136,19 +133,16 @@ static ssize_t lcd_store_contrast(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
char *endp;
|
||||
struct lcd_device *ld = to_lcd_device(dev);
|
||||
int contrast = simple_strtoul(buf, &endp, 0);
|
||||
size_t size = endp - buf;
|
||||
unsigned long contrast;
|
||||
|
||||
if (isspace(*endp))
|
||||
size++;
|
||||
if (size != count)
|
||||
return -EINVAL;
|
||||
rc = kstrtoul(buf, 0, &contrast);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->set_contrast) {
|
||||
pr_debug("lcd: set contrast to %d\n", contrast);
|
||||
pr_debug("lcd: set contrast to %lu\n", contrast);
|
||||
ld->ops->set_contrast(ld, contrast);
|
||||
rc = count;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/lcd.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "ld9040_gamma.h"
|
||||
|
||||
|
@ -53,8 +54,51 @@ struct ld9040 {
|
|||
struct lcd_device *ld;
|
||||
struct backlight_device *bd;
|
||||
struct lcd_platform_data *lcd_pd;
|
||||
|
||||
struct mutex lock;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static struct regulator_bulk_data supplies[] = {
|
||||
{ .supply = "vdd3", },
|
||||
{ .supply = "vci", },
|
||||
};
|
||||
|
||||
static void ld9040_regulator_enable(struct ld9040 *lcd)
|
||||
{
|
||||
int ret = 0;
|
||||
struct lcd_platform_data *pd = NULL;
|
||||
|
||||
pd = lcd->lcd_pd;
|
||||
mutex_lock(&lcd->lock);
|
||||
if (!lcd->enabled) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lcd->enabled = true;
|
||||
}
|
||||
mdelay(pd->power_on_delay);
|
||||
out:
|
||||
mutex_unlock(&lcd->lock);
|
||||
}
|
||||
|
||||
static void ld9040_regulator_disable(struct ld9040 *lcd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&lcd->lock);
|
||||
if (lcd->enabled) {
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lcd->enabled = false;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&lcd->lock);
|
||||
}
|
||||
|
||||
static const unsigned short seq_swreset[] = {
|
||||
0x01, COMMAND_ONLY,
|
||||
ENDDEF, 0x00
|
||||
|
@ -532,13 +576,8 @@ static int ld9040_power_on(struct ld9040 *lcd)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!pd->power_on) {
|
||||
dev_err(lcd->dev, "power_on is NULL.\n");
|
||||
return -EFAULT;
|
||||
} else {
|
||||
pd->power_on(lcd->ld, 1);
|
||||
mdelay(pd->power_on_delay);
|
||||
}
|
||||
/* lcd power on */
|
||||
ld9040_regulator_enable(lcd);
|
||||
|
||||
if (!pd->reset) {
|
||||
dev_err(lcd->dev, "reset is NULL.\n");
|
||||
|
@ -582,11 +621,8 @@ static int ld9040_power_off(struct ld9040 *lcd)
|
|||
|
||||
mdelay(pd->power_off_delay);
|
||||
|
||||
if (!pd->power_on) {
|
||||
dev_err(lcd->dev, "power_on is NULL.\n");
|
||||
return -EFAULT;
|
||||
} else
|
||||
pd->power_on(lcd->ld, 0);
|
||||
/* lcd power off */
|
||||
ld9040_regulator_disable(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -693,6 +729,14 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
goto out_free_lcd;
|
||||
}
|
||||
|
||||
mutex_init(&lcd->lock);
|
||||
|
||||
ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
|
||||
if (ret) {
|
||||
dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
|
||||
goto out_free_lcd;
|
||||
}
|
||||
|
||||
ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
|
||||
if (IS_ERR(ld)) {
|
||||
ret = PTR_ERR(ld);
|
||||
|
@ -739,6 +783,8 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
out_unregister_lcd:
|
||||
lcd_device_unregister(lcd->ld);
|
||||
out_free_lcd:
|
||||
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
||||
|
||||
kfree(lcd);
|
||||
return ret;
|
||||
}
|
||||
|
@ -750,6 +796,7 @@ static int __devexit ld9040_remove(struct spi_device *spi)
|
|||
ld9040_power(lcd, FB_BLANK_POWERDOWN);
|
||||
backlight_device_unregister(lcd->bd);
|
||||
lcd_device_unregister(lcd->ld);
|
||||
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -188,17 +188,7 @@ static struct platform_driver max8925_backlight_driver = {
|
|||
.remove = __devexit_p(max8925_backlight_remove),
|
||||
};
|
||||
|
||||
static int __init max8925_backlight_init(void)
|
||||
{
|
||||
return platform_driver_register(&max8925_backlight_driver);
|
||||
}
|
||||
module_init(max8925_backlight_init);
|
||||
|
||||
static void __exit max8925_backlight_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&max8925_backlight_driver);
|
||||
};
|
||||
module_exit(max8925_backlight_exit);
|
||||
module_platform_driver(max8925_backlight_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
|
|
|
@ -195,18 +195,7 @@ static struct platform_driver omapbl_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init omapbl_init(void)
|
||||
{
|
||||
return platform_driver_register(&omapbl_driver);
|
||||
}
|
||||
|
||||
static void __exit omapbl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&omapbl_driver);
|
||||
}
|
||||
|
||||
module_init(omapbl_init);
|
||||
module_exit(omapbl_exit);
|
||||
module_platform_driver(omapbl_driver);
|
||||
|
||||
MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>");
|
||||
MODULE_DESCRIPTION("OMAP LCD Backlight driver");
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче