Commit 7d36014b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'akpm' (Andrew's patch-bomb)

Merge patches through Andrew Morton:
 "180 patches - err 181 - listed below:

   - most of MM.  I held back the (large) "memcg: add hugetlb extension"
     series because a bunfight has recently broken out.

   - leds.  After this, Bryan Wu will be handling drivers/leds/

   - backlight

   - lib/

   - rtc"

* emailed from Andrew Morton <akpm@linux-foundation.org>: (181 patches)
  drivers/rtc/rtc-s3c.c: fix compiler warning
  drivers/rtc/rtc-tegra.c: clean up probe/remove routines
  drivers/rtc/rtc-pl031.c: remove RTC timer interrupt handling
  drivers/rtc/rtc-lpc32xx.c: add device tree support
  drivers/rtc/rtc-m41t93.c: don't let get_time() reset M41T93_FLAG_OF
  rtc: ds1307: add trickle charger support
  rtc: ds1307: remove superfluous initialization
  rtc: rename CONFIG_RTC_MXC to CONFIG_RTC_DRV_MXC
  drivers/rtc/Kconfig: place RTC_DRV_IMXDI and RTC_MXC under "on-CPU RTC drivers"
  drivers/rtc/rtc-pcf8563.c: add RTC_VL_READ/RTC_VL_CLR ioctl feature
  rtc: add ioctl to get/clear battery low voltage status
  drivers/rtc/rtc-ep93xx.c: convert to use module_platform_driver()
  rtc/spear: add Device Tree probing capability
  lib/vsprintf.c: "%#o",0 becomes '0' instead of '00'
  radix-tree: fix preload vector size
  spinlock_debug: print kallsyms name for lock
  vsprintf: fix %ps on non symbols when using kallsyms
  lib/bitmap.c: fix documentation for scnprintf() functions
  lib/string_helpers.c: make arrays static
  lib/test-kstrtox.c: mark const init data with __initconst instead of __initdata
  ...
parents 442a9ffa ecb41a77
What: /sys/class/backlight/<backlight>/als_channel
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get the ALS output channel used as input in
ALS-current-control mode (0, 1), where
0 - out_current0 (backlight 0)
1 - out_current1 (backlight 1)
What: /sys/class/backlight/<backlight>/als_en
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Enable ALS-current-control mode (0, 1).
What: /sys/class/backlight/<backlight>/id
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get the id of this backlight (0, 1).
What: /sys/class/backlight/<backlight>/linear
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the brightness-mapping mode (0, 1), where
0 - exponential mode
1 - linear mode
What: /sys/class/backlight/<backlight>/pwm
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the PWM-input control mask (5 bits), where
bit 5 - PWM-input enabled in Zone 4
bit 4 - PWM-input enabled in Zone 3
bit 3 - PWM-input enabled in Zone 2
bit 2 - PWM-input enabled in Zone 1
bit 1 - PWM-input enabled in Zone 0
bit 0 - PWM-input enabled
What: /sys/class/leds/<led>/als_channel
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the ALS output channel to use as input in
ALS-current-control mode (1, 2), where
1 - out_current1
2 - out_current2
What: /sys/class/leds/<led>/als_en
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Enable ALS-current-control mode (0, 1).
What: /sys/class/leds/<led>/falltime
What: /sys/class/leds/<led>/risetime
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the pattern generator fall and rise times (0..7), where
0 - 2048 us
1 - 262 ms
2 - 524 ms
3 - 1.049 s
4 - 2.097 s
5 - 4.194 s
6 - 8.389 s
7 - 16.78 s
What: /sys/class/leds/<led>/id
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get the id of this led (0..3).
What: /sys/class/leds/<led>/linear
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the brightness-mapping mode (0, 1), where
0 - exponential mode
1 - linear mode
What: /sys/class/leds/<led>/pwm
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the PWM-input control mask (5 bits), where
bit 5 - PWM-input enabled in Zone 4
bit 4 - PWM-input enabled in Zone 3
bit 3 - PWM-input enabled in Zone 2
bit 2 - PWM-input enabled in Zone 1
bit 1 - PWM-input enabled in Zone 0
bit 0 - PWM-input enabled
......@@ -184,12 +184,14 @@ behind this approach is that a cgroup that aggressively uses a shared
page will eventually get charged for it (once it is uncharged from
the cgroup that brought it in -- this will happen on memory pressure).
But see section 8.2: when moving a task to another cgroup, its pages may
be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used.
When you do swapoff and make swapped-out pages of shmem(tmpfs) to
be backed into memory in force, charges for pages are accounted against the
caller of swapoff rather than the users of shmem.
2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP)
Swap Extension allows you to record charge for swap. A swapped-in page is
......@@ -374,14 +376,15 @@ cgroup might have some charge associated with it, even though all
tasks have migrated away from it. (because we charge against pages, not
against tasks.)
Such charges are freed or moved to their parent. At moving, both of RSS
and CACHES are moved to parent.
rmdir() may return -EBUSY if freeing/moving fails. See 5.1 also.
We move the stats to root (if use_hierarchy==0) or parent (if
use_hierarchy==1), and no change on the charge except uncharging
from the child.
Charges recorded in swap information is not updated at removal of cgroup.
Recorded information is discarded and a cgroup which uses swap (swapcache)
will be charged as a new owner of it.
About use_hierarchy, see Section 6.
5. Misc. interfaces.
......@@ -394,13 +397,15 @@ will be charged as a new owner of it.
Almost all pages tracked by this memory cgroup will be unmapped and freed.
Some pages cannot be freed because they are locked or in-use. Such pages are
moved to parent and this cgroup will be empty. This may return -EBUSY if
VM is too busy to free/move all pages immediately.
moved to parent(if use_hierarchy==1) or root (if use_hierarchy==0) and this
cgroup will be empty.
Typical use case of this interface is that calling this before rmdir().
Because rmdir() moves all pages to parent, some out-of-use page caches can be
moved to the parent. If you want to avoid that, force_empty will be useful.
About use_hierarchy, see Section 6.
5.2 stat file
memory.stat file includes following statistics
......@@ -430,17 +435,10 @@ hierarchical_memory_limit - # of bytes of memory limit with regard to hierarchy
hierarchical_memsw_limit - # of bytes of memory+swap limit with regard to
hierarchy under which memory cgroup is.
total_cache - sum of all children's "cache"
total_rss - sum of all children's "rss"
total_mapped_file - sum of all children's "cache"
total_pgpgin - sum of all children's "pgpgin"
total_pgpgout - sum of all children's "pgpgout"
total_swap - sum of all children's "swap"
total_inactive_anon - sum of all children's "inactive_anon"
total_active_anon - sum of all children's "active_anon"
total_inactive_file - sum of all children's "inactive_file"
total_active_file - sum of all children's "active_file"
total_unevictable - sum of all children's "unevictable"
total_<counter> - # hierarchical version of <counter>, which in
addition to the cgroup's own value includes the
sum of all hierarchical children's values of
<counter>, i.e. total_cache
# The following additional stats are dependent on CONFIG_DEBUG_VM.
......@@ -622,8 +620,7 @@ memory cgroup.
bit | what type of charges would be moved ?
-----+------------------------------------------------------------------------
0 | A charge of an anonymous page(or swap of it) used by the target task.
| Those pages and swaps must be used only by the target task. You must
| enable Swap Extension(see 2.4) to enable move of swap charges.
| You must enable Swap Extension(see 2.4) to enable move of swap charges.
-----+------------------------------------------------------------------------
1 | A charge of file pages(normal file, tmpfs file(e.g. ipc shared memory)
| and swaps of tmpfs file) mmapped by the target task. Unlike the case of
......@@ -636,8 +633,6 @@ memory cgroup.
8.3 TODO
- Implement madvise(2) to let users decide the vma to be moved or not to be
moved.
- All of moving charge operations are done under cgroup_mutex. It's not good
behavior to hold the mutex too long, so we may need some trick.
......
......@@ -92,6 +92,14 @@ to work with it.
The _locked routines imply that the res_counter->lock is taken.
f. void res_counter_uncharge_until
(struct res_counter *rc, struct res_counter *top,
unsinged long val)
Almost same as res_cunter_uncharge() but propagation of uncharge
stops when rc == top. This is useful when kill a res_coutner in
child cgroup.
2.1 Other accounting routines
There are more routines that may help you with common needs, like
......
* NXP LPC32xx SoC Real Time Clock controller
Required properties:
- compatible: must be "nxp,lpc3220-rtc"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The RTC interrupt
Example:
rtc@40024000 {
compatible = "nxp,lpc3220-rtc";
reg = <0x40024000 0x1000>;
interrupts = <52 0>;
};
* SPEAr RTC
Required properties:
- compatible : "st,spear600-rtc"
- reg : Address range of the rtc registers
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupt: Should contain the rtc interrupt number
Example:
rtc@fc000000 {
compatible = "st,spear600-rtc";
reg = <0xfc000000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <12>;
};
......@@ -60,7 +60,6 @@ ata *);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
void (*truncate_range)(struct inode *, loff_t, loff_t);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
locking rules:
......@@ -87,7 +86,6 @@ setxattr: yes
getxattr: no
listxattr: no
removexattr: yes
truncate_range: yes
fiemap: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim.
......
......@@ -743,6 +743,7 @@ Committed_AS: 100056 kB
VmallocTotal: 112216 kB
VmallocUsed: 428 kB
VmallocChunk: 111088 kB
AnonHugePages: 49152 kB
MemTotal: Total usable ram (i.e. physical ram minus a few reserved
bits and the kernel binary code)
......@@ -776,6 +777,7 @@ VmallocChunk: 111088 kB
Dirty: Memory which is waiting to get written back to the disk
Writeback: Memory which is actively being written back to the disk
AnonPages: Non-file backed pages mapped into userspace page tables
AnonHugePages: Non-file backed huge pages mapped into userspace page tables
Mapped: files which have been mmaped, such as libraries
Slab: in-kernel data structures cache
SReclaimable: Part of Slab, that might be reclaimed, such as caches
......
......@@ -363,7 +363,6 @@ struct inode_operations {
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
void (*truncate_range)(struct inode *, loff_t, loff_t);
};
Again, all methods are called without any locks being held, unless
......@@ -472,9 +471,6 @@ otherwise noted.
removexattr: called by the VFS to remove an extended attribute from
a file. This method is called by removexattr(2) system call.
truncate_range: a method provided by the underlying filesystem to truncate a
range of blocks , i.e. punch a hole somewhere in a file.
The Address Space Object
========================
......@@ -760,7 +756,7 @@ struct file_operations
----------------------
This describes how the VFS can manipulate an open file. As of kernel
2.6.22, the following members are defined:
3.5, the following members are defined:
struct file_operations {
struct module *owner;
......@@ -790,6 +786,8 @@ struct file_operations {
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long arg, struct file_lock **);
long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len);
};
Again, all methods are called without any locks being held, unless
......@@ -858,6 +856,11 @@ otherwise noted.
splice_read: called by the VFS to splice data from file to a pipe. This
method is used by the splice(2) system call
setlease: called by the VFS to set or release a file lock lease.
setlease has the file_lock_lock held and must not sleep.
fallocate: called by the VFS to preallocate blocks or punch a hole.
Note that the file operations are implemented by the specific
filesystem in which the inode resides. When opening a device node
(character or block special) most filesystems will call special
......
LED Transient Trigger
=====================
The leds timer trigger does not currently have an interface to activate
a one shot timer. The current support allows for setting two timers, one for
specifying how long a state to be on, and the second for how long the state
to be off. The delay_on value specifies the time period an LED should stay
in on state, followed by a delay_off value that specifies how long the LED
should stay in off state. The on and off cycle repeats until the trigger
gets deactivated. There is no provision for one time activation to implement
features that require an on or off state to be held just once and then stay in
the original state forever.
Without one shot timer interface, user space can still use timer trigger to
set a timer to hold a state, however when user space application crashes or
goes away without deactivating the timer, the hardware will be left in that
state permanently.
As a specific example of this use-case, let's look at vibrate feature on
phones. Vibrate function on phones is implemented using PWM pins on SoC or
PMIC. There is a need to activate one shot timer to control the vibrate
feature, to prevent user space crashes leaving the phone in vibrate mode
permanently causing the battery to drain.
Transient trigger addresses the need for one shot timer activation. The
transient trigger can be enabled and disabled just like the other leds
triggers.
When an led class device driver registers itself, it can specify all leds
triggers it supports and a default trigger. During registration, activation
routine for the default trigger gets called. During registration of an led
class device, the LED state does not change.
When the driver unregisters, deactivation routine for the currently active
trigger will be called, and LED state is changed to LED_OFF.
Driver suspend changes the LED state to LED_OFF and resume doesn't change
the state. Please note that there is no explicit interaction between the
suspend and resume actions and the currently enabled trigger. LED state
changes are suspended while the driver is in suspend state. Any timers
that are active at the time driver gets suspended, continue to run, without
being able to actually change the LED state. Once driver is resumed, triggers
start functioning again.
LED state changes are controlled using brightness which is a common led
class device property. When brightness is set to 0 from user space via
echo 0 > brightness, it will result in deactivating the current trigger.
Transient trigger uses standard register and unregister interfaces. During
trigger registration, for each led class device that specifies this trigger
as its default trigger, trigger activation routine will get called. During
registration, the LED state does not change, unless there is another trigger
active, in which case LED state changes to LED_OFF.
During trigger unregistration, LED state gets changed to LED_OFF.
Transient trigger activation routine doesn't change the LED state. It
creates its properties and does its initialization. Transient trigger
deactivation routine, will cancel any timer that is active before it cleans
up and removes the properties it created. It will restore the LED state to
non-transient state. When driver gets suspended, irrespective of the transient
state, the LED state changes to LED_OFF.
Transient trigger can be enabled and disabled from user space on led class
devices, that support this trigger as shown below:
echo transient > trigger
echo none > trigger
NOTE: Add a new property trigger state to control the state.
This trigger exports three properties, activate, state, and duration. When
transient trigger is activated these properties are set to default values.
- duration allows setting timer value in msecs. The initial value is 0.
- activate allows activating and deactivating the timer specified by
duration as needed. The initial and default value is 0. This will allow
duration to be set after trigger activation.
- state allows user to specify a transient state to be held for the specified
duration.
activate - one shot timer activate mechanism.
1 when activated, 0 when deactivated.
default value is zero when transient trigger is enabled,
to allow duration to be set.
activate state indicates a timer with a value of specified
duration running.
deactivated state indicates that there is no active timer
running.
duration - one shot timer value. When activate is set, duration value
is used to start a timer that runs once. This value doesn't
get changed by the trigger unless user does a set via
echo new_value > duration
state - transient state to be held. It has two values 0 or 1. 0 maps
to LED_OFF and 1 maps to LED_FULL. The specified state is
held for the duration of the one shot timer and then the
state gets changed to the non-transient state which is the
inverse of transient state.
If state = LED_FULL, when the timer runs out the state will
go back to LED_OFF.
If state = LED_OFF, when the timer runs out the state will
go back to LED_FULL.
Please note that current LED state is not checked prior to
changing the state to the specified state.
Driver could map these values to inverted depending on the
default states it defines for the LED in its brightness_set()
interface which is called from the led brightness_set()
interfaces to control the LED state.
When timer expires activate goes back to deactivated state, duration is left
at the set value to be used when activate is set at a future time. This will
allow user app to set the time once and activate it to run it once for the
specified value as needed. When timer expires, state is restored to the
non-transient state which is the inverse of the transient state.
echo 1 > activate - starts timer = duration when duration is not 0.
echo 0 > activate - cancels currently running timer.
echo n > duration - stores timer value to be used upon next
activate. Currently active timer if
any, continues to run for the specified time.
echo 0 > duration - stores timer value to be used upon next
activate. Currently active timer if any,
continues to run for the specified time.
echo 1 > state - stores desired transient state LED_FULL to be
held for the specified duration.
echo 0 > state - stores desired transient state LED_OFF to be
held for the specified duration.
What is not supported:
======================
- Timer activation is one shot and extending and/or shortening the timer
is not supported.
Example use-case 1:
echo transient > trigger
echo n > duration
echo 1 > state
repeat the following step as needed:
echo 1 > activate - start timer = duration to run once
echo 1 > activate - start timer = duration to run once
echo none > trigger
This trigger is intended to be used for for the following example use cases:
- Control of vibrate (phones, tablets etc.) hardware by user space app.
- Use of LED by user space app as activity indicator.
- Use of LED by user space app as a kind of watchdog indicator -- as
long as the app is alive, it can keep the LED illuminated, if it dies
the LED will be extinguished automatically.
- Use by any user space app that needs a transient GPIO output.
......@@ -166,6 +166,68 @@ behavior. So to make them effective you need to restart any
application that could have been using hugepages. This also applies to
the regions registered in khugepaged.
== Monitoring usage ==
The number of transparent huge pages currently used by the system is
available by reading the AnonHugePages field in /proc/meminfo. To
identify what applications are using transparent huge pages, it is
necessary to read /proc/PID/smaps and count the AnonHugePages fields
for each mapping. Note that reading the smaps file is expensive and
reading it frequently will incur overhead.
There are a number of counters in /proc/vmstat that may be used to
monitor how successfully the system is providing huge pages for use.
thp_fault_alloc is incremented every time a huge page is successfully
allocated to handle a page fault. This applies to both the
first time a page is faulted and for COW faults.
thp_collapse_alloc is incremented by khugepaged when it has found
a range of pages to collapse into one huge page and has
successfully allocated a new huge page to store the data.
thp_fault_fallback is incremented if a page fault fails to allocate
a huge page and instead falls back to using small pages.
thp_collapse_alloc_failed is incremented if khugepaged found a range
of pages that should be collapsed into one huge page but failed
the allocation.
thp_split is incremented every time a huge page is split into base
pages. This can happen for a variety of reasons but a common
reason is that a huge page is old and is being reclaimed.
As the system ages, allocating huge pages may be expensive as the
system uses memory compaction to copy data around memory to free a
huge page for use. There are some counters in /proc/vmstat to help
monitor this overhead.
compact_stall is incremented every time a process stalls to run
memory compaction so that a huge page is free for use.
compact_success is incremented if the system compacted memory and
freed a huge page for use.
compact_fail is incremented if the system tries to compact memory
but failed.
compact_pages_moved is incremented each time a page is moved. If
this value is increasing rapidly, it implies that the system
is copying a lot of data to satisfy the huge page allocation.
It is possible that the cost of copying exceeds any savings
from reduced TLB misses.
compact_pagemigrate_failed is incremented when the underlying mechanism
for moving a page failed.
compact_blocks_moved is incremented each time memory compaction examines
a huge page aligned range of pages.
It is possible to establish how long the stalls were using the function
tracer to record how long was spent in __alloc_pages_nodemask and
using the mm_page_alloc tracepoint to identify which allocations were
for huge pages.
== get_user_pages and follow_page ==
get_user_pages and follow_page if run on a hugepage, will return the
......
......@@ -3232,10 +3232,8 @@ F: include/linux/clockchips.h
F: include/linux/hrtimer.h
HIGH-SPEED SCC DRIVER FOR AX.25
M: Klaus Kudielka <klaus.kudielka@ieee.org>
L: linux-hams@vger.kernel.org
W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/
S: Maintained
S: Orphan
F: drivers/net/hamradio/dmascc.c
F: drivers/net/hamradio/scc.c
......@@ -4511,12 +4509,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/mmc/host/imxmmc.*
MOUSE AND MISC DEVICES [GENERAL]
M: Alessandro Rubini <rubini@ipvvis.unipv.it>
S: Maintained
F: drivers/input/mouse/
F: include/linux/gpio_mouse.h
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@gmail.com>
S: Maintained
......
......@@ -173,7 +173,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PCF8563=y
CONFIG_RTC_DRV_IMXDI=y
CONFIG_RTC_MXC=y
CONFIG_RTC_DRV_MXC=y
CONFIG_DMADEVICES=y
CONFIG_IMX_SDMA=y
CONFIG_IMX_DMA=y
......
......@@ -178,7 +178,7 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
CONFIG_RTC_MXC=y
CONFIG_RTC_DRV_MXC=y
CONFIG_DMADEVICES=y
CONFIG_IMX_SDMA=y
CONFIG_EXT2_FS=y
......
......@@ -40,6 +40,7 @@ config CRIS
bool
default y
select HAVE_IDE
select GENERIC_ATOMIC64
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_SHOW
select GENERIC_IOMAP
......
......@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
ptep->pte_low = pte.pte_low;
}
#define pmd_read_atomic pmd_read_atomic
/*
* pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with
* a "*pmdp" dereference done by gcc. Problem is, in certain places
* where pte_offset_map_lock is called, concurrent page faults are
* allowed, if the mmap_sem is hold for reading. An example is mincore
* vs page faults vs MADV_DONTNEED. On the page fault side
* pmd_populate rightfully does a set_64bit, but if we're reading the
* pmd_t with a "*pmdp" on the mincore side, a SMP race can happen
* because gcc will not read the 64bit of the pmd atomically. To fix
* this all places running pmd_offset_map_lock() while holding the
* mmap_sem in read mode, shall read the pmdp pointer using this
* function to know if the pmd is null nor not, and in turn to know if
* they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
* operations.
*
* Without THP if the mmap_sem is hold for reading, the
* pmd can only transition from null to not null while pmd_read_atomic runs.
* So there's no need of literally reading it atomically.
*
* With THP if the mmap_sem is hold for reading, the pmd can become
* THP or null or point to a pte (and in turn become "stable") at any
* time under pmd_read_atomic, so it's mandatory to read it atomically
* with cmpxchg8b.
*/
#ifndef CONFIG_TRANSPARENT_HUGEPAGE
static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
{
pmdval_t ret;
u32 *tmp = (u32 *)pmdp;
ret = (pmdval_t) (*tmp);
if (ret) {
/*
* If the low part is null, we must not read the high part
* or we can end up with a partial pmd.
*/
smp_rmb();
ret |= ((pmdval_t)*(tmp + 1)) << 32;
}
return (pmd_t) { ret };
}
#else /* CONFIG_TRANSPARENT_HUGEPAGE */
static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
{
return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
{
set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
......
......@@ -113,7 +113,9 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
int x = e820x->nr_map;
if (x >= ARRAY_SIZE(e820x->map)) {
printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n",
(unsigned long long) start,
(unsigned long long) (start + size - 1));
return;
}
......@@ -133,19 +135,19 @@ static void __init e820_print_type(u32 type)
switch (type) {
case E820_RAM:
case E820_RESERVED_KERN:
printk(KERN_CONT "(usable)");
printk(KERN_CONT "usable");
break;
case E820_RESERVED:
printk(KERN_CONT "(reserved)");
printk(KERN_CONT "reserved");
break;
case E820_ACPI:
printk(KERN_CONT "(ACPI data)");
printk(KERN_CONT "ACPI data");
break;
case E820_NVS:
printk(KERN_CONT "(ACPI NVS)");
printk(KERN_CONT "ACPI NVS");
break;
case E820_UNUSABLE:
printk(KERN_CONT "(unusable)");
printk(KERN_CONT "unusable");
break;
default:
printk(KERN_CONT "type %u", type);
......@@ -158,10 +160,10 @@ void __init e820_print_map(char *who)
int i;
for (i = 0; i < e820.nr_map; i++) {
printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who,
(unsigned long long) e820.map[i].addr,
(unsigned long long)
(e820.map[i].addr + e820.map[i].size));
(e820.map[i].addr + e820.map[i].size - 1));
e820_print_type(e820.map[i].type);
printk(KERN_CONT "\n");
}
......@@ -428,9 +430,8 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
size = ULLONG_MAX - start;
end = start + size;
printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ",
(unsigned long long) start,
(unsigned long long) end);
printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ",
(unsigned long long) start, (unsigned long long) (end - 1));
e820_print_type(old_type);
printk(KERN_CONT " ==> ");
e820_print_type(new_type);
......@@ -509,9 +510,8 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
size = ULLONG_MAX - start;
end = start + size;
printk(KERN_DEBUG "e820 remove range: %016Lx - %016Lx ",
(unsigned long long) start,
(unsigned long long) end);
printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ",
(unsigned long long) start, (unsigned long long) (end - 1));
if (checktype)
e820_print_type(old_type);
printk(KERN_CONT "\n");
......@@ -567,7 +567,7 @@ void __init update_e820(void)
if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
return;
e820.nr_map = nr_map;
printk(KERN_INFO "modified physical RAM map:\n");
printk(KERN_INFO "e820: modified physical RAM map:\n");
e820_print_map("modified");
}
static void __init update_e820_saved(void)
......@@ -637,8 +637,8 @@ __init void e820_setup_gap(void)
if (!found) {
gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
printk(KERN_ERR
"PCI: Warning: Cannot find a gap in the 32bit address range\n"
"PCI: Unassigned devices with 32bit resource registers may break!\n");
"e820: cannot find a gap in the 32bit address range\n"
"e820: PCI devices with unassigned 32bit BARs may break!\n");
}
#endif
......@@ -648,8 +648,8 @@ __init void e820_setup_gap(void)
pci_mem_start = gapstart;
printk(KERN_INFO
"Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
pci_mem_start, gapstart, gapsize);
"e820: [mem %#010lx-%#010lx] available for PCI devices\n",
gapstart, gapstart + gapsize - 1);
}
/**
......@@ -667,7 +667,7 @@ void __init parse_e820_ext(struct setup_data *sdata)
extmap = (struct e820entry *)(sdata->data);
__append_e820_map(extmap, entries);
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
printk(KERN_INFO "extended physical RAM map:\n");
printk(KERN_INFO "e820: extended physical RAM map:\n");
e820_print_map("extended");
}
......@@ -734,7 +734,7 @@ u64 __init early_reserve_e820(u64 size, u64 align)
addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
if (addr) {
e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
printk(KERN_INFO "e820: update e820_saved for early_reserve_e820\n");
update_e820_saved();
}
......@@ -784,7 +784,7 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
if (last_pfn > max_arch_pfn)
last_pfn = max_arch_pfn;
printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
printk(KERN_INFO "e820: last_pfn = %#lx max_arch_pfn = %#lx\n",
last_pfn, max_arch_pfn);
return last_pfn;
}
......@@ -888,7 +888,7 @@ void __init finish_e820_parsing(void)
early_panic("Invalid user supplied memory map");
e820.nr_map = nr;
printk(KERN_INFO "user-defined physical RAM map:\n");
printk(KERN_INFO "e820: user-defined physical RAM map:\n");
e820_print_map("user");
}
}
......@@ -996,8 +996,9 @@ void __init e820_reserve_resources_late(void)
end = MAX_RESOURCE_SIZE;
if (start >= end)
continue;
printk(KERN_DEBUG "reserve RAM buffer: %016llx - %016llx ",
start, end);
printk(KERN_DEBUG
"e820: reserve RAM buffer [mem %#010llx-%#010llx]\n",
start, end);
reserve_region_with_split(&iomem_resource, start, end,
"RAM buffer");
}
......@@ -1047,7 +1048,7 @@ void __init setup_memory_map(void)
who = x86_init.resources.memory_setup();
memcpy(&e820_saved, &e820, sizeof(struct e820map));
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n");
e820_print_map(who);
}
......
......@@ -568,8 +568,8 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
struct mpf_intel *mpf;
unsigned long mem;
apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
bp, length);
apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n",
base, base + length - 1);
BUILD_BUG_ON(sizeof(*mpf) != 16);
while (length > 0) {
......@@ -584,8 +584,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
#endif
mpf_found = mpf;
printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
mpf, (u64)virt_to_phys(mpf));
printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
(unsigned long long) virt_to_phys(mpf),
(unsigned long long) virt_to_phys(mpf) +
sizeof(*mpf) - 1, mpf);
mem = virt_to_phys(mpf);
memblock_reserve(mem, sizeof(*mpf));
......
......@@ -334,8 +334,8 @@ static void __init relocate_initrd(void)
memblock_reserve(ramdisk_here, area_size);
initrd_start = ramdisk_here + PAGE_OFFSET;
initrd_end = initrd_start + ramdisk_size;
printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
ramdisk_here, ramdisk_here + ramdisk_size);
printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
ramdisk_here, ramdisk_here + ramdisk_size - 1);
q = (char *)initrd_start;
......@@ -366,8 +366,8 @@ static void __init relocate_initrd(void)
/* high pages is not converted by early_res_to_bootmem */
ramdisk_image = boot_params.hdr.ramdisk_image;
ramdisk_size = boot_params.hdr.ramdisk_size;
printk(KERN_INFO "Move RAMDISK from %016llx - %016llx to"
" %08llx - %08llx\n",
printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
" [mem %#010llx-%#010llx]\n",
ramdisk_image, ramdisk_image + ramdisk_size - 1,
ramdisk_here, ramdisk_here + ramdisk_size - 1);
}
......@@ -392,8 +392,8 @@ static void __init reserve_initrd(void)
ramdisk_size, end_of_lowmem>>1);
}
printk(KERN_INFO "RAMDISK: %08llx - %08llx\n", ramdisk_image,
ramdisk_end);
printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
ramdisk_end - 1);
if (ramdisk_end <= end_of_lowmem) {
......@@ -906,8 +906,8 @@ void __init setup_arch(char **cmdline_p)
setup_bios_corruption_check();
#endif
printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
max_pfn_mapped<<PAGE_SHIFT);
printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
(max_pfn_mapped<<PAGE_SHIFT) - 1);
setup_trampolines();
......
......@@ -84,8 +84,9 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
pgt_buf_end = pgt_buf_start;
pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
end - 1, pgt_buf_start << PAGE_SHIFT,
(pgt_buf_top << PAGE_SHIFT) - 1);
}
void __init native_pagetable_reserve(u64 start, u64 end)
......@@ -132,7 +133,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
int nr_range, i;
int use_pse, use_gbpages;
printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
printk(KERN_INFO "init_memory_mapping: [mem %#010lx-%#010lx]\n",
start, end - 1);
#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
/*
......@@ -251,8 +253,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
}
for (i = 0; i < nr_range; i++)
printk(KERN_DEBUG " %010lx - %010lx page %s\n",
mr[i].start, mr[i].end,
printk(KERN_DEBUG " [mem %#010lx-%#010lx] page %s\n",
mr[i].start, mr[i].end - 1,
(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
(mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
......@@ -350,8 +352,8 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
* create a kernel page fault:
*/
#ifdef CONFIG_DEBUG_PAGEALLOC
printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
begin, end);
printk(KERN_INFO "debug: unmapping init [mem %#010lx-%#010lx]\n",
begin, end - 1);
set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
#else
/*
......
......@@ -141,8 +141,8 @@ static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
/* whine about and ignore invalid blks */
if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
nid, start, end);
pr_warning("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
nid, start, end - 1);
return 0;
}
......@@ -210,8 +210,8 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
start = roundup(start, ZONE_ALIGN);
printk(KERN_INFO "Initmem setup node %d %016Lx-%016Lx\n",
nid, start, end);
printk(KERN_INFO "Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
nid, start, end - 1);
/*
* Allocate node data. Try remap allocator first, node-local
......@@ -232,7 +232,7 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
}
/* report and initialize */
printk(KERN_INFO " NODE_DATA [%016Lx - %016Lx]%s\n",
printk(KERN_INFO " NODE_DATA [mem %#010Lx-%#010Lx]%s\n",
nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : "");
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
if (!remapped && tnid != nid)
......@@ -291,14 +291,14 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
*/
if (bi->end > bj->start && bi->start < bj->end) {
if (bi->nid != bj->nid) {
pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
bi->nid, bi->start, bi->end,
bj->nid, bj->start, bj->end);
pr_err("NUMA: node %d [mem %#010Lx-%#010Lx] overlaps with node %d [mem %#010Lx-%#010Lx]\n",
bi->nid, bi->start, bi->end - 1,
bj->nid, bj->start, bj->end - 1);
return -EINVAL;
}
pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
bi->nid, bi->start, bi->end,
bj->start, bj->end);
pr_warning("NUMA: Warning: node %d [mem %#010Lx-%#010Lx] overlaps with itself [mem %#010Lx-%#010Lx]\n",
bi->nid, bi->start, bi->end - 1,
bj->start, bj->end - 1);
}
/*
......@@ -320,9 +320,9 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
}
if (k < mi->nr_blks)
continue;
printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%Lx,%Lx)\n",
bi->nid, bi->start, bi->end, bj->start, bj->end,
start, end);
printk(KERN_INFO "NUMA: Node %d [mem %#010Lx-%#010Lx] + [mem %#010Lx-%#010Lx] -> [mem %#010Lx-%#010Lx]\n",
bi->nid, bi->start, bi->end - 1, bj->start,
bj->end - 1, start, end - 1);
bi->start = start;
bi->end = end;
numa_remove_memblk_from(j--, mi);
......@@ -616,8 +616,8 @@ static int __init dummy_numa_init(void)
{
printk(KERN_INFO "%s\n",
numa_off ? "NUMA turned off" : "No NUMA configuration found");
printk(KERN_INFO "Faking a node at %016Lx-%016Lx\n",
0LLU, PFN_PHYS(max_pfn));
printk(KERN_INFO "Faking a node at [mem %#018Lx-%#018Lx]\n",
0LLU, PFN_PHYS(max_pfn) - 1);
node_set(0, numa_nodes_parsed);
numa_add_memblk(0, 0, PFN_PHYS(max_pfn));
......
......@@ -68,8 +68,8 @@ static int __init emu_setup_memblk(struct numa_meminfo *ei,
numa_remove_memblk_from(phys_blk, pi);
}
printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
eb->start, eb->end, (eb->end - eb->start) >> 20);
printk(KERN_INFO "Faking node %d at [mem %#018Lx-%#018Lx] (%LuMB)\n",
nid, eb->start, eb->end - 1, (eb->end - eb->start) >> 20);
return 0;
}
......
......@@ -209,9 +209,8 @@ static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
page = pfn_to_page(pfn);
type = get_page_memtype(page);
if (type != -1) {
printk(KERN_INFO "reserve_ram_pages_type failed "
"0x%Lx-0x%Lx, track 0x%lx, req 0x%lx\n",
start, end, type, req_type);
printk(KERN_INFO "reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%lx, req 0x%lx\n",
start, end - 1, type, req_type);
if (new_type)
*new_type = type;
......@@ -314,9 +313,9 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
err = rbt_memtype_check_insert(new, new_type);
if (err) {
printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
"track %s, req %s\n",
start, end, cattr_name(new->type), cattr_name(req_type));
printk(KERN_INFO "reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
start, end - 1,
cattr_name(new->type), cattr_name(req_type));
kfree(new);
spin_unlock(&memtype_lock);
......@@ -325,8 +324,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
spin_unlock(&memtype_lock);
dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
start, end, cattr_name(new->type), cattr_name(req_type),
dprintk("reserve_memtype added [mem %#010Lx-%#010Lx], track %s, req %s, ret %s\n",
start, end - 1, cattr_name(new->type), cattr_name(req_type),
new_type ? cattr_name(*new_type) : "-");
return err;
......@@ -360,14 +359,14 @@ int free_memtype(u64 start, u64 end)
spin_unlock(&memtype_lock);
if (!entry) {
printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
current->comm, current->pid, start, end);
printk(KERN_INFO "%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
current->comm, current->pid, start, end - 1);
return -EINVAL;
}
kfree(entry);
dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
dprintk("free_memtype request [mem %#010Lx-%#010Lx]\n", start, end - 1);
return 0;
}
......@@ -491,9 +490,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
while (cursor < to) {
if (!devmem_is_allowed(pfn)) {
printk(KERN_INFO
"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
current->comm, from, to);
printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx]\n",
current->comm, from, to - 1);
return 0;
}
cursor += PAGE_SIZE;
......@@ -554,12 +552,11 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
size;
if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
printk(KERN_INFO
"%s:%d ioremap_change_attr failed %s "
"for %Lx-%Lx\n",
printk(KERN_INFO "%s:%d ioremap_change_attr failed %s "
"for [mem %#010Lx-%#010Lx]\n",
current->comm, current->pid,
cattr_name(flags),
base, (unsigned long long)(base + size));
base, (unsigned long long)(base + size-1));
return -EINVAL;
}
return 0;
......@@ -591,12 +588,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
flags = lookup_memtype(paddr);
if (want_flags != flags) {
printk(KERN_WARNING
"%s:%d map pfn RAM range req %s for %Lx-%Lx, got %s\n",
printk(KERN_WARNING "%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
current->comm, current->pid,
cattr_name(want_flags),
(unsigned long long)paddr,
(unsigned long long)(paddr + size),
(unsigned long long)(paddr + size - 1),
cattr_name(flags));
*vma_prot = __pgprot((pgprot_val(*vma_prot) &
(~_PAGE_CACHE_MASK)) |
......@@ -614,11 +610,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
!is_new_memtype_allowed(paddr, size, want_flags, flags)) {
free_memtype(paddr, paddr + size);
printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
" for %Lx-%Lx, got %s\n",
" for [mem %#010Lx-%#010Lx], got %s\n",
current->comm, current->pid,
cattr_name(want_flags),
(unsigned long long)paddr,
(unsigned long long)(paddr + size),
(unsigned long long)(paddr + size - 1),
cattr_name(flags));
return -EINVAL;
}
......
......@@ -176,8 +176,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
return;
}
printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
start, end);
printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",
node, pxm,
(unsigned long long) start, (unsigned long long) end - 1);
}
void __init acpi_numa_arch_fixup(void) {}
......
......@@ -592,11 +592,9 @@ static ssize_t print_nodes_state(enum node_states state, char *buf)
{
int n;
n = nodelist_scnprintf(buf, PAGE_SIZE, node_states[state]);
if (n > 0 && PAGE_SIZE > n + 1) {
*(buf + n++) = '\n';
*(buf + n++) = '\0';
}
n = nodelist_scnprintf(buf, PAGE_SIZE-2, node_states[state]);
buf[n++] = '\n';
buf[n] = '\0';
return n;
}
......
......@@ -50,6 +50,19 @@ config LEDS_LM3530
controlled manually or using PWM input or using ambient
light automatically.
config LEDS_LM3533
tristate "LED support for LM3533"
depends on LEDS_CLASS
depends on MFD_LM3533
help
This option enables support for the LEDs on National Semiconductor /
TI LM3533 Lighting Power chips.
The LEDs can be controlled directly, through PWM input, or by the
ambient-light-sensor interface. The chip supports
hardware-accelerated blinking with maximum on and off periods of 9.8
and 77 seconds respectively.
config LEDS_LOCOMO
tristate "LED Support for Locomo device"
depends on LEDS_CLASS
......@@ -259,6 +272,14 @@ config LEDS_DA903X
This option enables support for on-chip LED drivers found
on Dialog Semiconductor DA9030/DA9034 PMICs.
config LEDS_DA9052
tristate "Dialog DA9052/DA9053 LEDS"
depends on LEDS_CLASS
depends on PMIC_DA9052
help
This option enables support for on-chip LED drivers found
on Dialog Semiconductor DA9052-BC and DA9053-AA/Bx PMICs.
config LEDS_DAC124S085
tristate "LED Support for DAC124S085 SPI DAC"
depends on LEDS_CLASS
......@@ -471,4 +492,12 @@ config LEDS_TRIGGER_DEFAULT_ON
comment "iptables trigger is under Netfilter config (LED target)"
depends on LEDS_TRIGGERS
config LEDS_TRIGGER_TRANSIENT
tristate "LED Transient Trigger"
depends on LEDS_TRIGGERS
help
This allows one time activation of a transient state on
GPIO/PWM based hadrware.
If unsure, say Y.
endif # NEW_LEDS
......@@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o
obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
......@@ -31,6 +32,7 @@ obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
obj-$(CONFIG_LEDS_PCA9633) += leds-pca9633.o
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o
obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
......@@ -56,3 +58,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
......@@ -44,23 +44,18 @@ static ssize_t led_brightness_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
unsigned long state;
ssize_t ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (isspace(*after))
count++;
ret = kstrtoul(buf, 10, &state);
if (ret)
return ret;
if (count == size) {
ret = count;
if (state == LED_OFF)
led_trigger_remove(led_cdev);
led_set_brightness(led_cdev, state);
if (state == LED_OFF)
led_trigger_remove(led_cdev);
led_set_brightness(led_cdev, state);
}
return ret;
return size;
}
static ssize_t led_max_brightness_show(struct device *dev,
......
/*
* LED Driver for Dialog DA9052 PMICs.
*
* Copyright(c) 2012 Dialog Semiconductor Ltd.
*
* Author: David Dajun Chen <dchen@diasemi.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/mfd/da9052/reg.h>
#include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/pdata.h>
#define DA9052_OPENDRAIN_OUTPUT 2
#define DA9052_SET_HIGH_LVL_OUTPUT (1 << 3)
#define DA9052_MASK_UPPER_NIBBLE 0xF0
#define DA9052_MASK_LOWER_NIBBLE 0x0F
#define DA9052_NIBBLE_SHIFT 4
#define DA9052_MAX_BRIGHTNESS 0x5f
struct da9052_led {
struct led_classdev cdev;
struct work_struct work;
struct da9052 *da9052;
unsigned char led_index;
unsigned char id;
int brightness;
};
static unsigned char led_reg[] = {
DA9052_LED_CONT_4_REG,
DA9052_LED_CONT_5_REG,
};
static int da9052_set_led_brightness(struct da9052_led *led)
{
u8 val;
int error;
val = (led->brightness & 0x7f) | DA9052_LED_CONT_DIM;
error = da9052_reg_write(led->da9052, led_reg[led->led_index], val);
if (error < 0)
dev_err(led->da9052->dev, "Failed to set led brightness, %d\n",
error);
return error;
}
static void da9052_led_work(struct work_struct *work)
{
struct da9052_led *led = container_of(work, struct da9052_led, work);
da9052_set_led_brightness(led);
}
static void da9052_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct da9052_led *led;
led = container_of(led_cdev, struct da9052_led, cdev);
led->brightness = value;
schedule_work(&led->work);
}
static int da9052_configure_leds(struct da9052 *da9052)
{
int error;
unsigned char register_value = DA9052_OPENDRAIN_OUTPUT
| DA9052_SET_HIGH_LVL_OUTPUT;
error = da9052_reg_update(da9052, DA9052_GPIO_14_15_REG,
DA9052_MASK_LOWER_NIBBLE,
register_value);
if (error < 0) {
dev_err(da9052->dev, "Failed to write GPIO 14-15 reg, %d\n",
error);
return error;
}
error = da9052_reg_update(da9052, DA9052_GPIO_14_15_REG,
DA9052_MASK_UPPER_NIBBLE,
register_value << DA9052_NIBBLE_SHIFT);
if (error < 0)
dev_err(da9052->dev, "Failed to write GPIO 14-15 reg, %d\n",
error);
return error;
}
static int __devinit da9052_led_probe(struct platform_device *pdev)
{
struct da9052_pdata *pdata;
struct da9052 *da9052;
struct led_platform_data *pled;
struct da9052_led *led = NULL;
int error = -ENODEV;
int i;
da9052 = dev_get_drvdata(pdev->dev.parent);
pdata = da9052->dev->platform_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data\n");
goto err;
}
pled = pdata->pled;
if (pled == NULL) {
dev_err(&pdev->dev, "No platform data for LED\n");
goto err;
}
led = devm_kzalloc(&pdev->dev,
sizeof(struct da9052_led) * pled->num_leds,
GFP_KERNEL);
if (led == NULL) {
dev_err(&pdev->dev, "Failed to alloc memory\n");
error = -ENOMEM;
goto err;
}
for (i = 0; i < pled->num_leds; i++) {
led[i].cdev.name = pled->leds[i].name;
led[i].cdev.brightness_set = da9052_led_set;
led[i].cdev.brightness = LED_OFF;
led[i].cdev.max_brightness = DA9052_MAX_BRIGHTNESS;
led[i].brightness = LED_OFF;
led[i].led_index = pled->leds[i].flags;
led[i].da9052 = dev_get_drvdata(pdev->dev.parent);
INIT_WORK(&led[i].work, da9052_led_work);
error = led_classdev_register(pdev->dev.parent, &led[i].cdev);
if (error) {
dev_err(&pdev->dev, "Failed to register led %d\n",
led[i].led_index);
goto err_register;
}
error = da9052_set_led_brightness(&led[i]);
if (error) {
dev_err(&pdev->dev, "Unable to init led %d\n",
led[i].led_index);
continue;
}
}
error = da9052_configure_leds(led->da9052);
if (error) {
dev_err(&pdev->dev, "Failed to configure GPIO LED%d\n", error);
goto err_register;
}
platform_set_drvdata(pdev, led);
return 0;
err_register:
for (i = i - 1; i >= 0; i--) {
led_classdev_unregister(&led[i].cdev);
cancel_work_sync(&led[i].work);
}
err:
return error;
}
static int __devexit da9052_led_remove(struct platform_device *pdev)
{
struct da9052_led *led = platform_get_drvdata(pdev);
struct da9052_pdata *pdata;
struct da9052 *da9052;
struct led_platform_data *pled;
int i;
da9052 = dev_get_drvdata(pdev->dev.parent);
pdata = da9052->dev->platform_data;
pled = pdata->pled;
for (i = 0; i < pled->num_leds; i++) {
led[i].brightness = 0;
da9052_set_led_brightness(&led[i]);
led_classdev_unregister(&led[i].cdev);
cancel_work_sync(&led[i].work);
}
return 0;
}
static struct platform_driver da9052_led_driver = {
.driver = {
.name = "da9052-leds",
.owner = THIS_MODULE,
},
.probe = da9052_led_probe,
.remove = __devexit_p(da9052_led_remove),
};
module_platform_driver(da9052_led_driver);
MODULE_AUTHOR("Dialog Semiconductor Ltd <dchen@diasemi.com>");
MODULE_DESCRIPTION("LED driver for Dialog DA9052 PMIC");
MODULE_LICENSE("GPL");
......@@ -113,6 +113,18 @@ struct lm3530_data {
bool enable;
};
/*
* struct lm3530_als_data
* @config : value of ALS configuration register
* @imp_sel : value of ALS resistor select register
* @zone : values of ALS ZB(Zone Boundary) registers
*/
struct lm3530_als_data {
u8 config;
u8 imp_sel;
u8 zones[LM3530_ALS_ZB_MAX];
};
static const u8 lm3530_reg[LM3530_REG_MAX] = {
LM3530_GEN_CONFIG,
LM3530_ALS_CONFIG,
......@@ -141,29 +153,65 @@ static int lm3530_get_mode_from_str(const char *str)
return -1;
}
static void lm3530_als_configure(struct lm3530_platform_data *pdata,
struct lm3530_als_data *als)
{
int i;
u32 als_vmin, als_vmax, als_vstep;
if (pdata->als_vmax == 0) {
pdata->als_vmin = 0;
pdata->als_vmax = LM3530_ALS_WINDOW_mV;
}
als_vmin = pdata->als_vmin;
als_vmax = pdata->als_vmax;
if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
pdata->als_vmax = als_vmax = als_vmin + LM3530_ALS_WINDOW_mV;
/* n zone boundary makes n+1 zones */
als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
als->zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
als->config =
(pdata->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
(LM3530_ENABLE_ALS) |
(pdata->als_input_mode << LM3530_ALS_SEL_SHIFT);
als->imp_sel =
(pdata->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
(pdata->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
}
static int lm3530_init_registers(struct lm3530_data *drvdata)
{
int ret = 0;
int i;
u8 gen_config;
u8 als_config = 0;
u8 brt_ramp;
u8 als_imp_sel = 0;
u8 brightness;
u8 reg_val[LM3530_REG_MAX];
u8 zones[LM3530_ALS_ZB_MAX];
u32 als_vmin, als_vmax, als_vstep;
struct lm3530_platform_data *pdata = drvdata->pdata;
struct i2c_client *client = drvdata->client;
struct lm3530_pwm_data *pwm = &pdata->pwm_data;
struct lm3530_als_data als;
memset(&als, 0, sizeof(struct lm3530_als_data));
gen_config = (pdata->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) |
((pdata->max_current & 7) << LM3530_MAX_CURR_SHIFT);
switch (drvdata->mode) {
case LM3530_BL_MODE_MANUAL:
gen_config |= LM3530_ENABLE_I2C;
break;
case LM3530_BL_MODE_ALS:
gen_config |= LM3530_ENABLE_I2C;
lm3530_als_configure(pdata, &als);
break;
case LM3530_BL_MODE_PWM:
gen_config |= LM3530_ENABLE_PWM | LM3530_ENABLE_PWM_SIMPLE |
......@@ -171,38 +219,6 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
break;
}
if (drvdata->mode == LM3530_BL_MODE_ALS) {
if (pdata->als_vmax == 0) {
pdata->als_vmin = 0;
pdata->als_vmax = LM3530_ALS_WINDOW_mV;
}
als_vmin = pdata->als_vmin;
als_vmax = pdata->als_vmax;
if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
pdata->als_vmax = als_vmax =
als_vmin + LM3530_ALS_WINDOW_mV;
/* n zone boundary makes n+1 zones */
als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
als_vstep + (i * als_vstep)) * LED_FULL)
/ 1000;
als_config =
(pdata->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
(LM3530_ENABLE_ALS) |
(pdata->als_input_mode << LM3530_ALS_SEL_SHIFT);
als_imp_sel =
(pdata->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
(pdata->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
}
brt_ramp = (pdata->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) |
(pdata->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT);
......@@ -215,14 +231,14 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
brightness = drvdata->led_dev.max_brightness;
reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */
reg_val[1] = als_config; /* LM3530_ALS_CONFIG */
reg_val[1] = als.config; /* LM3530_ALS_CONFIG */
reg_val[2] = brt_ramp; /* LM3530_BRT_RAMP_RATE */
reg_val[3] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */
reg_val[3] = als.imp_sel; /* LM3530_ALS_IMP_SELECT */
reg_val[4] = brightness; /* LM3530_BRT_CTRL_REG */
reg_val[5] = zones[0]; /* LM3530_ALS_ZB0_REG */
reg_val[6] = zones[1]; /* LM3530_ALS_ZB1_REG */
reg_val[7] = zones[2]; /* LM3530_ALS_ZB2_REG */
reg_val[8] = zones[3]; /* LM3530_ALS_ZB3_REG */
reg_val[5] = als.zones[0]; /* LM3530_ALS_ZB0_REG */
reg_val[6] = als.zones[1]; /* LM3530_ALS_ZB1_REG */
reg_val[7] = als.zones[2]; /* LM3530_ALS_ZB2_REG */
reg_val[8] = als.zones[3]; /* LM3530_ALS_ZB3_REG */
reg_val[9] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */
reg_val[10] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */
reg_val[11] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */
......
This diff is collapsed.
......@@ -193,9 +193,14 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
/* move current engine to direct mode and remember the state */
ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
if (ret)
return ret;
/* Mode change requires min 500 us delay. 1 - 2 ms with margin */
usleep_range(1000, 2000);
ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode);
ret = lp5521_read(client, LP5521_REG_OP_MODE, &mode);
if (ret)
return ret;
/* For loading, all the engines to load mode */
lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
......@@ -211,8 +216,7 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
LP5521_PROG_MEM_SIZE,
pattern);
ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode);
return ret;
return lp5521_write(client, LP5521_REG_OP_MODE, mode);
}
static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr)
......@@ -785,7 +789,7 @@ static int __devinit lp5521_probe(struct i2c_client *client,
* LP5521_REG_ENABLE register will not have any effect - strange!
*/
ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
if (buf != LP5521_REG_R_CURR_DEFAULT) {
if (ret || buf != LP5521_REG_R_CURR_DEFAULT) {
dev_err(&client->dev, "error in resetting chip\n");
goto fail2;
}
......
......@@ -280,7 +280,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
return -EINVAL;
}
led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
if (led == NULL) {
dev_err(&pdev->dev, "failed to alloc memory\n");
return -ENOMEM;
......
......@@ -101,11 +101,16 @@ static const struct i2c_device_id pca955x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca955x_id);
struct pca955x_led {
struct pca955x {
struct mutex lock;
struct pca955x_led *leds;
struct pca955x_chipdef *chipdef;
struct i2c_client *client;
};
struct pca955x_led {
struct pca955x *pca955x;
struct work_struct work;
spinlock_t lock;
enum led_brightness brightness;
struct led_classdev led_cdev;
int led_num; /* 0 .. 15 potentially */
......@@ -140,7 +145,7 @@ static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state)
*/
static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
struct pca955x *pca955x = i2c_get_clientdata(client);
i2c_smbus_write_byte_data(client,
pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
......@@ -156,7 +161,7 @@ static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
*/
static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
struct pca955x *pca955x = i2c_get_clientdata(client);
i2c_smbus_write_byte_data(client,
pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
......@@ -169,7 +174,7 @@ static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
*/
static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
struct pca955x *pca955x = i2c_get_clientdata(client);
i2c_smbus_write_byte_data(client,
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
......@@ -182,7 +187,7 @@ static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
*/
static u8 pca955x_read_ls(struct i2c_client *client, int n)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
struct pca955x *pca955x = i2c_get_clientdata(client);
return (u8) i2c_smbus_read_byte_data(client,
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
......@@ -190,18 +195,23 @@ static u8 pca955x_read_ls(struct i2c_client *client, int n)
static void pca955x_led_work(struct work_struct *work)
{
struct pca955x_led *pca955x;
struct pca955x_led *pca955x_led;
struct pca955x *pca955x;
u8 ls;
int chip_ls; /* which LSx to use (0-3 potentially) */
int ls_led; /* which set of bits within LSx to use (0-3) */
pca955x = container_of(work, struct pca955x_led, work);
chip_ls = pca955x->led_num / 4;
ls_led = pca955x->led_num % 4;
pca955x_led = container_of(work, struct pca955x_led, work);
pca955x = pca955x_led->pca955x;
chip_ls = pca955x_led->led_num / 4;
ls_led = pca955x_led->led_num % 4;
mutex_lock(&pca955x->lock);
ls = pca955x_read_ls(pca955x->client, chip_ls);
switch (pca955x->brightness) {
switch (pca955x_led->brightness) {
case LED_FULL:
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
break;
......@@ -219,12 +229,15 @@ static void pca955x_led_work(struct work_struct *work)
* OFF, HALF, or FULL. But, this is probably better than
* just turning off for all other values.
*/
pca955x_write_pwm(pca955x->client, 1, 255-pca955x->brightness);
pca955x_write_pwm(pca955x->client, 1,
255 - pca955x_led->brightness);
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
break;
}
pca955x_write_ls(pca955x->client, chip_ls, ls);
mutex_unlock(&pca955x->lock);
}
static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
......@@ -233,7 +246,6 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
spin_lock(&pca955x->lock);
pca955x->brightness = value;
/*
......@@ -241,14 +253,13 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
* can sleep.
*/
schedule_work(&pca955x->work);
spin_unlock(&pca955x->lock);
}
static int __devinit pca955x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca955x_led *pca955x;
struct pca955x *pca955x;
struct pca955x_led *pca955x_led;
struct pca955x_chipdef *chip;
struct i2c_adapter *adapter;
struct led_platform_data *pdata;
......@@ -282,39 +293,48 @@ static int __devinit pca955x_probe(struct i2c_client *client,
}
}
pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL);
pca955x = kzalloc(sizeof(*pca955x), GFP_KERNEL);
if (!pca955x)
return -ENOMEM;
pca955x->leds = kzalloc(sizeof(*pca955x_led) * chip->bits, GFP_KERNEL);
if (!pca955x->leds) {
err = -ENOMEM;
goto exit_nomem;
}
i2c_set_clientdata(client, pca955x);
mutex_init(&pca955x->lock);
pca955x->client = client;
pca955x->chipdef = chip;
for (i = 0; i < chip->bits; i++) {
pca955x[i].chipdef = chip;
pca955x[i].client = client;
pca955x[i].led_num = i;
pca955x_led = &pca955x->leds[i];
pca955x_led->led_num = i;
pca955x_led->pca955x = pca955x;
/* Platform data can specify LED names and default triggers */
if (pdata) {
if (pdata->leds[i].name)
snprintf(pca955x[i].name,
sizeof(pca955x[i].name), "pca955x:%s",
pdata->leds[i].name);
snprintf(pca955x_led->name,
sizeof(pca955x_led->name), "pca955x:%s",
pdata->leds[i].name);
if (pdata->leds[i].default_trigger)
pca955x[i].led_cdev.default_trigger =
pca955x_led->led_cdev.default_trigger =
pdata->leds[i].default_trigger;
} else {
snprintf(pca955x[i].name, sizeof(pca955x[i].name),
snprintf(pca955x_led->name, sizeof(pca955x_led->name),
"pca955x:%d", i);
}
spin_lock_init(&pca955x[i].lock);
pca955x[i].led_cdev.name = pca955x[i].name;
pca955x[i].led_cdev.brightness_set = pca955x_led_set;
pca955x_led->led_cdev.name = pca955x_led->name;
pca955x_led->led_cdev.brightness_set = pca955x_led_set;
INIT_WORK(&pca955x[i].work, pca955x_led_work);
INIT_WORK(&pca955x_led->work, pca955x_led_work);
err = led_classdev_register(&client->dev, &pca955x[i].led_cdev);
err = led_classdev_register(&client->dev,
&pca955x_led->led_cdev);
if (err < 0)
goto exit;
}
......@@ -337,10 +357,12 @@ static int __devinit pca955x_probe(struct i2c_client *client,
exit:
while (i--) {
led_classdev_unregister(&pca955x[i].led_cdev);
cancel_work_sync(&pca955x[i].work);
led_classdev_unregister(&pca955x->leds[i].led_cdev);
cancel_work_sync(&pca955x->leds[i].work);
}
kfree(pca955x->leds);
exit_nomem:
kfree(pca955x);
return err;
......@@ -348,14 +370,15 @@ static int __devinit pca955x_probe(struct i2c_client *client,
static int __devexit pca955x_remove(struct i2c_client *client)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
struct pca955x *pca955x = i2c_get_clientdata(client);
int i;
for (i = 0; i < pca955x->chipdef->bits; i++) {
led_classdev_unregister(&pca955x[i].led_cdev);
cancel_work_sync(&pca955x[i].work);
led_classdev_unregister(&pca955x->leds[i].led_cdev);
cancel_work_sync(&pca955x->leds[i].work);
}
kfree(pca955x->leds);
kfree(pca955x);
return 0;
......
......@@ -120,6 +120,7 @@ static void bl_trig_activate(struct led_classdev *led)
ret = fb_register_client(&n->notifier);
if (ret)
dev_err(led->dev, "unable to register backlight trigger\n");
led->activated = true;
return;
......@@ -133,10 +134,11 @@ static void bl_trig_deactivate(struct led_classdev *led)
struct bl_trig_notifier *n =
(struct bl_trig_notifier *) led->trigger_data;
if (n) {
if (led->activated) {
device_remove_file(led->dev, &dev_attr_inverted);
fb_unregister_client(&n->notifier);
kfree(n);
led->activated = false;
}
}
......
......@@ -200,6 +200,7 @@ static void gpio_trig_activate(struct led_classdev *led)
gpio_data->led = led;
led->trigger_data = gpio_data;
INIT_WORK(&gpio_data->work, gpio_trig_work);
led->activated = true;
return;
......@@ -217,7 +218,7 @@ static void gpio_trig_deactivate(struct led_classdev *led)
{
struct gpio_trig_data *gpio_data = led->trigger_data;
if (gpio_data) {
if (led->activated) {
device_remove_file(led->dev, &dev_attr_gpio);
device_remove_file(led->dev, &dev_attr_inverted);
device_remove_file(led->dev, &dev_attr_desired_brightness);
......@@ -225,6 +226,7 @@ static void gpio_trig_deactivate(struct led_classdev *led)
if (gpio_data->gpio != 0)
free_irq(gpio_to_irq(gpio_data->gpio), led);
kfree(gpio_data);
led->activated = false;
}
}
......
......@@ -18,6 +18,7 @@
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/leds.h>
#include <linux/reboot.h>
#include "leds.h"
struct heartbeat_trig_data {
......@@ -83,15 +84,17 @@ static void heartbeat_trig_activate(struct led_classdev *led_cdev)
led_heartbeat_function, (unsigned long) led_cdev);
heartbeat_data->phase = 0;
led_heartbeat_function(heartbeat_data->timer.data);
led_cdev->activated = true;
}
static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
{
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
if (heartbeat_data) {
if (led_cdev->activated) {
del_timer_sync(&heartbeat_data->timer);
kfree(heartbeat_data);
led_cdev->activated = false;
}
}
......@@ -101,13 +104,38 @@ static struct led_trigger heartbeat_led_trigger = {
.deactivate = heartbeat_trig_deactivate,
};
static int heartbeat_reboot_notifier(struct notifier_block *nb,
unsigned long code, void *unused)
{
led_trigger_unregister(&heartbeat_led_trigger);
return NOTIFY_DONE;
}
static struct notifier_block heartbeat_reboot_nb = {
.notifier_call = heartbeat_reboot_notifier,
};
static struct notifier_block heartbeat_panic_nb = {
.notifier_call = heartbeat_reboot_notifier,
};
static int __init heartbeat_trig_init(void)
{
return led_trigger_register(&heartbeat_led_trigger);
int rc = led_trigger_register(&heartbeat_led_trigger);
if (!rc) {
atomic_notifier_chain_register(&panic_notifier_list,
&heartbeat_panic_nb);
register_reboot_notifier(&heartbeat_reboot_nb);
}
return rc;
}
static void __exit heartbeat_trig_exit(void)
{
unregister_reboot_notifier(&heartbeat_reboot_nb);
atomic_notifier_chain_unregister(&panic_notifier_list,
&heartbeat_panic_nb);
led_trigger_unregister(&heartbeat_led_trigger);
}
......
......@@ -31,21 +31,17 @@ static ssize_t led_delay_on_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
int ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (isspace(*after))
count++;
if (count == size) {
led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
led_cdev->blink_delay_on = state;
ret = count;
}
unsigned long state;
ssize_t ret = -EINVAL;
ret = kstrtoul(buf, 10, &state);
if (ret)
return ret;
return ret;
led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
led_cdev->blink_delay_on = state;
return size;
}
static ssize_t led_delay_off_show(struct device *dev,
......@@ -60,21 +56,17 @@ static ssize_t led_delay_off_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
int ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (isspace(*after))
count++;
if (count == size) {
led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
led_cdev->blink_delay_off = state;
ret = count;
}
unsigned long state;
ssize_t ret = -EINVAL;
return ret;
ret = kstrtoul(buf, 10, &state);
if (ret)
return ret;
led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
led_cdev->blink_delay_off = state;
return size;
}
static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
......@@ -95,8 +87,7 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
led_blink_set(led_cdev, &led_cdev->blink_delay_on,
&led_cdev->blink_delay_off);
led_cdev->trigger_data = (void *)1;
led_cdev->activated = true;
return;
......@@ -106,9 +97,10 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
static void timer_trig_deactivate(struct led_classdev *led_cdev)
{
if (led_cdev->trigger_data) {
if (led_cdev->activated) {
device_remove_file(led_cdev->dev, &dev_attr_delay_on);
device_remove_file(led_cdev->dev, &dev_attr_delay_off);
led_cdev->activated = false;
}
/* Stop blinking */
......
/*
* LED Kernel Transient Trigger
*
* Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
*
* Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
* ledtrig-heartbeat.c
* Design and use-case input from Jonas Bonn <jonas@southpole.se> and
* Neil Brown <neilb@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
/*
* Transient trigger allows one shot timer activation. Please refer to
* Documentation/leds/ledtrig-transient.txt for details
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/leds.h>
#include "leds.h"
struct transient_trig_data {
int activate;
int state;
int restore_state;
unsigned long duration;
struct timer_list timer;
};
static void transient_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (struct led_classdev *) data;
struct transient_trig_data *transient_data = led_cdev->trigger_data;
transient_data->activate = 0;
led_set_brightness(led_cdev, transient_data->restore_state);
}
static ssize_t transient_activate_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
return sprintf(buf, "%d\n", transient_data->activate);
}
static ssize_t transient_activate_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
unsigned long state;
ssize_t ret;
ret = kstrtoul(buf, 10, &state);
if (ret)
return ret;
if (state != 1 && state != 0)
return -EINVAL;
/* cancel the running timer */
if (state == 0 && transient_data->activate == 1) {
del_timer(&transient_data->timer);
transient_data->activate = state;
led_set_brightness(led_cdev, transient_data->restore_state);
return size;
}
/* start timer if there is no active timer */
if (state == 1 && transient_data->activate == 0 &&
transient_data->duration != 0) {
transient_data->activate = state;
led_set_brightness(led_cdev, transient_data->state);
transient_data->restore_state =
(transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
mod_timer(&transient_data->timer,
jiffies + transient_data->duration);
}
/* state == 0 && transient_data->activate == 0
timer is not active - just return */
/* state == 1 && transient_data->activate == 1
timer is already active - just return */
return size;
}
static ssize_t transient_duration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
return sprintf(buf, "%lu\n", transient_data->duration);
}
static ssize_t transient_duration_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
unsigned long state;
ssize_t ret;
ret = kstrtoul(buf, 10, &state);
if (ret)
return ret;
transient_data->duration = state;
return size;
}
static ssize_t transient_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
int state;
state = (transient_data->state == LED_FULL) ? 1 : 0;
return sprintf(buf, "%d\n", state);
}
static ssize_t transient_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
unsigned long state;
ssize_t ret;
ret = kstrtoul(buf, 10, &state);
if (ret)
return ret;
if (state != 1 && state != 0)
return -EINVAL;
transient_data->state = (state == 1) ? LED_FULL : LED_OFF;
return size;
}
static DEVICE_ATTR(activate, 0644, transient_activate_show,
transient_activate_store);
static DEVICE_ATTR(duration, 0644, transient_duration_show,
transient_duration_store);
static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);
static void transient_trig_activate(struct led_classdev *led_cdev)
{
int rc;
struct transient_trig_data *tdata;
tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
if (!tdata) {
dev_err(led_cdev->dev,
"unable to allocate transient trigger\n");
return;
}
led_cdev->trigger_data = tdata;
rc = device_create_file(led_cdev->dev, &dev_attr_activate);
if (rc)
goto err_out;
rc = device_create_file(led_cdev->dev, &dev_attr_duration);
if (rc)
goto err_out_duration;
rc = device_create_file(led_cdev->dev, &dev_attr_state);
if (rc)
goto err_out_state;
setup_timer(&tdata->timer, transient_timer_function,
(unsigned long) led_cdev);
led_cdev->activated = true;
return;
err_out_state:
device_remove_file(led_cdev->dev, &dev_attr_duration);
err_out_duration:
device_remove_file(led_cdev->dev, &dev_attr_activate);
err_out:
dev_err(led_cdev->dev, "unable to register transient trigger\n");
led_cdev->trigger_data = NULL;
kfree(tdata);
}
static void transient_trig_deactivate(struct led_classdev *led_cdev)
{
struct transient_trig_data *transient_data = led_cdev->trigger_data;
if (led_cdev->activated) {
del_timer_sync(&transient_data->timer);
led_set_brightness(led_cdev, transient_data->restore_state);
device_remove_file(led_cdev->dev, &dev_attr_activate);
device_remove_file(led_cdev->dev, &dev_attr_duration);
device_remove_file(led_cdev->dev, &dev_attr_state);
led_cdev->trigger_data = NULL;
led_cdev->activated = false;
kfree(transient_data);
}
}
static struct led_trigger transient_trigger = {
.name = "transient",
.activate = transient_trig_activate,
.deactivate = transient_trig_deactivate,
};
static int __init transient_trig_init(void)
{
return led_trigger_register(&transient_trigger);
}
static void __exit transient_trig_exit(void)
{
led_trigger_unregister(&transient_trigger);
}
module_init(transient_trig_init);
module_exit(transient_trig_exit);
MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
MODULE_DESCRIPTION("Transient LED trigger");
MODULE_LICENSE("GPL");
......@@ -1104,6 +1104,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
mutex_init(&dev->mutex);
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
dev->backlight_dev = backlight_device_register("toshiba",
......
......@@ -620,27 +620,6 @@ config RTC_DRV_MSM6242
This driver can also be built as a module. If so, the module
will be called rtc-msm6242.
config RTC_DRV_IMXDI
tristate "Freescale IMX DryIce Real Time Clock"
depends on ARCH_MX25
depends on RTC_CLASS
help
Support for Freescale IMX DryIce RTC
This driver can also be built as a module, if so, the module
will be called "rtc-imxdi".
config RTC_MXC
tristate "Freescale MXC Real Time Clock"
depends on ARCH_MXC
depends on RTC_CLASS
help
If you say yes here you get support for the Freescale MXC
RTC module.
This driver can also be built as a module, if so, the module
will be called "rtc-mxc".
config RTC_DRV_BQ4802
tristate "TI BQ4802"
help
......@@ -738,6 +717,16 @@ config RTC_DRV_DAVINCI
This driver can also be built as a module. If so, the module
will be called rtc-davinci.
config RTC_DRV_IMXDI
tristate "Freescale IMX DryIce Real Time Clock"
depends on SOC_IMX25
depends on RTC_CLASS
help
Support for Freescale IMX DryIce RTC
This driver can also be built as a module, if so, the module
will be called "rtc-imxdi".
config RTC_DRV_OMAP
tristate "TI OMAP1"
depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
......@@ -1087,4 +1076,15 @@ config RTC_DRV_LOONGSON1
This driver can also be built as a module. If so, the module
will be called rtc-ls1x.
config RTC_DRV_MXC
tristate "Freescale MXC Real Time Clock"
depends on ARCH_MXC
depends on RTC_CLASS
help
If you say yes here you get support for the Freescale MXC
RTC module.
This driver can also be built as a module, if so, the module
will be called "rtc-mxc".
endif # RTC_CLASS
......@@ -61,7 +61,7 @@ obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
......
......@@ -17,8 +17,7 @@
#include <linux/string.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/rtc/ds1307.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
......@@ -92,7 +91,8 @@ enum ds_type {
# define DS1337_BIT_A2I 0x02
# define DS1337_BIT_A1I 0x01
#define DS1339_REG_ALARM1_SECS 0x07
#define DS1339_REG_TRICKLE 0x10
#define DS13XX_TRICKLE_CHARGER_MAGIC 0xa0
#define RX8025_REG_CTRL1 0x0e
# define RX8025_BIT_2412 0x20
......@@ -124,6 +124,7 @@ struct chip_desc {
unsigned alarm:1;
u16 nvram_offset;
u16 nvram_size;
u16 trickle_charger_reg;
};
static const struct chip_desc chips[last_ds_type] = {
......@@ -140,6 +141,13 @@ static const struct chip_desc chips[last_ds_type] = {
},
[ds_1339] = {
.alarm = 1,
.trickle_charger_reg = 0x10,
},
[ds_1340] = {
.trickle_charger_reg = 0x08,
},
[ds_1388] = {
.trickle_charger_reg = 0x0a,
},
[ds_3231] = {
.alarm = 1,
......@@ -619,6 +627,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
int want_irq = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = client->dev.platform_data;
static const int bbsqi_bitpos[] = {
[ds_1337] = 0,
[ds_1339] = DS1339_BIT_BBSQI,
......@@ -637,7 +646,10 @@ static int __devinit ds1307_probe(struct i2c_client *client,
ds1307->client = client;
ds1307->type = id->driver_data;
ds1307->offset = 0;
if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg)
i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup);
buf = ds1307->regs;
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
......
......@@ -127,7 +127,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = {
.attrs = ep93xx_rtc_attrs,
};
static int __init ep93xx_rtc_probe(struct platform_device *pdev)
static int __devinit ep93xx_rtc_probe(struct platform_device *pdev)
{
struct ep93xx_rtc *ep93xx_rtc;
struct resource *res;
......@@ -174,7 +174,7 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
return err;
}
static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
static int __devexit ep93xx_rtc_remove(struct platform_device *pdev)
{
struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev);
......@@ -186,31 +186,19 @@ static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:ep93xx-rtc");
static struct platform_driver ep93xx_rtc_driver = {
.driver = {
.name = "ep93xx-rtc",
.owner = THIS_MODULE,
},
.remove = __exit_p(ep93xx_rtc_remove),
.probe = ep93xx_rtc_probe,
.remove = __devexit_p(ep93xx_rtc_remove),
};
static int __init ep93xx_rtc_init(void)
{
return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe);
}
static void __exit ep93xx_rtc_exit(void)
{
platform_driver_unregister(&ep93xx_rtc_driver);
}
module_platform_driver(ep93xx_rtc_driver);
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("EP93XX RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
module_init(ep93xx_rtc_init);
module_exit(ep93xx_rtc_exit);
MODULE_ALIAS("platform:ep93xx-rtc");
......@@ -19,6 +19,7 @@
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
/*
* Clock and Power control register offsets
......@@ -386,13 +387,22 @@ static const struct dev_pm_ops lpc32xx_rtc_pm_ops = {
#define LPC32XX_RTC_PM_OPS NULL
#endif
#ifdef CONFIG_OF
static const struct of_device_id lpc32xx_rtc_match[] = {
{ .compatible = "nxp,lpc3220-rtc" },
{ }
};
MODULE_DEVICE_TABLE(of, lpc32xx_rtc_match);
#endif
static struct platform_driver lpc32xx_rtc_driver = {
.probe = lpc32xx_rtc_probe,
.remove = __devexit_p(lpc32xx_rtc_remove),
.driver = {
.name = RTC_NAME,
.owner = THIS_MODULE,
.pm = LPC32XX_RTC_PM_OPS
.pm = LPC32XX_RTC_PM_OPS,
.of_match_table = of_match_ptr(lpc32xx_rtc_match),
},
};
......
......@@ -48,6 +48,7 @@ static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
{
struct spi_device *spi = to_spi_device(dev);
int tmp;
u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
u8 * const data = &buf[1]; /* ptr to first data byte */
......@@ -62,6 +63,30 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
if (tmp < 0)
return tmp;
if (tmp & M41T93_FLAG_OF) {
dev_warn(&spi->dev, "OF bit is set, resetting.\n");
m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
if (tmp < 0) {
return tmp;
} else if (tmp & M41T93_FLAG_OF) {
/* OF cannot be immediately reset: oscillator has to be
* restarted. */
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
dev_warn(&spi->dev,
"OF bit is still set, kickstarting clock.\n");
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
reset_osc &= ~M41T93_FLAG_ST;
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
}
}
data[M41T93_REG_SSEC] = 0;
data[M41T93_REG_ST_SEC] = bin2bcd(tm->tm_sec);
data[M41T93_REG_MIN] = bin2bcd(tm->tm_min);
......@@ -89,10 +114,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
1. halt bit (HT) is set: the clock is running but update of readout
registers has been disabled due to power failure. This is normal
case after poweron. Time is valid after resetting HT bit.
2. oscillator fail bit (OF) is set. Oscillator has be stopped and
time is invalid:
a) OF can be immeditely reset.
b) OF cannot be immediately reset: oscillator has to be restarted.
2. oscillator fail bit (OF) is set: time is invalid.
*/
tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
if (tmp < 0)
......@@ -110,21 +132,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
if (tmp & M41T93_FLAG_OF) {
ret = -EINVAL;
dev_warn(&spi->dev, "OF bit is set, resetting.\n");
m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
if (tmp < 0)
return tmp;
else if (tmp & M41T93_FLAG_OF) {
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
dev_warn(&spi->dev,
"OF bit is still set, kickstarting clock.\n");
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
reset_osc &= ~M41T93_FLAG_ST;
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
}
dev_warn(&spi->dev, "OF bit is set, write time to restart.\n");
}
if (tmp & M41T93_FLAG_BL)
......
......@@ -64,6 +64,7 @@ struct pcf8563 {
* 1970...2069.
*/
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
int voltage_low; /* incicates if a low_voltage was detected */
};
/*
......@@ -86,9 +87,11 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
pcf8563->voltage_low = 1;
dev_info(&client->dev,
"low voltage detected, date/time is not reliable.\n");
}
dev_dbg(&client->dev,
"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
......@@ -173,6 +176,44 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0;
}
#ifdef CONFIG_RTC_INTF_DEV
static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev));
struct rtc_time tm;
switch (cmd) {
case RTC_VL_READ:
if (pcf8563->voltage_low)
dev_info(dev, "low voltage detected, date/time is not reliable.\n");
if (copy_to_user((void __user *)arg, &pcf8563->voltage_low,
sizeof(int)))
return -EFAULT;
return 0;
case RTC_VL_CLR:
/*
* Clear the VL bit in the seconds register in case
* the time has not been set already (which would
* have cleared it). This does not really matter
* because of the cached voltage_low value but do it
* anyway for consistency.
*/
if (pcf8563_get_datetime(to_i2c_client(dev), &tm))
pcf8563_set_datetime(to_i2c_client(dev), &tm);
/* Clear the cached value. */
pcf8563->voltage_low = 0;
return 0;
default:
return -ENOIOCTLCMD;
}
}
#else
#define pcf8563_rtc_ioctl NULL
#endif
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return pcf8563_get_datetime(to_i2c_client(dev), tm);
......@@ -184,6 +225,7 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
}
static const struct rtc_class_ops pcf8563_rtc_ops = {
.ioctl = pcf8563_rtc_ioctl,
.read_time = pcf8563_rtc_read_time,
.set_time = pcf8563_rtc_set_time,
};
......
......@@ -220,17 +220,9 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id)
unsigned long events = 0;
rtcmis = readl(ldata->base + RTC_MIS);
if (rtcmis) {
writel(rtcmis, ldata->base + RTC_ICR);
if (rtcmis & RTC_BIT_AI)
events |= (RTC_AF | RTC_IRQF);
/* Timer interrupt is only available in ST variants */
if ((rtcmis & RTC_BIT_PI) &&
(ldata->hw_designer == AMBA_VENDOR_ST))
events |= (RTC_PF | RTC_IRQF);
if (rtcmis & RTC_BIT_AI) {
writel(RTC_BIT_AI, ldata->base + RTC_ICR);
events |= (RTC_AF | RTC_IRQF);
rtc_update_irq(ldata->rtc, 1, events);
return IRQ_HANDLED;
......
......@@ -670,6 +670,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
#define s3c_rtc_resume NULL
#endif
#ifdef CONFIG_OF
static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
[TYPE_S3C2410] = { TYPE_S3C2410 },
[TYPE_S3C2416] = { TYPE_S3C2416 },
......@@ -677,7 +678,6 @@ static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
[TYPE_S3C64XX] = { TYPE_S3C64XX },
};
#ifdef CONFIG_OF
static const struct of_device_id s3c_rtc_dt_match[] = {
{
.compatible = "samsung,s3c2410-rtc",
......
......@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/slab.h>
......@@ -519,6 +520,14 @@ static void spear_rtc_shutdown(struct platform_device *pdev)
clk_disable(config->clk);
}
#ifdef CONFIG_OF
static const struct of_device_id spear_rtc_id_table[] = {
{ .compatible = "st,spear600-rtc" },
{}
};
MODULE_DEVICE_TABLE(of, spear_rtc_id_table);
#endif
static struct platform_driver spear_rtc_driver = {
.probe = spear_rtc_probe,
.remove = __devexit_p(spear_rtc_remove),
......@@ -527,6 +536,7 @@ static struct platform_driver spear_rtc_driver = {
.shutdown = spear_rtc_shutdown,
.driver = {
.name = "rtc-spear",
.of_match_table = of_match_ptr(spear_rtc_id_table),
},
};
......
......@@ -309,7 +309,8 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
struct resource *res;
int ret;
info = kzalloc(sizeof(struct tegra_rtc_info), GFP_KERNEL);
info = devm_kzalloc(&pdev->dev, sizeof(struct tegra_rtc_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
......@@ -317,29 +318,18 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev,
"Unable to allocate resources for device.\n");
ret = -EBUSY;
goto err_free_info;
return -EBUSY;
}
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
dev_err(&pdev->dev,
"Unable to request mem region for device.\n");
ret = -EBUSY;
goto err_free_info;
info->rtc_base = devm_request_and_ioremap(&pdev->dev, res);
if (!info->rtc_base) {
dev_err(&pdev->dev, "Unable to request mem region and grab IOs for device.\n");
return -EBUSY;
}
info->tegra_rtc_irq = platform_get_irq(pdev, 0);
if (info->tegra_rtc_irq <= 0) {
ret = -EBUSY;
goto err_release_mem_region;
}
info->rtc_base = ioremap_nocache(res->start, resource_size(res));
if (!info->rtc_base) {
dev_err(&pdev->dev, "Unable to grab IOs for device.\n");
ret = -EBUSY;
goto err_release_mem_region;
}
if (info->tegra_rtc_irq <= 0)
return -EBUSY;
/* set context info. */
info->pdev = pdev;
......@@ -362,11 +352,12 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Unable to register device (err=%d).\n",
ret);
goto err_iounmap;
return ret;
}
ret = request_irq(info->tegra_rtc_irq, tegra_rtc_irq_handler,
IRQF_TRIGGER_HIGH, "rtc alarm", &pdev->dev);
ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH,
"rtc alarm", &pdev->dev);
if (ret) {
dev_err(&pdev->dev,
"Unable to request interrupt for device (err=%d).\n",
......@@ -380,12 +371,6 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
err_dev_unreg:
rtc_device_unregister(info->rtc_dev);
err_iounmap:
iounmap(info->rtc_base);
err_release_mem_region:
release_mem_region(res->start, resource_size(res));
err_free_info:
kfree(info);
return ret;
}
......@@ -393,17 +378,8 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
static int __devexit tegra_rtc_remove(struct platform_device *pdev)
{
struct tegra_rtc_info *info = platform_get_drvdata(pdev);
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EBUSY;
free_irq(info->tegra_rtc_irq, &pdev->dev);
rtc_device_unregister(info->rtc_dev);
iounmap(info->rtc_base);
release_mem_region(res->start, resource_size(res));
kfree(info);
platform_set_drvdata(pdev, NULL);
......
......@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/falloc.h>
#include <linux/miscdevice.h>
#include <linux/security.h>
#include <linux/mm.h>
......@@ -363,11 +364,12 @@ static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
mutex_lock(&ashmem_mutex);
list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
struct inode *inode = range->asma->file->f_dentry->d_inode;
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE - 1;
loff_t end = (range->pgend + 1) * PAGE_SIZE;
vmtruncate_range(inode, start, end);
do_fallocate(range->asma->file,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
start, end - start);
range->purged = ASHMEM_WAS_PURGED;
lru_del(range);
......
......@@ -184,6 +184,18 @@ config BACKLIGHT_GENERIC
known as the Corgi backlight driver. If you have a Sharp Zaurus
SL-C7xx, SL-Cxx00 or SL-6000x say y.
config BACKLIGHT_LM3533
tristate "Backlight Driver for LM3533"
depends on BACKLIGHT_CLASS_DEVICE
depends on MFD_LM3533
help
Say Y to enable the backlight driver for National Semiconductor / TI
LM3533 Lighting Power chips.
The backlights can be controlled directly, through PWM input, or by
the ambient-light-sensor interface. The chip supports 256 brightness
levels.
config BACKLIGHT_LOCOMO
tristate "Sharp LOCOMO LCD/Backlight Driver"
depends on SHARP_LOCOMO
......
......@@ -21,6 +21,7 @@ obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o
obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
......
......@@ -160,7 +160,7 @@ static ssize_t adp5520_store(struct device *dev, const char *buf,
unsigned long val;
int ret;
ret = strict_strtoul(buf, 10, &val);
ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
......@@ -214,7 +214,7 @@ static ssize_t adp5520_bl_daylight_max_store(struct device *dev,
struct adp5520_bl *data = dev_get_drvdata(dev);
int ret;
ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
ret = kstrtoul(buf, 10, &data->cached_daylight_max);
if (ret < 0)
return ret;
......
......@@ -222,7 +222,8 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
struct led_info *cur_led;
int ret, i;
led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
led = devm_kzalloc(&client->dev, sizeof(*led) * pdata->num_leds,
GFP_KERNEL);
if (led == NULL) {
dev_err(&client->dev, "failed to alloc memory\n");
return -ENOMEM;
......@@ -236,7 +237,7 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
if (ret) {
dev_err(&client->dev, "failed to write\n");
goto err_free;
return ret;
}
for (i = 0; i < pdata->num_leds; ++i) {
......@@ -291,9 +292,6 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
cancel_work_sync(&led[i].work);
}
err_free:
kfree(led);
return ret;
}
......@@ -309,7 +307,6 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
cancel_work_sync(&data->led[i].work);
}
kfree(data->led);
return 0;
}
#else
......@@ -451,7 +448,7 @@ static ssize_t adp8860_store(struct device *dev, const char *buf,
unsigned long val;
int ret;
ret = strict_strtoul(buf, 10, &val);
ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
......@@ -501,7 +498,7 @@ static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct adp8860_bl *data = dev_get_drvdata(dev);
int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
int ret = kstrtoul(buf, 10, &data->cached_daylight_max);
if (ret)
return ret;
......@@ -608,7 +605,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
uint8_t reg_val;
int ret;
ret = strict_strtoul(buf, 10, &val);
ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
......@@ -675,13 +672,13 @@ static int __devinit adp8860_probe(struct i2c_client *client,
return -EINVAL;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
ret = adp8860_read(client, ADP8860_MFDVID, &reg_val);
if (ret < 0)
goto out2;
return ret;
switch (ADP8860_MANID(reg_val)) {
case ADP8863_MANUFID:
......@@ -694,8 +691,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
break;
default:
dev_err(&client->dev, "failed to probe\n");
ret = -ENODEV;
goto out2;
return -ENODEV;
}
/* It's confirmed that the DEVID field is actually a REVID */
......@@ -717,8 +713,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
&client->dev, data, &adp8860_bl_ops, &props);
if (IS_ERR(bl)) {
dev_err(&client->dev, "failed to register backlight\n");
ret = PTR_ERR(bl);
goto out2;
return PTR_ERR(bl);
}
bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
......@@ -756,8 +751,6 @@ static int __devinit adp8860_probe(struct i2c_client *client,
&adp8860_bl_attr_group);
out1:
backlight_device_unregister(bl);
out2:
kfree(data);
return ret;
}
......@@ -776,7 +769,6 @@ static int __devexit adp8860_remove(struct i2c_client *client)
&adp8860_bl_attr_group);
backlight_device_unregister(data->bl);
kfree(data);
return 0;
}
......
......@@ -244,8 +244,8 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
struct led_info *cur_led;
int ret, i;
led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led),
GFP_KERNEL);
if (led == NULL) {
dev_err(&client->dev, "failed to alloc memory\n");
return -ENOMEM;
......@@ -253,17 +253,17 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
if (ret)
goto err_free;
return ret;
ret = adp8870_write(client, ADP8870_ISCT1,
(pdata->led_on_time & 0x3) << 6);
if (ret)
goto err_free;
return ret;
ret = adp8870_write(client, ADP8870_ISCF,
FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
if (ret)
goto err_free;
return ret;
for (i = 0; i < pdata->num_leds; ++i) {
cur_led = &pdata->leds[i];
......@@ -317,9 +317,6 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
cancel_work_sync(&led[i].work);
}
err_free:
kfree(led);
return ret;
}
......@@ -335,7 +332,6 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
cancel_work_sync(&data->led[i].work);
}
kfree(data->led);
return 0;
}
#else
......@@ -572,7 +568,7 @@ static ssize_t adp8870_store(struct device *dev, const char *buf,
unsigned long val;
int ret;
ret = strict_strtoul(buf, 10, &val);
ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
......@@ -652,7 +648,7 @@ static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct adp8870_bl *data = dev_get_drvdata(dev);
int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
int ret = kstrtoul(buf, 10, &data->cached_daylight_max);
if (ret)
return ret;
......@@ -794,7 +790,7 @@ static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
uint8_t reg_val;
int ret;
ret = strict_strtoul(buf, 10, &val);
ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
......@@ -874,7 +870,7 @@ static int __devinit adp8870_probe(struct i2c_client *client,
return -ENODEV;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
......@@ -894,8 +890,7 @@ static int __devinit adp8870_probe(struct i2c_client *client,
&client->dev, data, &adp8870_bl_ops, &props);
if (IS_ERR(bl)) {
dev_err(&client->dev, "failed to register backlight\n");
ret = PTR_ERR(bl);
goto out2;
return PTR_ERR(bl);
}
data->bl = bl;
......@@ -930,8 +925,6 @@ static int __devinit adp8870_probe(struct i2c_client *client,
&adp8870_bl_attr_group);
out1:
backlight_device_unregister(bl);
out2:
kfree(data);
return ret;
}
......@@ -950,7 +943,6 @@ static int __devexit adp8870_remove(struct i2c_client *client)
&adp8870_bl_attr_group);
backlight_device_unregister(data->bl);
kfree(data);
return 0;
}
......
......@@ -482,7 +482,7 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
struct backlight_device *bd = NULL;
struct backlight_properties props;
lcd = kzalloc(sizeof(struct ams369fg06), GFP_KERNEL);
lcd = devm_kzalloc(&spi->dev, sizeof(struct ams369fg06), GFP_KERNEL);
if (!lcd)
return -ENOMEM;
......@@ -492,7 +492,7 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&spi->dev, "spi setup failed.\n");
goto out_free_lcd;
return ret;
}
lcd->spi = spi;
......@@ -501,15 +501,13 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
lcd->lcd_pd = spi->dev.platform_data;
if (!lcd->lcd_pd) {
dev_err(&spi->dev, "platform data is NULL\n");
goto out_free_lcd;
return -EFAULT;
}
ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
&ams369fg06_lcd_ops);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
goto out_free_lcd;
}
if (IS_ERR(ld))
return PTR_ERR(ld);
lcd->ld = ld;
......@@ -547,8 +545,6 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
out_lcd_unregister:
lcd_device_unregister(ld);
out_free_lcd:
kfree(lcd);
return ret;
}
......@@ -559,7 +555,6 @@ static int __devexit ams369fg06_remove(struct spi_device *spi)
ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
backlight_device_unregister(lcd->bd);
lcd_device_unregister(lcd->ld);
kfree(lcd);
return 0;
}
......@@ -619,7 +614,6 @@ static void ams369fg06_shutdown(struct spi_device *spi)
static struct spi_driver ams369fg06_driver = {
.driver = {
.name = "ams369fg06",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ams369fg06_probe,
......
......@@ -16,6 +16,8 @@
* get at the firmware code in order to figure out what it's actually doing.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -25,6 +27,7 @@
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/atomic.h>
#include <linux/apple_bl.h>
static struct backlight_device *apple_backlight_device;
......@@ -39,8 +42,6 @@ struct hw_data {
static const struct hw_data *hw_data;
#define DRIVER "apple_backlight: "
/* Module parameters. */
static int debug;
module_param_named(debug, debug, int, 0644);
......@@ -60,8 +61,7 @@ static int intel_chipset_send_intensity(struct backlight_device *bd)
int intensity = bd->props.brightness;
if (debug)
printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
intensity);
pr_debug("setting brightness to %d\n", intensity);
intel_chipset_set_brightness(intensity);
return 0;
......@@ -76,8 +76,7 @@ static int intel_chipset_get_intensity(struct backlight_device *bd)
intensity = inb(0xb3) >> 4;
if (debug)
printk(KERN_DEBUG DRIVER "read brightness of %d\n",
intensity);
pr_debug("read brightness of %d\n", intensity);
return intensity;
}
......@@ -107,8 +106,7 @@ static int nvidia_chipset_send_intensity(struct backlight_device *bd)
int intensity = bd->props.brightness;
if (debug)
printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
intensity);
pr_debug("setting brightness to %d\n", intensity);
nvidia_chipset_set_brightness(intensity);
return 0;
......@@ -123,8 +121,7 @@ static int nvidia_chipset_get_intensity(struct backlight_device *bd)
intensity = inb(0x52f) >> 4;
if (debug)
printk(KERN_DEBUG DRIVER "read brightness of %d\n",
intensity);
pr_debug("read brightness of %d\n", intensity);
return intensity;
}
......@@ -149,7 +146,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
host = pci_get_bus_and_slot(0, 0);
if (!host) {
printk(KERN_ERR DRIVER "unable to find PCI host\n");
pr_err("unable to find PCI host\n");
return -ENODEV;
}
......@@ -161,7 +158,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
pci_dev_put(host);
if (!hw_data) {
printk(KERN_ERR DRIVER "unknown hardware\n");
pr_err("unknown hardware\n");
return -ENODEV;
}
......
......@@ -5,6 +5,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
......@@ -123,7 +125,7 @@ static ssize_t backlight_store_power(struct device *dev,
rc = -ENXIO;
mutex_lock(&bd->ops_lock);
if (bd->ops) {
pr_debug("backlight: set power to %lu\n", power);
pr_debug("set power to %lu\n", power);
if (bd->props.power != power) {
bd->props.power = power;
backlight_update_status(bd);
......@@ -161,8 +163,7 @@ static ssize_t backlight_store_brightness(struct device *dev,
if (brightness > bd->props.max_brightness)
rc = -EINVAL;
else {
pr_debug("backlight: set brightness to %lu\n",
brightness);
pr_debug("set brightness to %lu\n", brightness);
bd->props.brightness = brightness;
backlight_update_status(bd);
rc = count;
......@@ -378,8 +379,8 @@ static int __init backlight_class_init(void)
{
backlight_class = class_create(THIS_MODULE, "backlight");
if (IS_ERR(backlight_class)) {
printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n",
PTR_ERR(backlight_class));
pr_warn("Unable to create backlight class; errno = %ld\n",
PTR_ERR(backlight_class));
return PTR_ERR(backlight_class);
}
......
......@@ -544,7 +544,7 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
return -EINVAL;
}
lcd = kzalloc(sizeof(struct corgi_lcd), GFP_KERNEL);
lcd = devm_kzalloc(&spi->dev, sizeof(struct corgi_lcd), GFP_KERNEL);
if (!lcd) {
dev_err(&spi->dev, "failed to allocate memory\n");
return -ENOMEM;
......@@ -554,10 +554,9 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
lcd, &corgi_lcd_ops);
if (IS_ERR(lcd->lcd_dev)) {
ret = PTR_ERR(lcd->lcd_dev);
goto err_free_lcd;
}
if (IS_ERR(lcd->lcd_dev))
return PTR_ERR(lcd->lcd_dev);
lcd->power = FB_BLANK_POWERDOWN;
lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
......@@ -591,8 +590,6 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
backlight_device_unregister(lcd->bl_dev);
err_unregister_lcd:
lcd_device_unregister(lcd->lcd_dev);
err_free_lcd:
kfree(lcd);
return ret;
}
......@@ -613,7 +610,6 @@ static int __devexit corgi_lcd_remove(struct spi_device *spi)
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
lcd_device_unregister(lcd->lcd_dev);
kfree(lcd);
return 0;
}
......
......@@ -27,6 +27,8 @@
* Alan Hourihane <alanh-at-tungstengraphics-dot-com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -180,14 +182,13 @@ static int cr_backlight_probe(struct platform_device *pdev)
lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
CRVML_DEVICE_LPC, NULL);
if (!lpc_dev) {
printk("INTEL CARILLO RANCH LPC not found.\n");
pr_err("INTEL CARILLO RANCH LPC not found.\n");
return -ENODEV;
}
pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
if (!(dev_en & CRVML_GPIOEN_BIT)) {
printk(KERN_ERR
"Carillo Ranch GPIO device was not enabled.\n");
pr_err("Carillo Ranch GPIO device was not enabled.\n");
pci_dev_put(lpc_dev);
return -ENODEV;
}
......@@ -270,7 +271,7 @@ static int __init cr_backlight_init(void)
return PTR_ERR(crp);
}
printk("Carillo Ranch Backlight Driver Initialized.\n");
pr_info("Carillo Ranch Backlight Driver Initialized.\n");
return 0;
}
......
......@@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
DA9034_WLED_ISET(pdata->output_current));
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_RAW;
props.max_brightness = max_brightness;
bl = backlight_device_register(pdev->name, data->da903x_dev, data,
......
......@@ -9,6 +9,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -106,7 +108,7 @@ static int genericbl_probe(struct platform_device *pdev)
generic_backlight_device = bd;
printk("Generic Backlight Driver Initialized.\n");
pr_info("Generic Backlight Driver Initialized.\n");
return 0;
}
......@@ -120,7 +122,7 @@ static int genericbl_remove(struct platform_device *pdev)
backlight_device_unregister(bd);
printk("Generic Backlight Driver Unloaded\n");
pr_info("Generic Backlight Driver Unloaded\n");
return 0;
}
......
......@@ -220,7 +220,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
/* allocate and initialse our state */
ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
ili = devm_kzalloc(&spi->dev, sizeof(struct ili9320), GFP_KERNEL);
if (ili == NULL) {
dev_err(dev, "no memory for device\n");
return -ENOMEM;
......@@ -240,8 +240,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
if (IS_ERR(lcd)) {
dev_err(dev, "failed to register lcd device\n");
ret = PTR_ERR(lcd);
goto err_free;
return PTR_ERR(lcd);
}
ili->lcd = lcd;
......@@ -259,9 +258,6 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
err_unregister:
lcd_device_unregister(lcd);
err_free:
kfree(ili);
return ret;
}
......@@ -272,7 +268,6 @@ int __devexit ili9320_remove(struct ili9320 *ili)
ili9320_power(ili, FB_BLANK_POWERDOWN);
lcd_device_unregister(ili->lcd);
kfree(ili);
return 0;
}
......
......@@ -9,6 +9,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/backlight.h>
#include <linux/device.h>
#include <linux/fb.h>
......@@ -38,7 +40,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
ret = jornada_ssp_byte(GETBRIGHTNESS);
if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
printk(KERN_ERR "bl : get brightness timeout\n");
pr_err("get brightness timeout\n");
jornada_ssp_end();
return -ETIMEDOUT;
} else /* exchange txdummy for value */
......@@ -59,7 +61,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
ret = jornada_ssp_byte(BRIGHTNESSOFF);
if (ret != TXDUMMY) {
printk(KERN_INFO "bl : brightness off timeout\n");
pr_info("brightness off timeout\n");
/* turn off backlight */
PPSR &= ~PPC_LDD1;
PPDR |= PPC_LDD1;
......@@ -70,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
/* send command to our mcu */
if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
printk(KERN_INFO "bl : failed to set brightness\n");
pr_info("failed to set brightness\n");
ret = -ETIMEDOUT;
goto out;
}
......@@ -81,7 +83,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
but due to physical layout it is equal to 0, so we simply
invert the value (MAX VALUE - NEW VALUE). */
if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
printk(KERN_ERR "bl : set brightness failed\n");
pr_err("set brightness failed\n");
ret = -ETIMEDOUT;
}
......@@ -113,7 +115,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
if (IS_ERR(bd)) {
ret = PTR_ERR(bd);
printk(KERN_ERR "bl : failed to register device, err=%x\n", ret);
pr_err("failed to register device, err=%x\n", ret);
return ret;
}
......@@ -125,7 +127,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
jornada_bl_update_status(bd);
platform_set_drvdata(pdev, bd);
printk(KERN_INFO "HP Jornada 700 series backlight driver\n");
pr_info("HP Jornada 700 series backlight driver\n");
return 0;
}
......
......@@ -9,6 +9,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/device.h>
#include <linux/fb.h>
#include <linux/kernel.h>
......@@ -44,7 +46,7 @@ static int jornada_lcd_get_contrast(struct lcd_device *dev)
jornada_ssp_start();
if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
printk(KERN_ERR "lcd: get contrast failed\n");
pr_err("get contrast failed\n");
jornada_ssp_end();
return -ETIMEDOUT;
} else {
......@@ -65,7 +67,7 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
/* push the new value */
if (jornada_ssp_byte(value) != TXDUMMY) {
printk(KERN_ERR "lcd : set contrast failed\n");
pr_err("set contrast failed\n");
jornada_ssp_end();
return -ETIMEDOUT;
}
......@@ -103,7 +105,7 @@ static int jornada_lcd_probe(struct platform_device *pdev)
if (IS_ERR(lcd_device)) {
ret = PTR_ERR(lcd_device);
printk(KERN_ERR "lcd : failed to register device\n");
pr_err("failed to register device\n");
return ret;
}
......
......@@ -11,6 +11,8 @@
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -159,7 +161,8 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
return -EINVAL;
}
priv = kzalloc(sizeof(struct l4f00242t03_priv), GFP_KERNEL);
priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv),
GFP_KERNEL);
if (priv == NULL) {
dev_err(&spi->dev, "No memory for this device.\n");
......@@ -177,7 +180,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
if (ret) {
dev_err(&spi->dev,
"Unable to get the lcd l4f00242t03 reset gpio.\n");
goto err;
return ret;
}
ret = gpio_request_one(pdata->data_enable_gpio, GPIOF_OUT_INIT_LOW,
......@@ -185,7 +188,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
if (ret) {
dev_err(&spi->dev,
"Unable to get the lcd l4f00242t03 data en gpio.\n");
goto err2;
goto err;
}
priv->io_reg = regulator_get(&spi->dev, "vdd");
......@@ -193,7 +196,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
ret = PTR_ERR(priv->io_reg);
dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
__func__);
goto err3;
goto err2;
}
priv->core_reg = regulator_get(&spi->dev, "vcore");
......@@ -201,14 +204,14 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
ret = PTR_ERR(priv->core_reg);
dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
__func__);
goto err4;
goto err3;
}
priv->ld = lcd_device_register("l4f00242t03",
&spi->dev, priv, &l4f_ops);
if (IS_ERR(priv->ld)) {
ret = PTR_ERR(priv->ld);
goto err5;
goto err4;
}
/* Init the LCD */
......@@ -220,16 +223,14 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
return 0;
err5:
regulator_put(priv->core_reg);
err4:
regulator_put(priv->io_reg);
regulator_put(priv->core_reg);
err3:
gpio_free(pdata->data_enable_gpio);
regulator_put(priv->io_reg);
err2:
gpio_free(pdata->reset_gpio);
gpio_free(pdata->data_enable_gpio);
err:
kfree(priv);
gpio_free(pdata->reset_gpio);
return ret;
}
......@@ -250,8 +251,6 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
regulator_put(priv->io_reg);
regulator_put(priv->core_reg);
kfree(priv);
return 0;
}
......
......@@ -5,6 +5,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
......@@ -32,6 +34,8 @@ static int fb_notifier_callback(struct notifier_block *self,
case FB_EVENT_BLANK:
case FB_EVENT_MODE_CHANGE:
case FB_EVENT_MODE_CHANGE_ALL:
case FB_EARLY_EVENT_BLANK:
case FB_R_EARLY_EVENT_BLANK:
break;
default:
return 0;
......@@ -46,6 +50,14 @@ static int fb_notifier_callback(struct notifier_block *self,
if (event == FB_EVENT_BLANK) {
if (ld->ops->set_power)
ld->ops->set_power(ld, *(int *)evdata->data);
} else if (event == FB_EARLY_EVENT_BLANK) {
if (ld->ops->early_set_power)
ld->ops->early_set_power(ld,
*(int *)evdata->data);
} else if (event == FB_R_EARLY_EVENT_BLANK) {
if (ld->ops->r_early_set_power)
ld->ops->r_early_set_power(ld,
*(int *)evdata->data);
} else {
if (ld->ops->set_mode)
ld->ops->set_mode(ld, evdata->data);
......@@ -106,7 +118,7 @@ static ssize_t lcd_store_power(struct device *dev,
mutex_lock(&ld->ops_lock);
if (ld->ops && ld->ops->set_power) {
pr_debug("lcd: set power to %lu\n", power);
pr_debug("set power to %lu\n", power);
ld->ops->set_power(ld, power);
rc = count;
}
......@@ -142,7 +154,7 @@ static ssize_t lcd_store_contrast(struct device *dev,
mutex_lock(&ld->ops_lock);
if (ld->ops && ld->ops->set_contrast) {
pr_debug("lcd: set contrast to %lu\n", contrast);
pr_debug("set contrast to %lu\n", contrast);
ld->ops->set_contrast(ld, contrast);
rc = count;
}
......@@ -253,8 +265,8 @@ static int __init lcd_class_init(void)
{
lcd_class = class_create(THIS_MODULE, "lcd");
if (IS_ERR(lcd_class)) {
printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n",
PTR_ERR(lcd_class));
pr_warn("Unable to create backlight class; errno = %ld\n",
PTR_ERR(lcd_class));
return PTR_ERR(lcd_class);
}
......
......@@ -707,7 +707,7 @@ static int ld9040_probe(struct spi_device *spi)
struct backlight_device *bd = NULL;
struct backlight_properties props;
lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
lcd = devm_kzalloc(&spi->dev, sizeof(struct ld9040), GFP_KERNEL);
if (!lcd)
return -ENOMEM;
......@@ -717,7 +717,7 @@ static int ld9040_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&spi->dev, "spi setup failed.\n");
goto out_free_lcd;
return ret;
}
lcd->spi = spi;
......@@ -726,7 +726,7 @@ static int ld9040_probe(struct spi_device *spi)
lcd->lcd_pd = spi->dev.platform_data;
if (!lcd->lcd_pd) {
dev_err(&spi->dev, "platform data is NULL.\n");
goto out_free_lcd;
return -EFAULT;
}
mutex_init(&lcd->lock);
......@@ -734,13 +734,13 @@ static int ld9040_probe(struct spi_device *spi)
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;
return ret;
}
ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
goto out_free_lcd;
goto out_free_regulator;
}
lcd->ld = ld;
......@@ -782,10 +782,9 @@ static int ld9040_probe(struct spi_device *spi)
out_unregister_lcd:
lcd_device_unregister(lcd->ld);
out_free_lcd:
out_free_regulator:
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
kfree(lcd);
return ret;
}
......@@ -797,7 +796,6 @@ static int __devexit ld9040_remove(struct spi_device *spi)
backlight_device_unregister(lcd->bd);
lcd_device_unregister(lcd->ld);
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
kfree(lcd);
return 0;
}
......@@ -846,7 +844,6 @@ static void ld9040_shutdown(struct spi_device *spi)
static struct spi_driver ld9040_driver = {
.driver = {
.name = "ld9040",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ld9040_probe,
......
/*
* lm3533-bl.c -- LM3533 Backlight driver
*
* Copyright (C) 2011-2012 Texas Instruments
*
* Author: Johan Hovold <jhovold@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/backlight.h>
#include <linux/fb.h>
#include <linux/slab.h>
#include <linux/mfd/lm3533.h>
#define LM3533_HVCTRLBANK_COUNT 2
#define LM3533_BL_MAX_BRIGHTNESS 255
#define LM3533_REG_CTRLBANK_AB_BCONF 0x1a
struct lm3533_bl {
struct lm3533 *lm3533;
struct lm3533_ctrlbank cb;
struct backlight_device *bd;
int id;
};
static inline int lm3533_bl_get_ctrlbank_id(struct lm3533_bl *bl)
{
return bl->id;
}
static int lm3533_bl_update_status(struct backlight_device *bd)
{
struct lm3533_bl *bl = bl_get_data(bd);
int brightness = bd->props.brightness;
if (bd->props.power != FB_BLANK_UNBLANK)
brightness = 0;
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
brightness = 0;
return lm3533_ctrlbank_set_brightness(&bl->cb, (u8)brightness);
}
static int lm3533_bl_get_brightness(struct backlight_device *bd)
{
struct lm3533_bl *bl = bl_get_data(bd);
u8 val;
int ret;
ret = lm3533_ctrlbank_get_brightness(&bl->cb, &val);
if (ret)
return ret;
return val;
}
static const struct backlight_ops lm3533_bl_ops = {
.get_brightness = lm3533_bl_get_brightness,
.update_status = lm3533_bl_update_status,
};
static ssize_t show_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", bl->id);
}
static ssize_t show_als_channel(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
unsigned channel = lm3533_bl_get_ctrlbank_id(bl);
return scnprintf(buf, PAGE_SIZE, "%u\n", channel);
}
static ssize_t show_als_en(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
u8 val;
u8 mask;
bool enable;
int ret;
ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
if (ret)
return ret;
mask = 1 << (2 * ctrlbank);
enable = val & mask;
return scnprintf(buf, PAGE_SIZE, "%d\n", enable);
}
static ssize_t store_als_en(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
int enable;
u8 val;
u8 mask;
int ret;
if (kstrtoint(buf, 0, &enable))
return -EINVAL;
mask = 1 << (2 * ctrlbank);
if (enable)
val = mask;
else
val = 0;
ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
mask);
if (ret)
return ret;
return len;
}
static ssize_t show_linear(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
u8 val;
u8 mask;
int linear;
int ret;
ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
if (ret)
return ret;
mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
if (val & mask)
linear = 1;
else
linear = 0;
return scnprintf(buf, PAGE_SIZE, "%x\n", linear);
}
static ssize_t store_linear(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
unsigned long linear;
u8 mask;
u8 val;
int ret;
if (kstrtoul(buf, 0, &linear))
return -EINVAL;
mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
if (linear)
val = mask;
else
val = 0;
ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
mask);
if (ret)
return ret;
return len;
}
static ssize_t show_pwm(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
u8 val;
int ret;
ret = lm3533_ctrlbank_get_pwm(&bl->cb, &val);
if (ret)
return ret;
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
}
static ssize_t store_pwm(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
u8 val;
int ret;
if (kstrtou8(buf, 0, &val))
return -EINVAL;
ret = lm3533_ctrlbank_set_pwm(&bl->cb, val);
if (ret)
return ret;
return len;
}
static LM3533_ATTR_RO(als_channel);
static LM3533_ATTR_RW(als_en);
static LM3533_ATTR_RO(id);
static LM3533_ATTR_RW(linear);
static LM3533_ATTR_RW(pwm);
static struct attribute *lm3533_bl_attributes[] = {
&dev_attr_als_channel.attr,
&dev_attr_als_en.attr,
&dev_attr_id.attr,
&dev_attr_linear.attr,
&dev_attr_pwm.attr,
NULL,
};
static umode_t lm3533_bl_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct lm3533_bl *bl = dev_get_drvdata(dev);
umode_t mode = attr->mode;
if (attr == &dev_attr_als_channel.attr ||
attr == &dev_attr_als_en.attr) {
if (!bl->lm3533->have_als)
mode = 0;
}
return mode;
};
static struct attribute_group lm3533_bl_attribute_group = {
.is_visible = lm3533_bl_attr_is_visible,
.attrs = lm3533_bl_attributes
};
static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
struct lm3533_bl_platform_data *pdata)
{
int ret;
ret = lm3533_ctrlbank_set_max_current(&bl->cb, pdata->max_current);
if (ret)
return ret;
return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
}
static int __devinit lm3533_bl_probe(struct platform_device *pdev)
{
struct lm3533 *lm3533;
struct lm3533_bl_platform_data *pdata;
struct lm3533_bl *bl;
struct backlight_device *bd;
struct backlight_properties props;
int ret;
dev_dbg(&pdev->dev, "%s\n", __func__);
lm3533 = dev_get_drvdata(pdev->dev.parent);
if (!lm3533)
return -EINVAL;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
if (pdev->id < 0 || pdev->id >= LM3533_HVCTRLBANK_COUNT) {
dev_err(&pdev->dev, "illegal backlight id %d\n", pdev->id);
return -EINVAL;
}
bl = kzalloc(sizeof(*bl), GFP_KERNEL);
if (!bl) {
dev_err(&pdev->dev,
"failed to allocate memory for backlight\n");
return -ENOMEM;
}
bl->lm3533 = lm3533;
bl->id = pdev->id;
bl->cb.lm3533 = lm3533;
bl->cb.id = lm3533_bl_get_ctrlbank_id(bl);
bl->cb.dev = NULL; /* until registered */
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_RAW;
props.max_brightness = LM3533_BL_MAX_BRIGHTNESS;
props.brightness = pdata->default_brightness;
bd = backlight_device_register(pdata->name, pdev->dev.parent, bl,
&lm3533_bl_ops, &props);
if (IS_ERR(bd)) {
dev_err(&pdev->dev, "failed to register backlight device\n");
ret = PTR_ERR(bd);
goto err_free;
}
bl->bd = bd;
bl->cb.dev = &bl->bd->dev;
platform_set_drvdata(pdev, bl);
ret = sysfs_create_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
if (ret < 0) {
dev_err(&pdev->dev, "failed to create sysfs attributes\n");
goto err_unregister;
}
backlight_update_status(bd);
ret = lm3533_bl_setup(bl, pdata);
if (ret)
goto err_sysfs_remove;
ret = lm3533_ctrlbank_enable(&bl->cb);
if (ret)
goto err_sysfs_remove;
return 0;
err_sysfs_remove:
sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
err_unregister:
backlight_device_unregister(bd);
err_free:
kfree(bl);
return ret;
}
static int __devexit lm3533_bl_remove(struct platform_device *pdev)
{
struct lm3533_bl *bl = platform_get_drvdata(pdev);
struct backlight_device *bd = bl->bd;
dev_dbg(&bd->dev, "%s\n", __func__);
bd->props.power = FB_BLANK_POWERDOWN;
bd->props.brightness = 0;
lm3533_ctrlbank_disable(&bl->cb);
sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
backlight_device_unregister(bd);
kfree(bl);
return 0;
}
#ifdef CONFIG_PM
static int lm3533_bl_suspend(struct platform_device *pdev, pm_message_t state)
{
struct lm3533_bl *bl = platform_get_drvdata(pdev);
dev_dbg(&pdev->dev, "%s\n", __func__);
return lm3533_ctrlbank_disable(&bl->cb);
}
static int lm3533_bl_resume(struct platform_device *pdev)
{
struct lm3533_bl *bl = platform_get_drvdata(pdev);
dev_dbg(&pdev->dev, "%s\n", __func__);
return lm3533_ctrlbank_enable(&bl->cb);
}
#else
#define lm3533_bl_suspend NULL
#define lm3533_bl_resume NULL
#endif
static void lm3533_bl_shutdown(struct platform_device *pdev)
{
struct lm3533_bl *bl = platform_get_drvdata(pdev);
dev_dbg(&pdev->dev, "%s\n", __func__);
lm3533_ctrlbank_disable(&bl->cb);
}
static struct platform_driver lm3533_bl_driver = {
.driver = {
.name = "lm3533-backlight",
.owner = THIS_MODULE,
},
.probe = lm3533_bl_probe,
.remove = __devexit_p(lm3533_bl_remove),
.shutdown = lm3533_bl_shutdown,
.suspend = lm3533_bl_suspend,
.resume = lm3533_bl_resume,
};
module_platform_driver(lm3533_bl_driver);
MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
MODULE_DESCRIPTION("LM3533 Backlight driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:lm3533-backlight");
......@@ -168,7 +168,8 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
goto err;
}
st = kzalloc(sizeof(struct lms283gf05_state), GFP_KERNEL);
st = devm_kzalloc(&spi->dev, sizeof(struct lms283gf05_state),
GFP_KERNEL);
if (st == NULL) {
dev_err(&spi->dev, "No memory for device state\n");
ret = -ENOMEM;
......@@ -178,7 +179,7 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
goto err2;
goto err;
}
st->spi = spi;
......@@ -193,8 +194,6 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
return 0;
err2:
kfree(st);
err:
if (pdata != NULL)
gpio_free(pdata->reset_gpio);
......@@ -212,8 +211,6 @@ static int __devexit lms283gf05_remove(struct spi_device *spi)
if (pdata != NULL)
gpio_free(pdata->reset_gpio);
kfree(st);
return 0;
}
......
......@@ -232,23 +232,20 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
struct lcd_device *ld;
int ret;
lcd = kzalloc(sizeof(struct ltv350qv), GFP_KERNEL);
lcd = devm_kzalloc(&spi->dev, sizeof(struct ltv350qv), GFP_KERNEL);
if (!lcd)
return -ENOMEM;
lcd->spi = spi;
lcd->power = FB_BLANK_POWERDOWN;
lcd->buffer = kzalloc(8, GFP_KERNEL);
if (!lcd->buffer) {
ret = -ENOMEM;
goto out_free_lcd;
}
lcd->buffer = devm_kzalloc(&spi->dev, 8, GFP_KERNEL);
if (!lcd->buffer)
return -ENOMEM;
ld = lcd_device_register("ltv350qv", &spi->dev, lcd, &ltv_ops);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
goto out_free_buffer;
}
if (IS_ERR(ld))
return PTR_ERR(ld);
lcd->ld = ld;
ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK);
......@@ -261,10 +258,6 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
out_unregister:
lcd_device_unregister(ld);
out_free_buffer:
kfree(lcd->buffer);
out_free_lcd:
kfree(lcd);
return ret;
}
......@@ -274,8 +267,6 @@ static int __devexit ltv350qv_remove(struct spi_device *spi)
ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
lcd_device_unregister(lcd->ld);
kfree(lcd->buffer);
kfree(lcd);
return 0;
}
......@@ -310,7 +301,6 @@ static void ltv350qv_shutdown(struct spi_device *spi)
static struct spi_driver ltv350qv_driver = {
.driver = {
.name = "ltv350qv",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
......
......@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -168,7 +170,7 @@ static int omapbl_probe(struct platform_device *pdev)
dev->props.brightness = pdata->default_intensity;
omapbl_update_status(dev);
printk(KERN_INFO "OMAP LCD backlight initialised\n");
pr_info("OMAP LCD backlight initialised\n");
return 0;
}
......
......@@ -111,6 +111,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
if (!pcf_bl)
return -ENOMEM;
memset(&bl_props, 0, sizeof(bl_props));
bl_props.type = BACKLIGHT_RAW;
bl_props.max_brightness = 0x3f;
bl_props.power = FB_BLANK_UNBLANK;
......
......@@ -15,6 +15,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -68,13 +70,13 @@ static int progearbl_probe(struct platform_device *pdev)
pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
if (!pmu_dev) {
printk("ALI M7101 PMU not found.\n");
pr_err("ALI M7101 PMU not found.\n");
return -ENODEV;
}
sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
if (!sb_dev) {
printk("ALI 1533 SB not found.\n");
pr_err("ALI 1533 SB not found.\n");
ret = -ENODEV;
goto put_pmu;
}
......
......@@ -741,7 +741,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
struct backlight_device *bd = NULL;
struct backlight_properties props;
lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
lcd = devm_kzalloc(&spi->dev, sizeof(struct s6e63m0), GFP_KERNEL);
if (!lcd)
return -ENOMEM;
......@@ -751,7 +751,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&spi->dev, "spi setup failed.\n");
goto out_free_lcd;
return ret;
}
lcd->spi = spi;
......@@ -760,14 +760,12 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
if (!lcd->lcd_pd) {
dev_err(&spi->dev, "platform data is NULL.\n");
goto out_free_lcd;
return -EFAULT;
}
ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
goto out_free_lcd;
}
if (IS_ERR(ld))
return PTR_ERR(ld);
lcd->ld = ld;
......@@ -824,8 +822,6 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
out_lcd_unregister:
lcd_device_unregister(ld);
out_free_lcd:
kfree(lcd);
return ret;
}
......@@ -838,7 +834,6 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
device_remove_file(&spi->dev, &dev_attr_gamma_mode);
backlight_device_unregister(lcd->bd);
lcd_device_unregister(lcd->ld);
kfree(lcd);
return 0;
}
......@@ -899,7 +894,6 @@ static void s6e63m0_shutdown(struct spi_device *spi)
static struct spi_driver s6e63m0_driver = {
.driver = {
.name = "s6e63m0",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = s6e63m0_probe,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -194,6 +194,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
data->current_brightness = 0;
data->isink_reg = isink_reg;
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_RAW;
props.max_brightness = max_isel;
bl = backlight_device_register("wm831x", &pdev->dev, data,
......
This diff is collapsed.
......@@ -532,6 +532,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
/*------- Backlight control --------*/
memset(&props, 0, sizeof(props));
props.fb_blank = FB_BLANK_UNBLANK;
props.power = FB_BLANK_UNBLANK;
props.type = BACKLIGHT_RAW;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment