CLK: Add and use explicit locking for access to clock device registers.
Implicit locking (for read/write/modify) is not sufficient for complex cases.
This commit is contained in:
parent
a42e49208d
commit
a2b0006e89
@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
|
||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
|
||||
#define MD4(_clk, off, clr, set ) \
|
||||
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
|
||||
#define DEVICE_LOCK(_clk) \
|
||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
|
||||
#define DEVICE_UNLOCK(_clk) \
|
||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
|
||||
|
||||
static int clknode_div_init(struct clknode *clk, device_t dev);
|
||||
static int clknode_div_recalc(struct clknode *clk, uint64_t *req);
|
||||
@ -86,7 +90,9 @@ clknode_div_init(struct clknode *clk, device_t dev)
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
rv = RD4(clk, sc->offset, ®);
|
||||
DEVICE_UNLOCK(clk);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
@ -171,12 +177,17 @@ clknode_div_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
|
||||
(*fout != (_fin / divider)))
|
||||
return (ERANGE);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
rv = MD4(clk, sc->offset,
|
||||
(sc->i_mask << sc->i_shift) | (sc->f_mask << sc->f_shift),
|
||||
(i_div << sc->i_shift) | (f_div << sc->f_shift));
|
||||
if (rv != 0)
|
||||
if (rv != 0) {
|
||||
DEVICE_UNLOCK(clk);
|
||||
return (rv);
|
||||
}
|
||||
RD4(clk, sc->offset, ®);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
sc->divider = divider;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,10 @@ __FBSDID("$FreeBSD$");
|
||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
|
||||
#define MD4(_clk, off, clr, set ) \
|
||||
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
|
||||
|
||||
#define DEVICE_LOCK(_clk) \
|
||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
|
||||
#define DEVICE_UNLOCK(_clk) \
|
||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
|
||||
|
||||
static int clknode_gate_init(struct clknode *clk, device_t dev);
|
||||
static int clknode_gate_set_gate(struct clknode *clk, bool enable);
|
||||
@ -77,7 +80,9 @@ clknode_gate_init(struct clknode *clk, device_t dev)
|
||||
int rv;
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
DEVICE_LOCK(clk);
|
||||
rv = RD4(clk, sc->offset, ®);
|
||||
DEVICE_UNLOCK(clk);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
reg = (reg >> sc->shift) & sc->mask;
|
||||
@ -95,11 +100,15 @@ clknode_gate_set_gate(struct clknode *clk, bool enable)
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
sc->ungated = enable;
|
||||
DEVICE_LOCK(clk);
|
||||
rv = MD4(clk, sc->offset, sc->mask << sc->shift,
|
||||
(sc->ungated ? sc->on_value : sc->off_value) << sc->shift);
|
||||
if (rv != 0)
|
||||
if (rv != 0) {
|
||||
DEVICE_UNLOCK(clk);
|
||||
return (rv);
|
||||
}
|
||||
RD4(clk, sc->offset, ®);
|
||||
DEVICE_UNLOCK(clk);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
|
||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
|
||||
#define MD4(_clk, off, clr, set ) \
|
||||
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
|
||||
#define DEVICE_LOCK(_clk) \
|
||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
|
||||
#define DEVICE_UNLOCK(_clk) \
|
||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
|
||||
|
||||
static int clknode_mux_init(struct clknode *clk, device_t dev);
|
||||
static int clknode_mux_set_mux(struct clknode *clk, int idx);
|
||||
@ -76,9 +80,12 @@ clknode_mux_init(struct clknode *clk, device_t dev)
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
rv = RD4(clk, sc->offset, ®);
|
||||
if (rv != 0)
|
||||
DEVICE_UNLOCK(clk);
|
||||
if (rv != 0) {
|
||||
return (rv);
|
||||
}
|
||||
reg = (reg >> sc->shift) & sc->mask;
|
||||
clknode_init_parent_idx(clk, reg);
|
||||
return(0);
|
||||
@ -93,11 +100,16 @@ clknode_mux_set_mux(struct clknode *clk, int idx)
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
|
||||
DEVICE_LOCK(clk);
|
||||
rv = MD4(clk, sc->offset, sc->mask << sc->shift,
|
||||
(idx & sc->mask) << sc->shift);
|
||||
if (rv != 0)
|
||||
if (rv != 0) {
|
||||
DEVICE_UNLOCK(clk);
|
||||
return (rv);
|
||||
}
|
||||
RD4(clk, sc->offset, ®);
|
||||
DEVICE_UNLOCK(clk);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,23 @@
|
||||
|
||||
INTERFACE clkdev;
|
||||
|
||||
CODE {
|
||||
#include <sys/systm.h>
|
||||
static void
|
||||
clkdev_default_device_lock(device_t dev)
|
||||
{
|
||||
|
||||
panic("clkdev_device_lock() is not implemented");
|
||||
}
|
||||
|
||||
static void
|
||||
clkdev_default_device_unlock(device_t dev)
|
||||
{
|
||||
|
||||
panic("clkdev_device_unlock() is not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Write single register
|
||||
#
|
||||
@ -57,3 +74,17 @@ METHOD int modify_4 {
|
||||
uint32_t clear_mask;
|
||||
uint32_t set_mask;
|
||||
};
|
||||
|
||||
#
|
||||
# Get exclusive access to underlying device
|
||||
#
|
||||
METHOD void device_lock {
|
||||
device_t dev;
|
||||
} DEFAULT clkdev_default_device_lock;
|
||||
|
||||
#
|
||||
# Release exclusive access to underlying device
|
||||
#
|
||||
METHOD void device_unlock {
|
||||
device_t dev;
|
||||
} DEFAULT clkdev_default_device_unlock;
|
||||
|
Loading…
x
Reference in New Issue
Block a user