index
:
litmus-rt.git
archive/unc-master-3.0
archived-2013.1
archived-private-master
archived-semi-part
demo
ecrts-pgm-final
ecrts14-pgm-final
gpusync-rtss12
gpusync/staging
linux-tip
litmus2008-patch-series
master
pgm
prop/litmus-signals
prop/robust-tie-break
staging
test
tracing-devel
v2.6.34-with-arm-patches
v2015.1
wip-2011.2-bbb
wip-2011.2-bbb-trace
wip-2012.3-gpu
wip-2012.3-gpu-preport
wip-2012.3-gpu-rtss13
wip-2012.3-gpu-sobliv-budget-w-kshark
wip-aedzl-final
wip-aedzl-revised
wip-arbit-deadline
wip-aux-tasks
wip-bbb
wip-bbb-prio-don
wip-better-break
wip-binary-heap
wip-budget
wip-color
wip-color-jlh
wip-d10-hz1000
wip-default-clustering
wip-dissipation-jerickso
wip-dissipation2-jerickso
wip-ecrts14-pgm
wip-edf-hsb
wip-edf-os
wip-edf-tie-break
wip-edzl-critique
wip-edzl-final
wip-edzl-revised
wip-events
wip-extra-debug
wip-fix-switch-jerickso
wip-fix3
wip-fmlp-dequeue
wip-ft-irq-flag
wip-gpu-cleanup
wip-gpu-interrupts
wip-gpu-rtas12
wip-gpu-rtss12
wip-gpu-rtss12-srp
wip-gpusync-merge
wip-ikglp
wip-k-fmlp
wip-kernel-coloring
wip-kernthreads
wip-klmirqd-to-aux
wip-kshark
wip-litmus-3.2
wip-litmus2011.2
wip-litmus3.0-2011.2
wip-master-2.6.33-rt
wip-mc
wip-mc-bipasa
wip-mc-jerickso
wip-mc2-cache-slack
wip-mcrit-mac
wip-merge-3.0
wip-merge-v3.0
wip-migration-affinity
wip-mmap-uncache
wip-modechange
wip-nested-locking
wip-omlp-gedf
wip-pai
wip-percore-lib
wip-performance
wip-pgm
wip-pgm-split
wip-pm-ovd
wip-prio-inh
wip-prioq-dgl
wip-refactored-gedf
wip-release-master-fix
wip-robust-tie-break
wip-rt-kshark
wip-rtas12-pgm
wip-semi-part
wip-semi-part-edfos-jerickso
wip-shared-lib
wip-shared-lib2
wip-shared-mem
wip-splitting-jerickso
wip-splitting-omlp-jerickso
wip-stage-binheap
wip-sun-port
wip-timer-trace
wip-tracepoints
The LITMUS^RT kernel.
Bjoern Brandenburg
about
summary
refs
log
tree
commit
diff
stats
log msg
author
committer
range
path:
root
/
arch
/
mips
/
kernel
Mode
Name
Size
-rw-r--r--
8250-platform.c
1091
log
stats
plain
blame
-rw-r--r--
Makefile
3417
log
stats
plain
blame
-rw-r--r--
asm-offsets.c
9498
log
stats
plain
blame
-rw-r--r--
binfmt_elfn32.c
3368
log
stats
plain
blame
-rw-r--r--
binfmt_elfo32.c
4086
log
stats
plain
blame
-rw-r--r--
branch.c
4675
log
stats
plain
blame
-rw-r--r--
cevt-bcm1480.c
4466
log
stats
plain
blame
-rw-r--r--
cevt-ds1287.c
2837
log
stats
plain
blame
-rw-r--r--
cevt-gt641xx.c
3666
log
stats
plain
blame
-rw-r--r--
cevt-r4k.c
6852
log
stats
plain
blame
-rw-r--r--
cevt-sb1250.c
4402
log
stats
plain
blame
-rw-r--r--
cevt-txx9.c
4972
log
stats
plain
blame
-rw-r--r--
cpu-bugs64.c
7627
log
stats
plain
blame
-rw-r--r--
cpu-probe.c
24193
log
stats
plain
blame
-rw-r--r--
csrc-bcm1480.c
1687
log
stats
plain
blame
-rw-r--r--
csrc-ioasic.c
1753
log
stats
plain
blame
-rw-r--r--
csrc-r4k.c
867
log
stats
plain
blame
-rw-r--r--
csrc-sb1250.c
2158
log
stats
plain
blame
-rw-r--r--
early_printk.c
976
log
stats
plain
blame
-rw-r--r--
entry.S
4541
log
stats
plain
blame
-rw-r--r--
gdb-low.S
8883
log
stats
plain
blame
-rw-r--r--
gdb-stub.c
25910
log
stats
plain
blame
-rw-r--r--
genex.S
11176
log
stats
plain
blame
-rw-r--r--
gpio_txx9.c
2194
log
stats
plain
blame
-rw-r--r--
head.S
5910
log
stats
plain
blame
-rw-r--r--
i8253.c
5537
log
stats
plain
blame
-rw-r--r--
i8259.c
9362
log
stats
plain
blame
-rw-r--r--
init_task.c
1158
log
stats
plain
blame
-rw-r--r--
irix5sys.S
26541
log
stats
plain
blame
-rw-r--r--
irixelf.c
35930
log
stats
plain
blame
-rw-r--r--
irixinv.c
2057
log
stats
plain
blame
-rw-r--r--
irixioctl.c
4549
log
stats
plain
blame
-rw-r--r--
irixsig.c
22128
log
stats
plain
blame
-rw-r--r--
irq-gic.c
7705
log
stats
plain
blame
-rw-r--r--
irq-gt641xx.c
3373
log
stats
plain
blame
-rw-r--r--
irq-msc01.c
3963
log
stats
plain
blame
-rw-r--r--
irq-rm7000.c
1266
log
stats
plain
blame
-rw-r--r--
irq-rm9000.c
2612
log
stats
plain
blame
-rw-r--r--
irq.c
3285
log
stats
plain
blame
-rw-r--r--
irq_cpu.c
3300
log
stats
plain
blame
-rw-r--r--
irq_txx9.c
4863
log
stats
plain
blame
-rw-r--r--
kspd.c
9284
log
stats
plain
blame
-rw-r--r--
linux32.c
14205
log
stats
plain
blame
-rw-r--r--
machine_kexec.c
1930
log
stats
plain
blame
-rw-r--r--
mips-mt-fpaff.c
4206
log
stats
plain
blame
-rw-r--r--
mips-mt.c
7970
log
stats
plain
blame
-rw-r--r--
mips_ksyms.c
1652
log
stats
plain
blame
-rw-r--r--
module.c
10159
log
stats
plain
blame
-rw-r--r--
proc.c
2838
log
stats
plain
blame
-rw-r--r--
process.c
11281
log
stats
plain
blame
-rw-r--r--
ptrace.c
11642
log
stats
plain
blame
-rw-r--r--
ptrace32.c
10275
log
stats
plain
blame
-rw-r--r--
r2300_fpu.S
3683
log
stats
plain
blame
-rw-r--r--
r2300_switch.S
3452
log
stats
plain
blame
-rw-r--r--
r4k_fpu.S
5059
log
stats
plain
blame
-rw-r--r--
r4k_switch.S
5223
log
stats
plain
blame
-rw-r--r--
r6000_fpu.S
2277
log
stats
plain
blame
-rw-r--r--
relocate_kernel.S
1676
log
stats
plain
blame
-rw-r--r--
reset.c
955
log
stats
plain
blame
-rw-r--r--
rtlx.c
12628
log
stats
plain
blame
-rw-r--r--
scall32-o32.S
16189
log
stats
plain
blame
-rw-r--r--
scall64-64.S
10482
log
stats
plain
blame
-rw-r--r--
scall64-n32.S
9727
log
stats
plain
blame
-rw-r--r--
scall64-o32.S
12741
log
stats
plain
blame
-rw-r--r--
setup.c
14207
log
stats
plain
blame
-rw-r--r--
signal-common.h
1288
log
stats
plain
blame
-rw-r--r--
signal.c
18206
log
stats
plain
blame
-rw-r--r--
signal32.c
21457
log
stats
plain
blame
-rw-r--r--
signal_n32.c
6719
log
stats
plain
blame
-rw-r--r--
smp-cmp.c
6426
log
stats
plain
blame
-rw-r--r--
smp-mt.c
7319
log
stats
plain
blame
-rw-r--r--
smp-up.c
1394
log
stats
plain
blame
-rw-r--r--
smp.c
10126
log
stats
plain
blame
-rw-r--r--
smtc-asm.S
3604
log
stats
plain
blame
-rw-r--r--
smtc-proc.c
2046
log
stats
plain
blame
-rw-r--r--
smtc.c
36428
log
stats
plain
blame
-rw-r--r--
spram.c
4769
log
stats
plain
blame
-rw-r--r--
stacktrace.c
1734
log
stats
plain
blame
-rw-r--r--
sync-r4k.c
3786
log
stats
plain
blame
-rw-r--r--
syscall.c
10794
log
stats
plain
blame
-rw-r--r--
sysirix.c
51177
log
stats
plain
blame
-rw-r--r--
time.c
3617
log
stats
plain
blame
-rw-r--r--
topology.c
582
log
stats
plain
blame
-rw-r--r--
traps.c
41418
log
stats
plain
blame
-rw-r--r--
unaligned.c
13982
log
stats
plain
blame
-rw-r--r--
vmlinux.lds.S
3941
log
stats
plain
blame
-rw-r--r--
vpe.c
36938
log
stats
plain
blame
opt">);
if
(
val
&
ST_COEFFWREN
)
MCBSP_ST_WRITE
(
mcbsp
,
SSELCR
,
val
& ~(
ST_COEFFWREN
));
MCBSP_ST_WRITE
(
mcbsp
,
SSELCR
,
val
|
ST_COEFFWREN
);
for
(
i
=
0
;
i
<
128
;
i
++)
MCBSP_ST_WRITE
(
mcbsp
,
SFIRCR
,
fir
[
i
]);
i
=
0
;
val
=
MCBSP_ST_READ
(
mcbsp
,
SSELCR
);
while
(!(
val
&
ST_COEFFWRDONE
) && (++
i
<
1000
))
val
=
MCBSP_ST_READ
(
mcbsp
,
SSELCR
);
MCBSP_ST_WRITE
(
mcbsp
,
SSELCR
,
val
& ~(
ST_COEFFWREN
));
if
(
i
==
1000
)
dev_err
(
mcbsp
->
dev
,
"McBSP FIR load error!
\n
"
);
}
static void
omap_st_chgain
(
struct
omap_mcbsp
*
mcbsp
)
{
u16 w
;
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
w
=
MCBSP_ST_READ
(
mcbsp
,
SSELCR
);
MCBSP_ST_WRITE
(
mcbsp
,
SGAINCR
,
ST_CH0GAIN
(
st_data
->
ch0gain
) |
\
ST_CH1GAIN
(
st_data
->
ch1gain
));
}
int
omap_st_set_chgain
(
struct
omap_mcbsp
*
mcbsp
,
int
channel
,
s16 chgain
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
int
ret
=
0
;
if
(!
st_data
)
return
-
ENOENT
;
spin_lock_irq
(&
mcbsp
->
lock
);
if
(
channel
==
0
)
st_data
->
ch0gain
=
chgain
;
else if
(
channel
==
1
)
st_data
->
ch1gain
=
chgain
;
else
ret
= -
EINVAL
;
if
(
st_data
->
enabled
)
omap_st_chgain
(
mcbsp
);
spin_unlock_irq
(&
mcbsp
->
lock
);
return
ret
;
}
int
omap_st_get_chgain
(
struct
omap_mcbsp
*
mcbsp
,
int
channel
,
s16
*
chgain
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
int
ret
=
0
;
if
(!
st_data
)
return
-
ENOENT
;
spin_lock_irq
(&
mcbsp
->
lock
);
if
(
channel
==
0
)
*
chgain
=
st_data
->
ch0gain
;
else if
(
channel
==
1
)
*
chgain
=
st_data
->
ch1gain
;
else
ret
= -
EINVAL
;
spin_unlock_irq
(&
mcbsp
->
lock
);
return
ret
;
}
static int
omap_st_start
(
struct
omap_mcbsp
*
mcbsp
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
if
(
st_data
->
enabled
&& !
st_data
->
running
) {
omap_st_fir_write
(
mcbsp
,
st_data
->
taps
);
omap_st_chgain
(
mcbsp
);
if
(!
mcbsp
->
free
) {
omap_st_on
(
mcbsp
);
st_data
->
running
=
1
;
}
}
return
0
;
}
int
omap_st_enable
(
struct
omap_mcbsp
*
mcbsp
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
if
(!
st_data
)
return
-
ENODEV
;
spin_lock_irq
(&
mcbsp
->
lock
);
st_data
->
enabled
=
1
;
omap_st_start
(
mcbsp
);
spin_unlock_irq
(&
mcbsp
->
lock
);
return
0
;
}
static int
omap_st_stop
(
struct
omap_mcbsp
*
mcbsp
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
if
(
st_data
->
running
) {
if
(!
mcbsp
->
free
) {
omap_st_off
(
mcbsp
);
st_data
->
running
=
0
;
}
}
return
0
;
}
int
omap_st_disable
(
struct
omap_mcbsp
*
mcbsp
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
int
ret
=
0
;
if
(!
st_data
)
return
-
ENODEV
;
spin_lock_irq
(&
mcbsp
->
lock
);
omap_st_stop
(
mcbsp
);
st_data
->
enabled
=
0
;
spin_unlock_irq
(&
mcbsp
->
lock
);
return
ret
;
}
int
omap_st_is_enabled
(
struct
omap_mcbsp
*
mcbsp
)
{
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
if
(!
st_data
)
return
-
ENODEV
;
return
st_data
->
enabled
;
}
/*
* omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
* The threshold parameter is 1 based, and it is converted (threshold - 1)
* for the THRSH2 register.
*/
void
omap_mcbsp_set_tx_threshold
(
struct
omap_mcbsp
*
mcbsp
,
u16 threshold
)
{
if
(
mcbsp
->
pdata
->
buffer_size
==
0
)
return
;
if
(
threshold
&&
threshold
<=
mcbsp
->
max_tx_thres
)
MCBSP_WRITE
(
mcbsp
,
THRSH2
,
threshold
-
1
);
}
/*
* omap_mcbsp_set_rx_threshold configures the receive threshold in words.
* The threshold parameter is 1 based, and it is converted (threshold - 1)
* for the THRSH1 register.
*/
void
omap_mcbsp_set_rx_threshold
(
struct
omap_mcbsp
*
mcbsp
,
u16 threshold
)
{
if
(
mcbsp
->
pdata
->
buffer_size
==
0
)
return
;
if
(
threshold
&&
threshold
<=
mcbsp
->
max_rx_thres
)
MCBSP_WRITE
(
mcbsp
,
THRSH1
,
threshold
-
1
);
}
/*
* omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
*/
u16
omap_mcbsp_get_tx_delay
(
struct
omap_mcbsp
*
mcbsp
)
{
u16 buffstat
;
if
(
mcbsp
->
pdata
->
buffer_size
==
0
)
return
0
;
/* Returns the number of free locations in the buffer */
buffstat
=
MCBSP_READ
(
mcbsp
,
XBUFFSTAT
);
/* Number of slots are different in McBSP ports */
return
mcbsp
->
pdata
->
buffer_size
-
buffstat
;
}
/*
* omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
* to reach the threshold value (when the DMA will be triggered to read it)
*/
u16
omap_mcbsp_get_rx_delay
(
struct
omap_mcbsp
*
mcbsp
)
{
u16 buffstat
,
threshold
;
if
(
mcbsp
->
pdata
->
buffer_size
==
0
)
return
0
;
/* Returns the number of used locations in the buffer */
buffstat
=
MCBSP_READ
(
mcbsp
,
RBUFFSTAT
);
/* RX threshold */
threshold
=
MCBSP_READ
(
mcbsp
,
THRSH1
);
/* Return the number of location till we reach the threshold limit */
if
(
threshold
<=
buffstat
)
return
0
;
else
return
threshold
-
buffstat
;
}
int
omap_mcbsp_request
(
struct
omap_mcbsp
*
mcbsp
)
{
void
*
reg_cache
;
int
err
;
reg_cache
=
kzalloc
(
mcbsp
->
reg_cache_size
,
GFP_KERNEL
);
if
(!
reg_cache
) {
return
-
ENOMEM
;
}
spin_lock
(&
mcbsp
->
lock
);
if
(!
mcbsp
->
free
) {
dev_err
(
mcbsp
->
dev
,
"McBSP%d is currently in use
\n
"
,
mcbsp
->
id
);
err
= -
EBUSY
;
goto
err_kfree
;
}
mcbsp
->
free
=
false
;
mcbsp
->
reg_cache
=
reg_cache
;
spin_unlock
(&
mcbsp
->
lock
);
if
(
mcbsp
->
pdata
&&
mcbsp
->
pdata
->
ops
&&
mcbsp
->
pdata
->
ops
->
request
)
mcbsp
->
pdata
->
ops
->
request
(
mcbsp
->
id
-
1
);
/*
* Make sure that transmitter, receiver and sample-rate generator are
* not running before activating IRQs.
*/
MCBSP_WRITE
(
mcbsp
,
SPCR1
,
0
);
MCBSP_WRITE
(
mcbsp
,
SPCR2
,
0
);
if
(
mcbsp
->
irq
) {
err
=
request_irq
(
mcbsp
->
irq
,
omap_mcbsp_irq_handler
,
0
,
"McBSP"
, (
void
*)
mcbsp
);
if
(
err
!=
0
) {
dev_err
(
mcbsp
->
dev
,
"Unable to request IRQ
\n
"
);
goto
err_clk_disable
;
}
}
else
{
err
=
request_irq
(
mcbsp
->
tx_irq
,
omap_mcbsp_tx_irq_handler
,
0
,
"McBSP TX"
, (
void
*)
mcbsp
);
if
(
err
!=
0
) {
dev_err
(
mcbsp
->
dev
,
"Unable to request TX IRQ
\n
"
);
goto
err_clk_disable
;
}
err
=
request_irq
(
mcbsp
->
rx_irq
,
omap_mcbsp_rx_irq_handler
,
0
,
"McBSP RX"
, (
void
*)
mcbsp
);
if
(
err
!=
0
) {
dev_err
(
mcbsp
->
dev
,
"Unable to request RX IRQ
\n
"
);
goto
err_free_irq
;
}
}
return
0
;
err_free_irq
:
free_irq
(
mcbsp
->
tx_irq
, (
void
*)
mcbsp
);
err_clk_disable
:
if
(
mcbsp
->
pdata
&&
mcbsp
->
pdata
->
ops
&&
mcbsp
->
pdata
->
ops
->
free
)
mcbsp
->
pdata
->
ops
->
free
(
mcbsp
->
id
-
1
);
/* Disable wakeup behavior */
if
(
mcbsp
->
pdata
->
has_wakeup
)
MCBSP_WRITE
(
mcbsp
,
WAKEUPEN
,
0
);
spin_lock
(&
mcbsp
->
lock
);
mcbsp
->
free
=
true
;
mcbsp
->
reg_cache
=
NULL
;
err_kfree
:
spin_unlock
(&
mcbsp
->
lock
);
kfree
(
reg_cache
);
return
err
;
}
void
omap_mcbsp_free
(
struct
omap_mcbsp
*
mcbsp
)
{
void
*
reg_cache
;
if
(
mcbsp
->
pdata
&&
mcbsp
->
pdata
->
ops
&&
mcbsp
->
pdata
->
ops
->
free
)
mcbsp
->
pdata
->
ops
->
free
(
mcbsp
->
id
-
1
);
/* Disable wakeup behavior */
if
(
mcbsp
->
pdata
->
has_wakeup
)
MCBSP_WRITE
(
mcbsp
,
WAKEUPEN
,
0
);
/* Disable interrupt requests */
if
(
mcbsp
->
irq
)
MCBSP_WRITE
(
mcbsp
,
IRQEN
,
0
);
if
(
mcbsp
->
irq
) {
free_irq
(
mcbsp
->
irq
, (
void
*)
mcbsp
);
}
else
{
free_irq
(
mcbsp
->
rx_irq
, (
void
*)
mcbsp
);
free_irq
(
mcbsp
->
tx_irq
, (
void
*)
mcbsp
);
}
reg_cache
=
mcbsp
->
reg_cache
;
/*
* Select CLKS source from internal source unconditionally before
* marking the McBSP port as free.
* If the external clock source via MCBSP_CLKS pin has been selected the
* system will refuse to enter idle if the CLKS pin source is not reset
* back to internal source.
*/
if
(!
cpu_class_is_omap1
())
omap2_mcbsp_set_clks_src
(
mcbsp
,
MCBSP_CLKS_PRCM_SRC
);
spin_lock
(&
mcbsp
->
lock
);
if
(
mcbsp
->
free
)
dev_err
(
mcbsp
->
dev
,
"McBSP%d was not reserved
\n
"
,
mcbsp
->
id
);
else
mcbsp
->
free
=
true
;
mcbsp
->
reg_cache
=
NULL
;
spin_unlock
(&
mcbsp
->
lock
);
if
(
reg_cache
)
kfree
(
reg_cache
);
}
/*
* Here we start the McBSP, by enabling transmitter, receiver or both.
* If no transmitter or receiver is active prior calling, then sample-rate
* generator and frame sync are started.
*/
void
omap_mcbsp_start
(
struct
omap_mcbsp
*
mcbsp
,
int
tx
,
int
rx
)
{
int
enable_srg
=
0
;
u16 w
;
if
(
mcbsp
->
st_data
)
omap_st_start
(
mcbsp
);
/* Only enable SRG, if McBSP is master */
w
=
MCBSP_READ_CACHE
(
mcbsp
,
PCR0
);
if
(
w
& (
FSXM
|
FSRM
|
CLKXM
|
CLKRM
))
enable_srg
= !((
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
) |
MCBSP_READ_CACHE
(
mcbsp
,
SPCR1
)) &
1
);
if
(
enable_srg
) {
/* Start the sample generator */
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
);
MCBSP_WRITE
(
mcbsp
,
SPCR2
,
w
| (
1
<<
6
));
}
/* Enable transmitter and receiver */
tx
&=
1
;
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
);
MCBSP_WRITE
(
mcbsp
,
SPCR2
,
w
|
tx
);
rx
&=
1
;
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR1
);
MCBSP_WRITE
(
mcbsp
,
SPCR1
,
w
|
rx
);
/*
* Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
* REVISIT: 100us may give enough time for two CLKSRG, however
* due to some unknown PM related, clock gating etc. reason it
* is now at 500us.
*/
udelay
(
500
);
if
(
enable_srg
) {
/* Start frame sync */
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
);
MCBSP_WRITE
(
mcbsp
,
SPCR2
,
w
| (
1
<<
7
));
}
if
(
mcbsp
->
pdata
->
has_ccr
) {
/* Release the transmitter and receiver */
w
=
MCBSP_READ_CACHE
(
mcbsp
,
XCCR
);
w
&= ~(
tx
?
XDISABLE
:
0
);
MCBSP_WRITE
(
mcbsp
,
XCCR
,
w
);
w
=
MCBSP_READ_CACHE
(
mcbsp
,
RCCR
);
w
&= ~(
rx
?
RDISABLE
:
0
);
MCBSP_WRITE
(
mcbsp
,
RCCR
,
w
);
}
/* Dump McBSP Regs */
omap_mcbsp_dump_reg
(
mcbsp
);
}
void
omap_mcbsp_stop
(
struct
omap_mcbsp
*
mcbsp
,
int
tx
,
int
rx
)
{
int
idle
;
u16 w
;
/* Reset transmitter */
tx
&=
1
;
if
(
mcbsp
->
pdata
->
has_ccr
) {
w
=
MCBSP_READ_CACHE
(
mcbsp
,
XCCR
);
w
|= (
tx
?
XDISABLE
:
0
);
MCBSP_WRITE
(
mcbsp
,
XCCR
,
w
);
}
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
);
MCBSP_WRITE
(
mcbsp
,
SPCR2
,
w
& ~
tx
);
/* Reset receiver */
rx
&=
1
;
if
(
mcbsp
->
pdata
->
has_ccr
) {
w
=
MCBSP_READ_CACHE
(
mcbsp
,
RCCR
);
w
|= (
rx
?
RDISABLE
:
0
);
MCBSP_WRITE
(
mcbsp
,
RCCR
,
w
);
}
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR1
);
MCBSP_WRITE
(
mcbsp
,
SPCR1
,
w
& ~
rx
);
idle
= !((
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
) |
MCBSP_READ_CACHE
(
mcbsp
,
SPCR1
)) &
1
);
if
(
idle
) {
/* Reset the sample rate generator */
w
=
MCBSP_READ_CACHE
(
mcbsp
,
SPCR2
);
MCBSP_WRITE
(
mcbsp
,
SPCR2
,
w
& ~(
1
<<
6
));
}
if
(
mcbsp
->
st_data
)
omap_st_stop
(
mcbsp
);
}
int
omap2_mcbsp_set_clks_src
(
struct
omap_mcbsp
*
mcbsp
,
u8 fck_src_id
)
{
const char
*
src
;
if
(
fck_src_id
==
MCBSP_CLKS_PAD_SRC
)
src
=
"clks_ext"
;
else if
(
fck_src_id
==
MCBSP_CLKS_PRCM_SRC
)
src
=
"clks_fclk"
;
else
return
-
EINVAL
;
if
(
mcbsp
->
pdata
->
set_clk_src
)
return
mcbsp
->
pdata
->
set_clk_src
(
mcbsp
->
dev
,
mcbsp
->
fclk
,
src
);
else
return
-
EINVAL
;
}
int
omap_mcbsp_6pin_src_mux
(
struct
omap_mcbsp
*
mcbsp
,
u8 mux
)
{
const char
*
signal
, *
src
;
if
(!
mcbsp
->
pdata
->
mux_signal
)
return
-
EINVAL
;
switch
(
mux
) {
case
CLKR_SRC_CLKR
:
signal
=
"clkr"
;
src
=
"clkr"
;
break
;
case
CLKR_SRC_CLKX
:
signal
=
"clkr"
;
src
=
"clkx"
;
break
;
case
FSR_SRC_FSR
:
signal
=
"fsr"
;
src
=
"fsr"
;
break
;
case
FSR_SRC_FSX
:
signal
=
"fsr"
;
src
=
"fsx"
;
break
;
default
:
return
-
EINVAL
;
}
return
mcbsp
->
pdata
->
mux_signal
(
mcbsp
->
dev
,
signal
,
src
);
}
#define max_thres(m) (mcbsp->pdata->buffer_size)
#define valid_threshold(m, val) ((val) <= max_thres(m))
#define THRESHOLD_PROP_BUILDER(prop) \
static ssize_t prop##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
\
return sprintf(buf,
"%u
\n
"
, mcbsp->prop); \
} \
\
static ssize_t prop##_store(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t size) \
{ \
struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
unsigned long val; \
int status; \
\
status = strict_strtoul(buf, 0, &val); \
if (status) \
return status; \
\
if (!valid_threshold(mcbsp, val)) \
return -EDOM; \
\
mcbsp->prop = val; \
return size; \
} \
\
static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store);
THRESHOLD_PROP_BUILDER
(
max_tx_thres
);
THRESHOLD_PROP_BUILDER
(
max_rx_thres
);
static const char
*
dma_op_modes
[] = {
"element"
,
"threshold"
,
};
static
ssize_t
dma_op_mode_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
omap_mcbsp
*
mcbsp
=
dev_get_drvdata
(
dev
);
int
dma_op_mode
,
i
=
0
;
ssize_t len
=
0
;
const char
*
const
*
s
;
dma_op_mode
=
mcbsp
->
dma_op_mode
;
for
(
s
= &
dma_op_modes
[
i
];
i
<
ARRAY_SIZE
(
dma_op_modes
);
s
++,
i
++) {
if
(
dma_op_mode
==
i
)
len
+=
sprintf
(
buf
+
len
,
"[%s] "
, *
s
);
else
len
+=
sprintf
(
buf
+
len
,
"%s "
, *
s
);
}
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
return
len
;
}
static
ssize_t
dma_op_mode_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const char
*
buf
,
size_t
size
)
{
struct
omap_mcbsp
*
mcbsp
=
dev_get_drvdata
(
dev
);
const char
*
const
*
s
;
int
i
=
0
;
for
(
s
= &
dma_op_modes
[
i
];
i
<
ARRAY_SIZE
(
dma_op_modes
);
s
++,
i
++)
if
(
sysfs_streq
(
buf
, *
s
))
break
;
if
(
i
==
ARRAY_SIZE
(
dma_op_modes
))
return
-
EINVAL
;
spin_lock_irq
(&
mcbsp
->
lock
);
if
(!
mcbsp
->
free
) {
size
= -
EBUSY
;
goto
unlock
;
}
mcbsp
->
dma_op_mode
=
i
;
unlock
:
spin_unlock_irq
(&
mcbsp
->
lock
);
return
size
;
}
static
DEVICE_ATTR
(
dma_op_mode
,
0644
,
dma_op_mode_show
,
dma_op_mode_store
);
static const struct
attribute
*
additional_attrs
[] = {
&
dev_attr_max_tx_thres
.
attr
,
&
dev_attr_max_rx_thres
.
attr
,
&
dev_attr_dma_op_mode
.
attr
,
NULL
,
};
static const struct
attribute_group additional_attr_group
= {
.
attrs
= (
struct
attribute
**)
additional_attrs
,
};
static
ssize_t
st_taps_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
omap_mcbsp
*
mcbsp
=
dev_get_drvdata
(
dev
);
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
ssize_t status
=
0
;
int
i
;
spin_lock_irq
(&
mcbsp
->
lock
);
for
(
i
=
0
;
i
<
st_data
->
nr_taps
;
i
++)
status
+=
sprintf
(&
buf
[
status
], (
i
?
", %d"
:
"%d"
),
st_data
->
taps
[
i
]);
if
(
i
)
status
+=
sprintf
(&
buf
[
status
],
"
\n
"
);
spin_unlock_irq
(&
mcbsp
->
lock
);
return
status
;
}
static
ssize_t
st_taps_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const char
*
buf
,
size_t
size
)
{
struct
omap_mcbsp
*
mcbsp
=
dev_get_drvdata
(
dev
);
struct
omap_mcbsp_st_data
*
st_data
=
mcbsp
->
st_data
;
int
val
,
tmp
,
status
,
i
=
0
;
spin_lock_irq
(&
mcbsp
->
lock
);
memset
(
st_data
->
taps
,
0
,
sizeof
(
st_data
->
taps
));
st_data
->
nr_taps
=
0
;
do
{
status
=
sscanf
(
buf
,
"%d%n"
, &
val
, &
tmp
);
if
(
status
<
0
||
status
==
0
) {
size
= -
EINVAL
;
goto
out
;
}
if
(
val
< -
32768
||
val
>
32767
) {
size
= -
EINVAL
;
goto
out
;
}
st_data
->
taps
[
i
++] =
val
;
buf
+=
tmp
;
if
(*
buf
!=
','
)
break
;
buf
++;
}
while
(
1
);
st_data
->
nr_taps
=
i
;
out
:
spin_unlock_irq
(&
mcbsp
->
lock
);
return
size
;
}
static
DEVICE_ATTR
(
st_taps
,
0644
,
st_taps_show
,
st_taps_store
);
static const struct
attribute
*
sidetone_attrs
[] = {
&
dev_attr_st_taps
.
attr
,
NULL
,
};
static const struct
attribute_group sidetone_attr_group
= {
.
attrs
= (
struct
attribute
**)
sidetone_attrs
,
};
static int
__devinit
omap_st_add
(
struct
omap_mcbsp
*
mcbsp
,
struct
resource
*
res
)
{
struct
omap_mcbsp_st_data
*
st_data
;
int
err
;
st_data
=
devm_kzalloc
(
mcbsp
->
dev
,
sizeof
(*
mcbsp
->
st_data
),
GFP_KERNEL
);
if
(!
st_data
)
return
-
ENOMEM
;
st_data
->
io_base_st
=
devm_ioremap
(
mcbsp
->
dev
,
res
->
start
,
resource_size
(
res
));
if
(!
st_data
->
io_base_st
)
return
-
ENOMEM
;
err
=
sysfs_create_group
(&
mcbsp
->
dev
->
kobj
, &
sidetone_attr_group
);
if
(
err
)
return
err
;
mcbsp
->
st_data
=
st_data
;
return
0
;
}
/*
* McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
* 730 has only 2 McBSP, and both of them are MPU peripherals.
*/
int
__devinit
omap_mcbsp_init
(
struct
platform_device
*
pdev
)
{
struct
omap_mcbsp
*
mcbsp
=
platform_get_drvdata
(
pdev
);
struct
resource
*
res
;
int
ret
=
0
;
spin_lock_init
(&
mcbsp
->
lock
);
mcbsp
->
free
=
true
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"mpu"
);
if
(!
res
) {
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(!
res
) {
dev_err
(
mcbsp
->
dev
,
"invalid memory resource
\n
"
);
return
-
ENOMEM
;
}
}
if
(!
devm_request_mem_region
(&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
),
dev_name
(&
pdev
->
dev
))) {
dev_err
(
mcbsp
->
dev
,
"memory region already claimed
\n
"
);
return
-
ENODEV
;
}
mcbsp
->
phys_base
=
res
->
start
;
mcbsp
->
reg_cache_size
=
resource_size
(
res
);
mcbsp
->
io_base
=
devm_ioremap
(&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
));
if
(!
mcbsp
->
io_base
)
return
-
ENOMEM
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"dma"
);
if
(!
res
)
mcbsp
->
phys_dma_base
=
mcbsp
->
phys_base
;
else
mcbsp
->
phys_dma_base
=
res
->
start
;
/*
* OMAP1, 2 uses two interrupt lines: TX, RX
* OMAP2430, OMAP3 SoC have combined IRQ line as well.
* OMAP4 and newer SoC only have the combined IRQ line.
* Use the combined IRQ if available since it gives better debugging
* possibilities.
*/
mcbsp
->
irq
=
platform_get_irq_byname
(
pdev
,
"common"
);
if
(
mcbsp
->
irq
== -
ENXIO
) {
mcbsp
->
tx_irq
=
platform_get_irq_byname
(
pdev
,
"tx"
);
if
(
mcbsp
->
tx_irq
== -
ENXIO
) {
mcbsp
->
irq
=
platform_get_irq
(
pdev
,
0
);
mcbsp
->
tx_irq
=
0
;
}
else
{
mcbsp
->
rx_irq
=
platform_get_irq_byname
(
pdev
,
"rx"
);
mcbsp
->
irq
=
0
;
}
}
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"rx"
);
if
(!
res
) {
dev_err
(&
pdev
->
dev
,
"invalid rx DMA channel
\n
"
);
return
-
ENODEV
;
}
/* RX DMA request number, and port address configuration */
mcbsp
->
dma_data
[
1
].
name
=
"Audio Capture"
;
mcbsp
->
dma_data
[
1
].
dma_req
=
res
->
start
;
mcbsp
->
dma_data
[
1
].
port_addr
=
omap_mcbsp_dma_reg_params
(
mcbsp
,
1
);
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"tx"
);
if
(!
res
) {
dev_err
(&
pdev
->
dev
,
"invalid tx DMA channel
\n
"
);
return
-
ENODEV
;
}
/* TX DMA request number, and port address configuration */
mcbsp
->
dma_data
[
0
].
name
=
"Audio Playback"
;
mcbsp
->
dma_data
[
0
].
dma_req
=
res
->
start
;
mcbsp
->
dma_data
[
0
].
port_addr
=
omap_mcbsp_dma_reg_params
(
mcbsp
,
0
);
mcbsp
->
fclk
=
clk_get
(&
pdev
->
dev
,
"fck"
);
if
(
IS_ERR
(
mcbsp
->
fclk
)) {
ret
=
PTR_ERR
(
mcbsp
->
fclk
);
dev_err
(
mcbsp
->
dev
,
"unable to get fck: %d
\n
"
,
ret
);
return
ret
;
}
mcbsp
->
dma_op_mode
=
MCBSP_DMA_MODE_ELEMENT
;
if
(
mcbsp
->
pdata
->
buffer_size
) {
/*
* Initially configure the maximum thresholds to a safe value.
* The McBSP FIFO usage with these values should not go under
* 16 locations.
* If the whole FIFO without safety buffer is used, than there
* is a possibility that the DMA will be not able to push the
* new data on time, causing channel shifts in runtime.
*/
mcbsp
->
max_tx_thres
=
max_thres
(
mcbsp
) -
0x10
;
mcbsp
->
max_rx_thres
=
max_thres
(
mcbsp
) -
0x10
;
ret
=
sysfs_create_group
(&
mcbsp
->
dev
->
kobj
,
&
additional_attr_group
);
if
(
ret
) {
dev_err
(
mcbsp
->
dev
,
"Unable to create additional controls
\n
"
);
goto
err_thres
;
}
}
else
{
mcbsp
->
max_tx_thres
= -
EINVAL
;
mcbsp
->
max_rx_thres
= -
EINVAL
;
}
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"sidetone"
);
if
(
res
) {
ret
=
omap_st_add
(
mcbsp
,
res
);
if
(
ret
) {
dev_err
(
mcbsp
->
dev
,
"Unable to create sidetone controls
\n
"
);
goto
err_st
;
}
}
return
0
;
err_st
:
if
(
mcbsp
->
pdata
->
buffer_size
)
sysfs_remove_group
(&
mcbsp
->
dev
->
kobj
, &
additional_attr_group
);
err_thres
:
clk_put
(
mcbsp
->
fclk
);
return
ret
;
}
void
__devexit
omap_mcbsp_sysfs_remove
(
struct
omap_mcbsp
*
mcbsp
)
{
if
(
mcbsp
->
pdata
->
buffer_size
)
sysfs_remove_group
(&
mcbsp
->
dev
->
kobj
, &
additional_attr_group
);
if
(
mcbsp
->
st_data
)
sysfs_remove_group
(&
mcbsp
->
dev
->
kobj
, &
sidetone_attr_group
);
}