Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
cd12de1f
Commit
cd12de1f
authored
Sep 28, 2006
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Plain Diff
Merge source.mvista.com:/home/git/linux-omap-2.6
parents
322bd187
5ea9c88f
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
174 additions
and
77 deletions
+174
-77
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-nokia770.c
+5
-3
arch/arm/mach-omap1/mailbox.c
arch/arm/mach-omap1/mailbox.c
+31
-20
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.c
+2
-11
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/io.c
+2
-0
arch/arm/mach-omap2/memory.c
arch/arm/mach-omap2/memory.c
+48
-0
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dma.c
+18
-7
arch/arm/plat-omap/dsp/dsp_common.c
arch/arm/plat-omap/dsp/dsp_common.c
+2
-4
arch/arm/plat-omap/dsp/dsp_common.h
arch/arm/plat-omap/dsp/dsp_common.h
+3
-0
arch/arm/plat-omap/dsp/dsp_core.c
arch/arm/plat-omap/dsp/dsp_core.c
+26
-11
arch/arm/plat-omap/dsp/dsp_ctl_core.c
arch/arm/plat-omap/dsp/dsp_ctl_core.c
+14
-0
arch/arm/plat-omap/dsp/dsp_mem.c
arch/arm/plat-omap/dsp/dsp_mem.c
+16
-21
arch/arm/plat-omap/dsp/ipbuf.c
arch/arm/plat-omap/dsp/ipbuf.c
+1
-0
include/asm-arm/arch-omap/omap16xx.h
include/asm-arm/arch-omap/omap16xx.h
+3
-0
include/asm-arm/arch-omap/omap24xx.h
include/asm-arm/arch-omap/omap24xx.h
+3
-0
No files found.
arch/arm/mach-omap1/board-nokia770.c
View file @
cd12de1f
...
...
@@ -212,7 +212,7 @@ static void nokia770_audio_pwr_down(void)
schedule_delayed_work
(
&
codec_power_down_work
,
HZ
/
20
);
/* 50ms */
}
static
void
static
int
nokia770_audio_pwr_up_request
(
struct
dsp_kfunc_device
*
kdev
,
int
stage
)
{
down
(
&
audio_pwr_sem
);
...
...
@@ -221,9 +221,10 @@ nokia770_audio_pwr_up_request(struct dsp_kfunc_device *kdev, int stage)
/* force audio_pwr_state = 0, even if it was 1. */
audio_pwr_state
=
0
;
up
(
&
audio_pwr_sem
);
return
0
;
}
static
void
static
int
nokia770_audio_pwr_down_request
(
struct
dsp_kfunc_device
*
kdev
,
int
stage
)
{
down
(
&
audio_pwr_sem
);
...
...
@@ -240,6 +241,7 @@ nokia770_audio_pwr_down_request(struct dsp_kfunc_device *kdev, int stage)
break
;
}
up
(
&
audio_pwr_sem
);
return
0
;
}
static
struct
dsp_kfunc_device
nokia770_audio_device
=
{
...
...
@@ -263,7 +265,7 @@ static __init int omap_dsp_init(void)
if
(
ret
)
{
printk
(
KERN_ERR
"KFUNC device registration faild: %s
\n
"
,
dsp
_audio_device
.
name
);
nokia770
_audio_device
.
name
);
goto
out
;
}
return
0
;
...
...
arch/arm/mach-omap1/mailbox.c
View file @
cd12de1f
...
...
@@ -9,8 +9,10 @@
* for more details.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/resource.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/arch/mailbox.h>
#include <asm/arch/irqs.h>
#include <asm/io.h>
...
...
@@ -28,9 +30,9 @@
unsigned
long
mbox_base
;
struct
omap_mbox1_fifo
{
void
*
cmd
;
void
*
data
;
void
*
flag
;
unsigned
long
cmd
;
unsigned
long
data
;
unsigned
long
flag
;
};
struct
omap_mbox1_priv
{
...
...
@@ -51,7 +53,8 @@ static inline void mbox_write_reg(unsigned int val, unsigned int reg)
/* msg */
static
inline
mbox_msg_t
omap1_mbox_fifo_read
(
struct
omap_mbox
*
mbox
)
{
struct
omap_mbox1_fifo
*
fifo
=
&
((
struct
omap_mbox1_priv
*
)
mbox
->
priv
)
->
rx_fifo
;
struct
omap_mbox1_fifo
*
fifo
=
&
((
struct
omap_mbox1_priv
*
)
mbox
->
priv
)
->
rx_fifo
;
mbox_msg_t
msg
;
msg
=
mbox_read_reg
(
fifo
->
data
);
...
...
@@ -60,9 +63,11 @@ static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
return
msg
;
}
static
inline
void
omap1_mbox_fifo_write
(
struct
omap_mbox
*
mbox
,
mbox_msg_t
msg
)
static
inline
void
omap1_mbox_fifo_write
(
struct
omap_mbox
*
mbox
,
mbox_msg_t
msg
)
{
struct
omap_mbox1_fifo
*
fifo
=
&
((
struct
omap_mbox1_priv
*
)
mbox
->
priv
)
->
rx_fifo
;
struct
omap_mbox1_fifo
*
fifo
=
&
((
struct
omap_mbox1_priv
*
)
mbox
->
priv
)
->
rx_fifo
;
mbox_write_reg
(
msg
&
0xffff
,
fifo
->
data
);
mbox_write_reg
(
msg
>>
16
,
fifo
->
cmd
);
...
...
@@ -75,23 +80,29 @@ static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
static
inline
int
omap1_mbox_fifo_full
(
struct
omap_mbox
*
mbox
)
{
struct
omap_mbox1_fifo
*
fifo
=
&
((
struct
omap_mbox1_priv
*
)
mbox
->
priv
)
->
rx_fifo
;
return
(
mbox_read_reg
(
fifo
->
flag
));
}
/* irq */
static
inline
void
omap1_mbox_enable_irq
(
struct
omap_mbox
*
mbox
,
omap_mbox_type_t
irq
)
static
inline
void
omap1_mbox_enable_irq
(
struct
omap_mbox
*
mbox
,
omap_mbox_type_t
irq
)
{
if
(
irq
==
IRQ_RX
)
enable_irq
(
mbox
->
irq
);
}
static
inline
void
omap1_mbox_disable_irq
(
struct
omap_mbox
*
mbox
,
omap_mbox_type_t
irq
)
static
inline
void
omap1_mbox_disable_irq
(
struct
omap_mbox
*
mbox
,
omap_mbox_type_t
irq
)
{
if
(
irq
==
IRQ_RX
)
disble_irq
(
mbox
->
irq
);
dis
a
ble_irq
(
mbox
->
irq
);
}
static
inline
int
omap1_mbox_is_irq
(
struct
omap_mbox
*
mbox
,
omap_mbox_type_t
irq
)
static
inline
int
omap1_mbox_is_irq
(
struct
omap_mbox
*
mbox
,
omap_mbox_type_t
irq
)
{
if
(
irq
==
IRQ_TX
)
return
0
;
...
...
@@ -111,22 +122,22 @@ struct omap_mbox_ops omap1_mbox_ops = {
/* FIXME: the following struct should be created automatically by the user id */
/* DSP */
static
struct
omap_mbox
2
_priv
omap1_mbox_dsp_priv
=
{
static
struct
omap_mbox
1
_priv
omap1_mbox_dsp_priv
=
{
.
tx_fifo
=
{
.
cmd
=
(
void
*
)
MAILBOX_ARM2DSP1b
,
.
data
=
(
void
*
)
MAILBOX_ARM2DSP1
,
.
flag
=
(
void
*
)
MAILBOX_ARM2DSP1_Flag
,
.
cmd
=
MAILBOX_ARM2DSP1b
,
.
data
=
MAILBOX_ARM2DSP1
,
.
flag
=
MAILBOX_ARM2DSP1_Flag
,
},
.
rx_fifo
=
{
.
cmd
=
(
void
*
)
MAILBOX_DSP2ARM1b
,
.
data
=
(
void
*
)
MAILBOX_DSP2ARM1
,
.
flag
=
(
void
*
)
MAILBOX_DSP2ARM1_Flag
,
.
cmd
=
MAILBOX_DSP2ARM1b
,
.
data
=
MAILBOX_DSP2ARM1
,
.
flag
=
MAILBOX_DSP2ARM1_Flag
,
},
};
struct
omap_mbox
mbox_dsp_info
=
{
.
name
=
"DSP"
,
.
ops
=
&
omap1_mbox_ops
,
.
ops
=
&
omap1_mbox_ops
,
.
priv
=
&
omap1_mbox_dsp_priv
,
};
...
...
@@ -170,7 +181,7 @@ static int omap1_mbox_remove(struct platform_device *pdev)
}
static
struct
platform_driver
omap1_mbox_driver
=
{
.
probe
=
omap1_mbox_probe
,
.
probe
=
omap1_mbox_probe
,
.
remove
=
omap1_mbox_remove
,
.
driver
=
{
.
name
=
"mailbox"
,
...
...
arch/arm/mach-omap2/clock.c
View file @
cd12de1f
...
...
@@ -1159,8 +1159,8 @@ int __init omap2_clk_init(void)
clk_enable
(
&
sync_32k_ick
);
clk_enable
(
&
omapctrl_ick
);
/* Force the APLLs a
ctive during bootup to avoid disabling an
d
*
enabling them unnecessarily
. */
/* Force the APLLs a
lways active. The clocks are idle
d
*
automatically by hardware
. */
clk_enable
(
&
apll96_ck
);
clk_enable
(
&
apll54_ck
);
...
...
@@ -1173,12 +1173,3 @@ int __init omap2_clk_init(void)
return
0
;
}
static
int
__init
omap2_disable_aplls
(
void
)
{
clk_disable
(
&
apll96_ck
);
clk_disable
(
&
apll54_ck
);
return
0
;
}
late_initcall
(
omap2_disable_aplls
);
arch/arm/mach-omap2/io.c
View file @
cd12de1f
...
...
@@ -26,6 +26,7 @@
extern
void
omap_sram_init
(
void
);
extern
int
omap2_clk_init
(
void
);
extern
void
omap2_check_revision
(
void
);
extern
void
omap2_init_memory
(
void
);
extern
void
gpmc_init
(
void
);
/*
...
...
@@ -85,5 +86,6 @@ void __init omap2_init_common_hw(void)
{
omap2_mux_init
();
omap2_clk_init
();
omap2_init_memory
();
gpmc_init
();
}
arch/arm/mach-omap2/memory.c
View file @
cd12de1f
...
...
@@ -30,6 +30,38 @@
#include "prcm-regs.h"
#include "memory.h"
#define SMS_BASE 0x68008000
#define SMS_SYSCONFIG 0x010
#define SDRC_BASE 0x68009000
#define SDRC_SYSCONFIG 0x010
#define SDRC_SYSSTATUS 0x014
static
const
u32
sms_base
=
IO_ADDRESS
(
SMS_BASE
);
static
const
u32
sdrc_base
=
IO_ADDRESS
(
SDRC_BASE
);
static
inline
void
sms_write_reg
(
int
idx
,
u32
val
)
{
__raw_writel
(
val
,
sms_base
+
idx
);
}
static
inline
u32
sms_read_reg
(
int
idx
)
{
return
__raw_readl
(
sms_base
+
idx
);
}
static
inline
void
sdrc_write_reg
(
int
idx
,
u32
val
)
{
__raw_writel
(
val
,
sdrc_base
+
idx
);
}
static
inline
u32
sdrc_read_reg
(
int
idx
)
{
return
__raw_readl
(
sdrc_base
+
idx
);
}
static
struct
memory_timings
mem_timings
;
u32
omap2_memory_get_slow_dll_ctrl
(
void
)
...
...
@@ -99,3 +131,19 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
/* 90 degree phase for anything below 133Mhz + disable DLL filter */
mem_timings
.
slow_dll_ctrl
|=
((
1
<<
1
)
|
(
3
<<
8
));
}
void
__init
omap2_init_memory
(
void
)
{
u32
l
;
l
=
sms_read_reg
(
SMS_SYSCONFIG
);
l
&=
~
(
0x3
<<
3
);
l
|=
(
0x2
<<
3
);
sms_write_reg
(
SMS_SYSCONFIG
,
l
);
l
=
sdrc_read_reg
(
SDRC_SYSCONFIG
);
l
&=
~
(
0x3
<<
3
);
l
|=
(
0x2
<<
3
);
sdrc_write_reg
(
SDRC_SYSCONFIG
,
l
);
}
arch/arm/plat-omap/dma.c
View file @
cd12de1f
...
...
@@ -930,10 +930,17 @@ static int omap2_dma_handle_ch(int ch)
u32
status
=
OMAP_DMA_CSR_REG
(
ch
);
u32
val
;
if
(
!
status
)
if
(
!
status
)
{
if
(
printk_ratelimit
())
printk
(
KERN_WARNING
"Spurious DMA IRQ for lch %d
\n
"
,
ch
);
return
0
;
if
(
unlikely
(
dma_chan
[
ch
].
dev_id
==
-
1
))
}
if
(
unlikely
(
dma_chan
[
ch
].
dev_id
==
-
1
))
{
if
(
printk_ratelimit
())
printk
(
KERN_WARNING
"IRQ %04x for non-allocated DMA"
"channel %d
\n
"
,
status
,
ch
);
return
0
;
}
if
(
unlikely
(
status
&
OMAP_DMA_DROP_IRQ
))
printk
(
KERN_INFO
"DMA synchronization event drop occurred with device "
...
...
@@ -969,11 +976,15 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id,
int
i
;
val
=
omap_readl
(
OMAP_DMA4_IRQSTATUS_L0
);
for
(
i
=
1
;
i
<=
OMAP_LOGICAL_DMA_CH_COUNT
;
i
++
)
{
int
active
=
val
&
(
1
<<
(
i
-
1
));
if
(
active
)
omap2_dma_handle_ch
(
i
-
1
);
if
(
val
==
0
)
{
if
(
printk_ratelimit
())
printk
(
KERN_WARNING
"Spurious DMA IRQ
\n
"
);
return
IRQ_HANDLED
;
}
for
(
i
=
0
;
i
<
OMAP_LOGICAL_DMA_CH_COUNT
&&
val
!=
0
;
i
++
)
{
if
(
val
&
1
)
omap2_dma_handle_ch
(
i
);
val
>>=
1
;
}
return
IRQ_HANDLED
;
...
...
arch/arm/plat-omap/dsp/dsp_common.c
View file @
cd12de1f
...
...
@@ -305,8 +305,6 @@ static int __init omap_dsp_init(void)
return
-
ENODEV
;
}
dsp_clk_autoidle
();
#if defined(CONFIG_ARCH_OMAP1)
dsp_ck_handle
=
clk_get
(
NULL
,
"dsp_ck"
);
if
(
IS_ERR
(
dsp_ck_handle
))
{
...
...
@@ -347,12 +345,12 @@ static int __init omap_dsp_init(void)
}
#if defined(CONFIG_ARCH_OMAP1)
static
int
dsp_late_init
(
void
)
static
int
__
dsp_late_init
(
void
)
{
clk_disable
(
api_ck_handle
);
return
0
;
}
late_initcall
(
dsp_late_init
);
late_initcall
(
__
dsp_late_init
);
#endif
static
void
dsp_cpustat_update
(
void
)
...
...
arch/arm/plat-omap/dsp/dsp_common.h
View file @
cd12de1f
...
...
@@ -189,6 +189,7 @@ struct omap_dsp {
struct
omap_mbox
*
mbox
;
struct
device
*
dev
;
struct
list_head
*
kdev_list
;
int
initialized
;
};
#if defined(CONFIG_ARCH_OMAP1)
...
...
@@ -203,4 +204,6 @@ struct omap_dsp {
extern
struct
omap_dsp
*
omap_dsp
;
extern
int
dsp_late_init
(
void
);
#endif
/* DRIVER_DSP_COMMON_H */
arch/arm/plat-omap/dsp/dsp_core.c
View file @
cd12de1f
...
...
@@ -45,6 +45,8 @@ static struct sync_seq *mbseq;
static
u16
mbseq_expect_tmp
;
static
u16
*
mbseq_expect
=
&
mbseq_expect_tmp
;
extern
void
dsp_mem_late_init
(
void
);
/*
* mailbox commands
*/
...
...
@@ -511,6 +513,30 @@ static void mbox_kfunc(struct mbcmd *mb)
}
}
int
dsp_late_init
(
void
)
{
int
ret
;
dsp_clk_autoidle
();
#ifdef CONFIG_ARCH_OMAP2
clk_enable
(
dsp_fck_handle
);
clk_enable
(
dsp_ick_handle
);
__dsp_per_enable
();
#endif
dsp_mem_late_init
();
#ifdef CONFIG_ARCH_OMAP1
dsp_set_idle_boot_base
(
IDLEPG_BASE
,
IDLEPG_SIZE
);
#endif
ret
=
dsp_kfunc_enable_devices
(
omap_dsp
,
DSP_KFUNC_DEV_TYPE_COMMON
,
0
);
if
(
ret
==
0
)
omap_dsp
->
enabled
=
0
;
return
0
;
}
extern
int
dsp_ctl_core_init
(
void
);
extern
void
dsp_ctl_core_exit
(
void
);
extern
void
dsp_ctl_init
(
void
);
...
...
@@ -557,12 +583,6 @@ static int __init dsp_drv_probe(struct platform_device *pdev)
goto
fail1
;
}
#ifdef CONFIG_ARCH_OMAP2
clk_enable
(
dsp_fck_handle
);
clk_enable
(
dsp_ick_handle
);
__dsp_per_enable
();
#endif
if
((
ret
=
dsp_ctl_core_init
())
<
0
)
goto
fail2
;
if
((
ret
=
dsp_mem_init
())
<
0
)
...
...
@@ -585,11 +605,6 @@ static int __init dsp_drv_probe(struct platform_device *pdev)
fail3:
dsp_ctl_core_exit
();
fail2:
#ifdef CONFIG_ARCH_OMAP2
__dsp_per_disable
();
clk_disable
(
dsp_ick_handle
);
clk_disable
(
dsp_fck_handle
);
#endif
fail1:
dsp_kfunc_remove_devices
(
info
);
fail0:
...
...
arch/arm/plat-omap/dsp/dsp_ctl_core.c
View file @
cd12de1f
...
...
@@ -40,6 +40,20 @@ extern struct file_operations dsp_ctl_fops,
static
int
dsp_ctl_core_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
static
DEFINE_MUTEX
(
open_lock
);
int
ret
=
0
;
mutex_lock_interruptible
(
&
open_lock
);
if
(
omap_dsp
->
initialized
==
0
)
{
ret
=
dsp_late_init
();
if
(
ret
!=
0
)
{
mutex_unlock
(
&
open_lock
);
return
ret
;
}
omap_dsp
->
initialized
=
1
;
}
mutex_unlock
(
&
open_lock
);
switch
(
iminor
(
inode
))
{
case
CTL_MINOR
:
file
->
f_op
=
&
dsp_ctl_fops
;
...
...
arch/arm/plat-omap/dsp/dsp_mem.c
View file @
cd12de1f
...
...
@@ -2453,24 +2453,32 @@ void dsp_mem_stop(void)
#endif
}
static
char
devid_mmu
;
int
__init
dsp_mem_init
(
void
)
/*
* later half of dsp memory initialization
*/
void
dsp_mem_late_init
(
void
)
{
int
i
;
int
ret
=
0
;
#ifdef CONFIG_ARCH_OMAP2
int
i
;
int
dspmem_pg_count
;
dspmem_pg_count
=
dspmem_size
>>
12
;
for
(
i
=
0
;
i
<
dspmem_pg_count
;
i
++
)
{
dsp_ipi_write_reg
(
i
,
DSP_IPI_INDEX
);
dsp_ipi_write_reg
(
DSP_IPI_ENTRY_ELMSIZEVALUE_16
,
DSP_IPI_ENTRY
);
dsp_ipi_write_reg
(
DSP_IPI_ENTRY_ELMSIZEVALUE_16
,
DSP_IPI_ENTRY
);
}
dsp_ipi_write_reg
(
1
,
DSP_IPI_ENABLE
);
dsp_ipi_write_reg
(
IOMAP_VAL
,
DSP_IPI_IOMAP
);
#endif
dsp_mmu_init
();
}
static
char
devid_mmu
;
int
__init
dsp_mem_init
(
void
)
{
int
i
,
ret
;
for
(
i
=
0
;
i
<
DSP_MMU_TLB_LINES
;
i
++
)
exmap_tbl
[
i
].
valid
=
0
;
...
...
@@ -2482,10 +2490,6 @@ int __init dsp_mem_init(void)
"for dsp vector table
\n
"
);
return
-
ENOMEM
;
}
dsp_mmu_init
();
#ifdef CONFIG_ARCH_OMAP1
dsp_set_idle_boot_base
(
IDLEPG_BASE
,
IDLEPG_SIZE
);
#endif
/*
* DSP MMU interrupt setup
...
...
@@ -2495,7 +2499,7 @@ int __init dsp_mem_init(void)
if
(
ret
)
{
printk
(
KERN_ERR
"failed to register DSP MMU interrupt: %d
\n
"
,
ret
);
goto
fail
;
return
ret
;
}
/* MMU interrupt is not enabled until DSP runs */
...
...
@@ -2506,15 +2510,6 @@ int __init dsp_mem_init(void)
device_create_file
(
omap_dsp
->
dev
,
&
dev_attr_mempool
);
return
0
;
fail:
#ifdef CONFIG_ARCH_OMAP1
dsp_reset_idle_boot_base
();
#endif
dsp_mmu_shutdown
();
free_page
((
unsigned
long
)
dspvect_page
);
dspvect_page
=
NULL
;
return
ret
;
}
void
dsp_mem_exit
(
void
)
...
...
arch/arm/plat-omap/dsp/ipbuf.c
View file @
cd12de1f
...
...
@@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <asm/arch/mailbox.h>
#include "dsp_mbcmd.h"
#include "dsp.h"
...
...
include/asm-arm/arch-omap/omap16xx.h
View file @
cd12de1f
...
...
@@ -190,5 +190,8 @@
#define WSPR_DISABLE_0 (0x0000aaaa)
#define WSPR_DISABLE_1 (0x00005555)
/* Mailbox */
#define OMAP16XX_MAILBOX_BASE (0xfffcf000)
#endif
/* __ASM_ARCH_OMAP16XX_H */
include/asm-arm/arch-omap/omap24xx.h
View file @
cd12de1f
...
...
@@ -28,5 +28,8 @@
#define OMAP24XX_DSP_IPI_BASE (OMAP24XX_DSP_BASE + 0x1000000)
#define OMAP24XX_DSP_MMU_BASE (OMAP24XX_DSP_BASE + 0x2000000)
/* Mailbox */
#define OMAP24XX_MAILBOX_BASE (L4_24XX_BASE + 0x94000)
#endif
/* __ASM_ARCH_OMAP24XX_H */
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