Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
613dac31
Commit
613dac31
authored
Sep 22, 2012
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'regmap/topic/cache' and 'regmap/topic/irq' into regmap-next
parents
5698bd75
4d879514
81380739
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
83 additions
and
26 deletions
+83
-26
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-irq.c
+75
-17
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+4
-9
drivers/mfd/wm8994-irq.c
drivers/mfd/wm8994-irq.c
+1
-0
include/linux/regmap.h
include/linux/regmap.h
+3
-0
No files found.
drivers/base/regmap/regmap-irq.c
View file @
613dac31
...
@@ -16,12 +16,14 @@
...
@@ -16,12 +16,14 @@
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/irqdomain.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include "internal.h"
#include "internal.h"
struct
regmap_irq_chip_data
{
struct
regmap_irq_chip_data
{
struct
mutex
lock
;
struct
mutex
lock
;
struct
irq_chip
irq_chip
;
struct
regmap
*
map
;
struct
regmap
*
map
;
const
struct
regmap_irq_chip
*
chip
;
const
struct
regmap_irq_chip
*
chip
;
...
@@ -59,6 +61,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
...
@@ -59,6 +61,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
struct
regmap_irq_chip_data
*
d
=
irq_data_get_irq_chip_data
(
data
);
struct
regmap_irq_chip_data
*
d
=
irq_data_get_irq_chip_data
(
data
);
struct
regmap
*
map
=
d
->
map
;
struct
regmap
*
map
=
d
->
map
;
int
i
,
ret
;
int
i
,
ret
;
u32
reg
;
if
(
d
->
chip
->
runtime_pm
)
{
ret
=
pm_runtime_get_sync
(
map
->
dev
);
if
(
ret
<
0
)
dev_err
(
map
->
dev
,
"IRQ sync failed to resume: %d
\n
"
,
ret
);
}
/*
/*
* If there's been a change in the mask write it back to the
* If there's been a change in the mask write it back to the
...
@@ -66,15 +76,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
...
@@ -66,15 +76,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* suppress pointless writes.
* suppress pointless writes.
*/
*/
for
(
i
=
0
;
i
<
d
->
chip
->
num_regs
;
i
++
)
{
for
(
i
=
0
;
i
<
d
->
chip
->
num_regs
;
i
++
)
{
ret
=
regmap_update_bits
(
d
->
map
,
d
->
chip
->
mask_base
+
reg
=
d
->
chip
->
mask_base
+
(
i
*
map
->
reg_stride
*
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
);
d
->
irq_reg_stride
),
if
(
d
->
chip
->
mask_invert
)
ret
=
regmap_update_bits
(
d
->
map
,
reg
,
d
->
mask_buf_def
[
i
],
~
d
->
mask_buf
[
i
]);
else
ret
=
regmap_update_bits
(
d
->
map
,
reg
,
d
->
mask_buf_def
[
i
],
d
->
mask_buf
[
i
]);
d
->
mask_buf_def
[
i
],
d
->
mask_buf
[
i
]);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
dev_err
(
d
->
map
->
dev
,
"Failed to sync masks in %x
\n
"
,
dev_err
(
d
->
map
->
dev
,
"Failed to sync masks in %x
\n
"
,
d
->
chip
->
mask_base
+
(
i
*
map
->
reg_stride
)
);
reg
);
}
}
if
(
d
->
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
/* If we've changed our wakeup count propagate it to the parent */
/* If we've changed our wakeup count propagate it to the parent */
if
(
d
->
wake_count
<
0
)
if
(
d
->
wake_count
<
0
)
for
(
i
=
d
->
wake_count
;
i
<
0
;
i
++
)
for
(
i
=
d
->
wake_count
;
i
<
0
;
i
++
)
...
@@ -128,8 +145,7 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
...
@@ -128,8 +145,7 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
return
0
;
return
0
;
}
}
static
struct
irq_chip
regmap_irq_chip
=
{
static
const
struct
irq_chip
regmap_irq_chip
=
{
.
name
=
"regmap"
,
.
irq_bus_lock
=
regmap_irq_lock
,
.
irq_bus_lock
=
regmap_irq_lock
,
.
irq_bus_sync_unlock
=
regmap_irq_sync_unlock
,
.
irq_bus_sync_unlock
=
regmap_irq_sync_unlock
,
.
irq_disable
=
regmap_irq_disable
,
.
irq_disable
=
regmap_irq_disable
,
...
@@ -144,6 +160,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
...
@@ -144,6 +160,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
struct
regmap
*
map
=
data
->
map
;
struct
regmap
*
map
=
data
->
map
;
int
ret
,
i
;
int
ret
,
i
;
bool
handled
=
false
;
bool
handled
=
false
;
u32
reg
;
if
(
chip
->
runtime_pm
)
{
ret
=
pm_runtime_get_sync
(
map
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
map
->
dev
,
"IRQ thread failed to resume: %d
\n
"
,
ret
);
return
IRQ_NONE
;
}
}
/*
/*
* Ignore masked IRQs and ack if we need to; we ack early so
* Ignore masked IRQs and ack if we need to; we ack early so
...
@@ -160,20 +186,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
...
@@ -160,20 +186,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to read IRQ status: %d
\n
"
,
dev_err
(
map
->
dev
,
"Failed to read IRQ status: %d
\n
"
,
ret
);
ret
);
if
(
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
return
IRQ_NONE
;
return
IRQ_NONE
;
}
}
data
->
status_buf
[
i
]
&=
~
data
->
mask_buf
[
i
];
data
->
status_buf
[
i
]
&=
~
data
->
mask_buf
[
i
];
if
(
data
->
status_buf
[
i
]
&&
chip
->
ack_base
)
{
if
(
data
->
status_buf
[
i
]
&&
chip
->
ack_base
)
{
ret
=
regmap_write
(
map
,
chip
->
ack_base
+
reg
=
chip
->
ack_base
+
(
i
*
map
->
reg_stride
*
(
i
*
map
->
reg_stride
*
data
->
irq_reg_stride
);
data
->
irq_reg_stride
),
ret
=
regmap_write
(
map
,
reg
,
data
->
status_buf
[
i
]);
data
->
status_buf
[
i
]);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
dev_err
(
map
->
dev
,
"Failed to ack 0x%x: %d
\n
"
,
dev_err
(
map
->
dev
,
"Failed to ack 0x%x: %d
\n
"
,
chip
->
ack_base
+
(
i
*
map
->
reg_stride
),
reg
,
ret
);
ret
);
}
}
}
}
...
@@ -185,6 +211,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
...
@@ -185,6 +211,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
}
}
}
}
if
(
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
if
(
handled
)
if
(
handled
)
return
IRQ_HANDLED
;
return
IRQ_HANDLED
;
else
else
...
@@ -197,7 +226,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
...
@@ -197,7 +226,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
struct
regmap_irq_chip_data
*
data
=
h
->
host_data
;
struct
regmap_irq_chip_data
*
data
=
h
->
host_data
;
irq_set_chip_data
(
virq
,
data
);
irq_set_chip_data
(
virq
,
data
);
irq_set_chip
_and_handler
(
virq
,
&
regmap_irq_chip
,
handle_edge_irq
);
irq_set_chip
(
virq
,
&
data
->
irq_chip
);
irq_set_nested_thread
(
virq
,
1
);
irq_set_nested_thread
(
virq
,
1
);
/* ARM needs us to explicitly flag the IRQ as valid
/* ARM needs us to explicitly flag the IRQ as valid
...
@@ -238,6 +267,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
...
@@ -238,6 +267,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
struct
regmap_irq_chip_data
*
d
;
struct
regmap_irq_chip_data
*
d
;
int
i
;
int
i
;
int
ret
=
-
ENOMEM
;
int
ret
=
-
ENOMEM
;
u32
reg
;
for
(
i
=
0
;
i
<
chip
->
num_irqs
;
i
++
)
{
for
(
i
=
0
;
i
<
chip
->
num_irqs
;
i
++
)
{
if
(
chip
->
irqs
[
i
].
reg_offset
%
map
->
reg_stride
)
if
(
chip
->
irqs
[
i
].
reg_offset
%
map
->
reg_stride
)
...
@@ -284,6 +314,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
...
@@ -284,6 +314,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
goto
err_alloc
;
goto
err_alloc
;
}
}
d
->
irq_chip
=
regmap_irq_chip
;
d
->
irq_chip
.
name
=
chip
->
name
;
if
(
!
chip
->
wake_base
)
{
d
->
irq_chip
.
irq_set_wake
=
NULL
;
d
->
irq_chip
.
flags
|=
IRQCHIP_MASK_ON_SUSPEND
|
IRQCHIP_SKIP_SET_WAKE
;
}
d
->
irq
=
irq
;
d
->
irq
=
irq
;
d
->
map
=
map
;
d
->
map
=
map
;
d
->
chip
=
chip
;
d
->
chip
=
chip
;
...
@@ -303,16 +340,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
...
@@ -303,16 +340,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
/* Mask all the interrupts by default */
/* Mask all the interrupts by default */
for
(
i
=
0
;
i
<
chip
->
num_regs
;
i
++
)
{
for
(
i
=
0
;
i
<
chip
->
num_regs
;
i
++
)
{
d
->
mask_buf
[
i
]
=
d
->
mask_buf_def
[
i
];
d
->
mask_buf
[
i
]
=
d
->
mask_buf_def
[
i
];
ret
=
regmap_write
(
map
,
chip
->
mask_base
+
(
i
*
map
->
reg_stride
reg
=
chip
->
mask_base
+
*
d
->
irq_reg_stride
),
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
);
d
->
mask_buf
[
i
]);
if
(
chip
->
mask_invert
)
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
mask_buf
[
i
],
~
d
->
mask_buf
[
i
]);
else
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
mask_buf
[
i
],
d
->
mask_buf
[
i
]);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to set masks in 0x%x: %d
\n
"
,
dev_err
(
map
->
dev
,
"Failed to set masks in 0x%x: %d
\n
"
,
chip
->
mask_base
+
(
i
*
map
->
reg_stride
)
,
ret
);
reg
,
ret
);
goto
err_alloc
;
goto
err_alloc
;
}
}
}
}
/* Wake is disabled by default */
if
(
d
->
wake_buf
)
{
for
(
i
=
0
;
i
<
chip
->
num_regs
;
i
++
)
{
d
->
wake_buf
[
i
]
=
d
->
mask_buf_def
[
i
];
reg
=
chip
->
wake_base
+
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
);
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
wake_buf
[
i
],
d
->
wake_buf
[
i
]);
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to set masks in 0x%x: %d
\n
"
,
reg
,
ret
);
goto
err_alloc
;
}
}
}
if
(
irq_base
)
if
(
irq_base
)
d
->
domain
=
irq_domain_add_legacy
(
map
->
dev
->
of_node
,
d
->
domain
=
irq_domain_add_legacy
(
map
->
dev
->
of_node
,
chip
->
num_irqs
,
irq_base
,
0
,
chip
->
num_irqs
,
irq_base
,
0
,
...
...
drivers/base/regmap/regmap.c
View file @
613dac31
...
@@ -659,13 +659,12 @@ EXPORT_SYMBOL_GPL(devm_regmap_init);
...
@@ -659,13 +659,12 @@ EXPORT_SYMBOL_GPL(devm_regmap_init);
* new cache. This can be used to restore the cache to defaults or to
* new cache. This can be used to restore the cache to defaults or to
* update the cache configuration to reflect runtime discovery of the
* update the cache configuration to reflect runtime discovery of the
* hardware.
* hardware.
*
* No explicit locking is done here, the user needs to ensure that
* this function will not race with other calls to regmap.
*/
*/
int
regmap_reinit_cache
(
struct
regmap
*
map
,
const
struct
regmap_config
*
config
)
int
regmap_reinit_cache
(
struct
regmap
*
map
,
const
struct
regmap_config
*
config
)
{
{
int
ret
;
map
->
lock
(
map
);
regcache_exit
(
map
);
regcache_exit
(
map
);
regmap_debugfs_exit
(
map
);
regmap_debugfs_exit
(
map
);
...
@@ -681,11 +680,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
...
@@ -681,11 +680,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
map
->
cache_bypass
=
false
;
map
->
cache_bypass
=
false
;
map
->
cache_only
=
false
;
map
->
cache_only
=
false
;
ret
=
regcache_init
(
map
,
config
);
return
regcache_init
(
map
,
config
);
map
->
unlock
(
map
);
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
regmap_reinit_cache
);
EXPORT_SYMBOL_GPL
(
regmap_reinit_cache
);
...
...
drivers/mfd/wm8994-irq.c
View file @
613dac31
...
@@ -135,6 +135,7 @@ static struct regmap_irq_chip wm8994_irq_chip = {
...
@@ -135,6 +135,7 @@ static struct regmap_irq_chip wm8994_irq_chip = {
.
status_base
=
WM8994_INTERRUPT_STATUS_1
,
.
status_base
=
WM8994_INTERRUPT_STATUS_1
,
.
mask_base
=
WM8994_INTERRUPT_STATUS_1_MASK
,
.
mask_base
=
WM8994_INTERRUPT_STATUS_1_MASK
,
.
ack_base
=
WM8994_INTERRUPT_STATUS_1
,
.
ack_base
=
WM8994_INTERRUPT_STATUS_1
,
.
runtime_pm
=
true
,
};
};
int
wm8994_irq_init
(
struct
wm8994
*
wm8994
)
int
wm8994_irq_init
(
struct
wm8994
*
wm8994
)
...
...
include/linux/regmap.h
View file @
613dac31
...
@@ -285,6 +285,7 @@ struct regmap_irq {
...
@@ -285,6 +285,7 @@ struct regmap_irq {
* @ack_base: Base ack address. If zero then the chip is clear on read.
* @ack_base: Base ack address. If zero then the chip is clear on read.
* @wake_base: Base address for wake enables. If zero unsupported.
* @wake_base: Base address for wake enables. If zero unsupported.
* @irq_reg_stride: Stride to use for chips where registers are not contiguous.
* @irq_reg_stride: Stride to use for chips where registers are not contiguous.
* @runtime_pm: Hold a runtime PM lock on the device when accessing it.
*
*
* @num_regs: Number of registers in each control bank.
* @num_regs: Number of registers in each control bank.
* @irqs: Descriptors for individual IRQs. Interrupt numbers are
* @irqs: Descriptors for individual IRQs. Interrupt numbers are
...
@@ -299,6 +300,8 @@ struct regmap_irq_chip {
...
@@ -299,6 +300,8 @@ struct regmap_irq_chip {
unsigned
int
ack_base
;
unsigned
int
ack_base
;
unsigned
int
wake_base
;
unsigned
int
wake_base
;
unsigned
int
irq_reg_stride
;
unsigned
int
irq_reg_stride
;
unsigned
int
mask_invert
;
bool
runtime_pm
;
int
num_regs
;
int
num_regs
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment