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
88b6f7eb
Commit
88b6f7eb
authored
May 26, 2009
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'omap-clock-upstream' of
git://git.pwsan.com/linux-2.6
into for-next
parents
8f9ccfee
79716870
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
128 additions
and
86 deletions
+128
-86
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap1/clock.c
+1
-1
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.c
+7
-7
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/clock24xx.c
+1
-1
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx.c
+14
-6
arch/arm/mach-omap2/sdrc.c
arch/arm/mach-omap2/sdrc.c
+18
-1
arch/arm/mach-omap2/sram34xx.S
arch/arm/mach-omap2/sram34xx.S
+67
-62
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/clock.c
+2
-2
arch/arm/plat-omap/include/mach/clock.h
arch/arm/plat-omap/include/mach/clock.h
+1
-1
arch/arm/plat-omap/include/mach/sram.h
arch/arm/plat-omap/include/mach/sram.h
+4
-2
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/sram.c
+13
-3
No files found.
arch/arm/mach-omap1/clock.c
View file @
88b6f7eb
...
...
@@ -776,7 +776,7 @@ int __init omap1_clk_init(void)
arm_idlect1_mask
=
~
0
;
for
(
c
=
omap_clks
;
c
<
omap_clks
+
ARRAY_SIZE
(
omap_clks
);
c
++
)
clk_
init_one
(
c
->
lk
.
clk
);
clk_
preinit
(
c
->
lk
.
clk
);
cpu_mask
=
0
;
if
(
cpu_is_omap16xx
())
...
...
arch/arm/mach-omap2/clock.c
View file @
88b6f7eb
...
...
@@ -547,8 +547,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
const
struct
clksel_rate
*
clkr
;
u32
last_div
=
0
;
pr
intk
(
KERN_INFO
"clock: clksel_round_rate_div: %s target_rate %ld
\n
"
,
clk
->
name
,
target_rate
);
pr
_debug
(
"clock: clksel_round_rate_div: %s target_rate %ld
\n
"
,
clk
->
name
,
target_rate
);
*
new_div
=
1
;
...
...
@@ -562,7 +562,7 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
/* Sanity check */
if
(
clkr
->
div
<=
last_div
)
pr
intk
(
KERN_ERR
"clock: clksel_rate table not sorted "
pr
_err
(
"clock: clksel_rate table not sorted "
"for clock %s"
,
clk
->
name
);
last_div
=
clkr
->
div
;
...
...
@@ -574,7 +574,7 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
}
if
(
!
clkr
->
div
)
{
pr
intk
(
KERN_ERR
"clock: Could not find divisor for target "
pr
_err
(
"clock: Could not find divisor for target "
"rate %ld for clock %s parent %s
\n
"
,
target_rate
,
clk
->
name
,
clk
->
parent
->
name
);
return
~
0
;
...
...
@@ -582,8 +582,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
*
new_div
=
clkr
->
div
;
pr
intk
(
KERN_INFO
"clock: new_div = %d, new_rate = %ld
\n
"
,
*
new_div
,
(
clk
->
parent
->
rate
/
clkr
->
div
));
pr
_debug
(
"clock: new_div = %d, new_rate = %ld
\n
"
,
*
new_div
,
(
clk
->
parent
->
rate
/
clkr
->
div
));
return
(
clk
->
parent
->
rate
/
clkr
->
div
);
}
...
...
@@ -1035,7 +1035,7 @@ void omap2_clk_disable_unused(struct clk *clk)
if
((
regval32
&
(
1
<<
clk
->
enable_bit
))
==
v
)
return
;
printk
(
KERN_
INFO
"Disabling unused clock
\"
%s
\"\n
"
,
clk
->
name
);
printk
(
KERN_
DEBUG
"Disabling unused clock
\"
%s
\"\n
"
,
clk
->
name
);
if
(
cpu_is_omap34xx
())
{
omap2_clk_enable
(
clk
);
omap2_clk_disable
(
clk
);
...
...
arch/arm/mach-omap2/clock24xx.c
View file @
88b6f7eb
...
...
@@ -725,7 +725,7 @@ int __init omap2_clk_init(void)
clk_init
(
&
omap2_clk_functions
);
for
(
c
=
omap24xx_clks
;
c
<
omap24xx_clks
+
ARRAY_SIZE
(
omap24xx_clks
);
c
++
)
clk_
init_one
(
c
->
lk
.
clk
);
clk_
preinit
(
c
->
lk
.
clk
);
osc_ck
.
rate
=
omap2_osc_clk_recalc
(
&
osc_ck
);
propagate_rate
(
&
osc_ck
);
...
...
arch/arm/mach-omap2/clock34xx.c
View file @
88b6f7eb
...
...
@@ -281,6 +281,8 @@ static struct omap_clk omap34xx_clks[] = {
#define MAX_DPLL_WAIT_TRIES 1000000
#define MIN_SDRC_DLL_LOCK_FREQ 83000000
/**
* omap3_dpll_recalc - recalculate DPLL rate
* @clk: DPLL struct clk
...
...
@@ -703,6 +705,7 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
static
int
omap3_core_dpll_m2_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
new_div
=
0
;
u32
unlock_dll
=
0
;
unsigned
long
validrate
,
sdrcrate
;
struct
omap_sdrc_params
*
sp
;
...
...
@@ -729,17 +732,22 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
if
(
!
sp
)
return
-
EINVAL
;
pr_info
(
"clock: changing CORE DPLL rate from %lu to %lu
\n
"
,
clk
->
rate
,
validrate
);
pr_info
(
"clock: SDRC timing params used: %08x %08x %08x
\n
"
,
sp
->
rfr_ctrl
,
sp
->
actim_ctrla
,
sp
->
actim_ctrlb
);
if
(
sdrcrate
<
MIN_SDRC_DLL_LOCK_FREQ
)
{
pr_debug
(
"clock: will unlock SDRC DLL
\n
"
);
unlock_dll
=
1
;
}
pr_debug
(
"clock: changing CORE DPLL rate from %lu to %lu
\n
"
,
clk
->
rate
,
validrate
);
pr_debug
(
"clock: SDRC timing params used: %08x %08x %08x
\n
"
,
sp
->
rfr_ctrl
,
sp
->
actim_ctrla
,
sp
->
actim_ctrlb
);
/* REVISIT: SRAM code doesn't support other M2 divisors yet */
WARN_ON
(
new_div
!=
1
&&
new_div
!=
2
);
/* REVISIT: Add SDRC_MR changing to this code also */
omap3_configure_core_dpll
(
sp
->
rfr_ctrl
,
sp
->
actim_ctrla
,
sp
->
actim_ctrlb
,
new_div
);
sp
->
actim_ctrlb
,
new_div
,
unlock_dll
);
return
0
;
}
...
...
@@ -956,7 +964,7 @@ int __init omap2_clk_init(void)
clk_init
(
&
omap2_clk_functions
);
for
(
c
=
omap34xx_clks
;
c
<
omap34xx_clks
+
ARRAY_SIZE
(
omap34xx_clks
);
c
++
)
clk_
init_one
(
c
->
lk
.
clk
);
clk_
preinit
(
c
->
lk
.
clk
);
for
(
c
=
omap34xx_clks
;
c
<
omap34xx_clks
+
ARRAY_SIZE
(
omap34xx_clks
);
c
++
)
if
(
c
->
cpu
&
cpu_clkflg
)
{
...
...
arch/arm/mach-omap2/sdrc.c
View file @
88b6f7eb
...
...
@@ -37,6 +37,10 @@ static struct omap_sdrc_params *sdrc_init_params;
void
__iomem
*
omap2_sdrc_base
;
void
__iomem
*
omap2_sms_base
;
/* SDRC_POWER register bits */
#define SDRC_POWER_EXTCLKDIS_SHIFT 3
#define SDRC_POWER_PWDENA_SHIFT 2
#define SDRC_POWER_PAGEPOLICY_SHIFT 0
/**
* omap2_sdrc_get_params - return SDRC register values for a given clock rate
...
...
@@ -74,7 +78,14 @@ void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
omap2_sms_base
=
omap2_globals
->
sms
;
}
/* turn on smart idle modes for SDRAM scheduler and controller */
/**
* omap2_sdrc_init - initialize SMS, SDRC devices on boot
* @sp: pointer to a null-terminated list of struct omap_sdrc_params
*
* Turn on smart idle modes for SDRAM scheduler and controller.
* Program a known-good configuration for the SDRC to deal with buggy
* bootloaders.
*/
void
__init
omap2_sdrc_init
(
struct
omap_sdrc_params
*
sp
)
{
u32
l
;
...
...
@@ -90,4 +101,10 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
sdrc_write_reg
(
l
,
SDRC_SYSCONFIG
);
sdrc_init_params
=
sp
;
/* XXX Enable SRFRONIDLEREQ here also? */
l
=
(
1
<<
SDRC_POWER_EXTCLKDIS_SHIFT
)
|
(
1
<<
SDRC_POWER_PWDENA_SHIFT
)
|
(
1
<<
SDRC_POWER_PAGEPOLICY_SHIFT
);
sdrc_write_reg
(
l
,
SDRC_POWER
);
}
arch/arm/mach-omap2/sram34xx.S
View file @
88b6f7eb
...
...
@@ -40,69 +40,74 @@
/*
*
Change
frequency
of
core
dpll
*
r0
=
sdrc_rfr_ctrl
r1
=
sdrc_actim_ctrla
r2
=
sdrc_actim_ctrlb
r3
=
M2
*
r4
=
Unlock
SDRC
DLL
?
(
1
=
yes
,
0
=
no
)
--
only
unlock
DLL
for
*
SDRC
rates
<
83
MHz
*/
ENTRY
(
omap3_sram_configure_core_dpll
)
stmfd
sp
!,
{
r1
-
r12
,
lr
}
@
store
regs
to
stack
ldr
r4
,
[
sp
,
#
52
]
@
pull
extra
args
off
the
stack
dsb
@
flush
buffered
writes
to
interconnect
cmp
r3
,
#
0x2
blne
configure_sdrc
cmp
r3
,
#
0x2
cmp
r4
,
#
0x1
bleq
unlock_dll
blne
lock_dll
cmp
r3
,
#
0x1
blne
unlock_dll
bl
sdram_in_selfrefresh
@
put
the
SDRAM
in
self
refresh
bl
configure_core_dpll
bl
enable_sdrc
cmp
r3
,
#
0x1
blne
wait_dll_unlock
cmp
r3
,
#
0x2
cmp
r4
,
#
0x1
bleq
wait_dll_unlock
blne
wait_dll_lock
cmp
r3
,
#
0x1
blne
configure_sdrc
isb
@
prevent
speculative
exec
past
here
mov
r0
,
#
0
@
return
value
ldmfd
sp
!,
{
r1
-
r12
,
pc
}
@
restore
regs
and
return
unlock_dll
:
ldr
r
4
,
omap3_sdrc_dlla_ctrl
ldr
r
5
,
[
r4
]
orr
r
5
,
r5
,
#
0x4
str
r
5
,
[
r4
]
ldr
r
11
,
omap3_sdrc_dlla_ctrl
ldr
r
12
,
[
r11
]
orr
r
12
,
r12
,
#
0x4
str
r
12
,
[
r11
]
@
(
no
OCP
barrier
needed
)
bx
lr
lock_dll
:
ldr
r
4
,
omap3_sdrc_dlla_ctrl
ldr
r
5
,
[
r4
]
bic
r
5
,
r5
,
#
0x4
str
r
5
,
[
r4
]
ldr
r
11
,
omap3_sdrc_dlla_ctrl
ldr
r
12
,
[
r11
]
bic
r
12
,
r12
,
#
0x4
str
r
12
,
[
r11
]
@
(
no
OCP
barrier
needed
)
bx
lr
sdram_in_selfrefresh
:
mov
r5
,
#
0x0
@
Move
0
to
R5
mcr
p15
,
0
,
r5
,
c7
,
c10
,
5
@
memory
barrier
ldr
r4
,
omap3_sdrc_power
@
read
the
SDRC_POWER
register
ldr
r5
,
[
r4
]
@
read
the
contents
of
SDRC_POWER
orr
r5
,
r5
,
#
0x40
@
enable
self
refresh
on
idle
req
str
r5
,
[
r4
]
@
write
back
to
SDRC_POWER
register
ldr
r4
,
omap3_cm_iclken1_core
@
read
the
CM_ICLKEN1_CORE
reg
ldr
r5
,
[
r4
]
bic
r5
,
r5
,
#
0x2
@
disable
iclk
bit
for
SRDC
str
r5
,
[
r4
]
ldr
r11
,
omap3_sdrc_power
@
read
the
SDRC_POWER
register
ldr
r12
,
[
r11
]
@
read
the
contents
of
SDRC_POWER
mov
r9
,
r12
@
keep
a
copy
of
SDRC_POWER
bits
orr
r12
,
r12
,
#
0x40
@
enable
self
refresh
on
idle
req
bic
r12
,
r12
,
#
0x4
@
clear
PWDENA
str
r12
,
[
r11
]
@
write
back
to
SDRC_POWER
register
ldr
r12
,
[
r11
]
@
posted
-
write
barrier
for
SDRC
ldr
r11
,
omap3_cm_iclken1_core
@
read
the
CM_ICLKEN1_CORE
reg
ldr
r12
,
[
r11
]
bic
r12
,
r12
,
#
0x2
@
disable
iclk
bit
for
SDRC
str
r12
,
[
r11
]
wait_sdrc_idle
:
ldr
r
4
,
omap3_cm_idlest1_core
ldr
r
5
,
[
r4
]
and
r
5
,
r5
,
#
0x2
@
check
for
SDRC
idle
cmp
r
5
,
#
2
ldr
r
11
,
omap3_cm_idlest1_core
ldr
r
12
,
[
r11
]
and
r
12
,
r12
,
#
0x2
@
check
for
SDRC
idle
cmp
r
12
,
#
2
bne
wait_sdrc_idle
bx
lr
configure_core_dpll
:
ldr
r4
,
omap3_cm_clksel1_pll
ldr
r5
,
[
r4
]
ldr
r6
,
core_m2_mask_val
@
modify
m2
for
core
dpll
and
r5
,
r5
,
r6
orr
r5
,
r5
,
r3
,
lsl
#
0x1B
@
r3
contains
the
M2
val
str
r5
,
[
r4
]
mov
r5
,
#
0x800
@
wait
for
the
clock
to
stabilise
ldr
r11
,
omap3_cm_clksel1_pll
ldr
r12
,
[
r11
]
ldr
r10
,
core_m2_mask_val
@
modify
m2
for
core
dpll
and
r12
,
r12
,
r10
orr
r12
,
r12
,
r3
,
lsl
#
0x1B
@
r3
contains
the
M2
val
str
r12
,
[
r11
]
ldr
r12
,
[
r11
]
@
posted
-
write
barrier
for
CM
mov
r12
,
#
0x800
@
wait
for
the
clock
to
stabilise
cmp
r3
,
#
2
bne
wait_clk_stable
bx
lr
wait_clk_stable
:
subs
r
5
,
r5
,
#
1
subs
r
12
,
r12
,
#
1
bne
wait_clk_stable
nop
nop
...
...
@@ -116,42 +121,42 @@ wait_clk_stable:
nop
bx
lr
enable_sdrc
:
ldr
r
4
,
omap3_cm_iclken1_core
ldr
r
5
,
[
r4
]
orr
r
5
,
r5
,
#
0x2
@
enable
iclk
bit
for
SDRC
str
r
5
,
[
r4
]
ldr
r
11
,
omap3_cm_iclken1_core
ldr
r
12
,
[
r11
]
orr
r
12
,
r12
,
#
0x2
@
enable
iclk
bit
for
SDRC
str
r
12
,
[
r11
]
wait_sdrc_idle1
:
ldr
r
4
,
omap3_cm_idlest1_core
ldr
r
5
,
[
r4
]
and
r
5
,
r5
,
#
0x2
cmp
r
5
,
#
0
ldr
r
11
,
omap3_cm_idlest1_core
ldr
r
12
,
[
r11
]
and
r
12
,
r12
,
#
0x2
cmp
r
12
,
#
0
bne
wait_sdrc_idle1
ldr
r4
,
omap3_sdrc_power
ldr
r5
,
[
r4
]
bic
r5
,
r5
,
#
0x40
str
r5
,
[
r4
]
restore_sdrc_power_val
:
ldr
r11
,
omap3_sdrc_power
str
r9
,
[
r11
]
@
restore
SDRC_POWER
,
no
barrier
needed
bx
lr
wait_dll_lock
:
ldr
r
4
,
omap3_sdrc_dlla_status
ldr
r
5
,
[
r4
]
and
r
5
,
r5
,
#
0x4
cmp
r
5
,
#
0x4
ldr
r
11
,
omap3_sdrc_dlla_status
ldr
r
12
,
[
r11
]
and
r
12
,
r12
,
#
0x4
cmp
r
12
,
#
0x4
bne
wait_dll_lock
bx
lr
wait_dll_unlock
:
ldr
r
4
,
omap3_sdrc_dlla_status
ldr
r
5
,
[
r4
]
and
r
5
,
r5
,
#
0x4
cmp
r
5
,
#
0x0
ldr
r
11
,
omap3_sdrc_dlla_status
ldr
r
12
,
[
r11
]
and
r
12
,
r12
,
#
0x4
cmp
r
12
,
#
0x0
bne
wait_dll_unlock
bx
lr
configure_sdrc
:
ldr
r4
,
omap3_sdrc_rfr_ctrl
str
r0
,
[
r4
]
ldr
r4
,
omap3_sdrc_actim_ctrla
str
r1
,
[
r4
]
ldr
r4
,
omap3_sdrc_actim_ctrlb
str
r2
,
[
r4
]
ldr
r11
,
omap3_sdrc_rfr_ctrl
str
r0
,
[
r11
]
ldr
r11
,
omap3_sdrc_actim_ctrla
str
r1
,
[
r11
]
ldr
r11
,
omap3_sdrc_actim_ctrlb
str
r2
,
[
r11
]
ldr
r2
,
[
r11
]
@
posted
-
write
barrier
for
SDRC
bx
lr
omap3_sdrc_power
:
...
...
arch/arm/plat-omap/clock.c
View file @
88b6f7eb
...
...
@@ -240,13 +240,13 @@ void recalculate_root_clocks(void)
}
/**
* clk_
init_one
- initialize any fields in the struct clk before clk init
* clk_
preinit
- initialize any fields in the struct clk before clk init
* @clk: struct clk * to initialize
*
* Initialize any struct clk fields needed before normal clk initialization
* can run. No return value.
*/
void
clk_
init_one
(
struct
clk
*
clk
)
void
clk_
preinit
(
struct
clk
*
clk
)
{
INIT_LIST_HEAD
(
&
clk
->
children
);
}
...
...
arch/arm/plat-omap/include/mach/clock.h
View file @
88b6f7eb
...
...
@@ -119,7 +119,7 @@ struct clk_functions {
extern
unsigned
int
mpurate
;
extern
int
clk_init
(
struct
clk_functions
*
custom_clocks
);
extern
void
clk_
init_one
(
struct
clk
*
clk
);
extern
void
clk_
preinit
(
struct
clk
*
clk
);
extern
int
clk_register
(
struct
clk
*
clk
);
extern
void
clk_reparent
(
struct
clk
*
child
,
struct
clk
*
parent
);
extern
void
clk_unregister
(
struct
clk
*
clk
);
...
...
arch/arm/plat-omap/include/mach/sram.h
View file @
88b6f7eb
...
...
@@ -23,7 +23,8 @@ extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
extern
u32
omap3_configure_core_dpll
(
u32
sdrc_rfr_ctrl
,
u32
sdrc_actim_ctrla
,
u32
sdrc_actim_ctrlb
,
u32
m2
);
u32
sdrc_actim_ctrlb
,
u32
m2
,
u32
unlock_dll
);
/* Do not use these */
extern
void
omap1_sram_reprogram_clock
(
u32
ckctl
,
u32
dpllctl
);
...
...
@@ -60,7 +61,8 @@ extern unsigned long omap243x_sram_reprogram_sdrc_sz;
extern
u32
omap3_sram_configure_core_dpll
(
u32
sdrc_rfr_ctrl
,
u32
sdrc_actim_ctrla
,
u32
sdrc_actim_ctrlb
,
u32
m2
);
u32
sdrc_actim_ctrlb
,
u32
m2
,
u32
unlock_dll
);
extern
unsigned
long
omap3_sram_configure_core_dpll_sz
;
#endif
arch/arm/plat-omap/sram.c
View file @
88b6f7eb
...
...
@@ -201,6 +201,15 @@ void __init omap_map_sram(void)
base
=
OMAP3_SRAM_PA
;
base
=
ROUND_DOWN
(
base
,
PAGE_SIZE
);
omap_sram_io_desc
[
0
].
pfn
=
__phys_to_pfn
(
base
);
/*
* SRAM must be marked as non-cached on OMAP3 since the
* CORE DPLL M2 divider change code (in SRAM) runs with the
* SDRAM controller disabled, and if it is marked cached,
* the ARM may attempt to write cache lines back to SDRAM
* which will cause the system to hang.
*/
omap_sram_io_desc
[
0
].
type
=
MT_MEMORY_NONCACHED
;
}
omap_sram_io_desc
[
0
].
length
=
1024
*
1024
;
/* Use section desc */
...
...
@@ -343,14 +352,15 @@ static inline int omap243x_sram_init(void)
static
u32
(
*
_omap3_sram_configure_core_dpll
)(
u32
sdrc_rfr_ctrl
,
u32
sdrc_actim_ctrla
,
u32
sdrc_actim_ctrlb
,
u32
m2
);
u32
m2
,
u32
unlock_dll
);
u32
omap3_configure_core_dpll
(
u32
sdrc_rfr_ctrl
,
u32
sdrc_actim_ctrla
,
u32
sdrc_actim_ctrlb
,
u32
m2
)
u32
sdrc_actim_ctrlb
,
u32
m2
,
u32
unlock_dll
)
{
BUG_ON
(
!
_omap3_sram_configure_core_dpll
);
return
_omap3_sram_configure_core_dpll
(
sdrc_rfr_ctrl
,
sdrc_actim_ctrla
,
sdrc_actim_ctrlb
,
m2
);
sdrc_actim_ctrlb
,
m2
,
unlock_dll
);
}
/* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */
...
...
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