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
7a103f02
Commit
7a103f02
authored
Nov 14, 2017
by
Stephen Boyd
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'clk-at91' into clk-next
* clk-at91: clk: at91: utmi: set the mainck rate
parents
2dd850ef
92041a9f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
14 deletions
+83
-14
drivers/clk/at91/clk-utmi.c
drivers/clk/at91/clk-utmi.c
+81
-14
include/soc/at91/atmel-sfr.h
include/soc/at91/atmel-sfr.h
+2
-0
No files found.
drivers/clk/at91/clk-utmi.c
View file @
7a103f02
...
@@ -14,14 +14,20 @@
...
@@ -14,14 +14,20 @@
#include <linux/of.h>
#include <linux/of.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/regmap.h>
#include <soc/at91/atmel-sfr.h>
#include "pmc.h"
#include "pmc.h"
#define UTMI_FIXED_MUL 40
/*
* The purpose of this clock is to generate a 480 MHz signal. A different
* rate can't be configured.
*/
#define UTMI_RATE 480000000
struct
clk_utmi
{
struct
clk_utmi
{
struct
clk_hw
hw
;
struct
clk_hw
hw
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap_pmc
;
struct
regmap
*
regmap_sfr
;
};
};
#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
...
@@ -37,13 +43,54 @@ static inline bool clk_utmi_ready(struct regmap *regmap)
...
@@ -37,13 +43,54 @@ static inline bool clk_utmi_ready(struct regmap *regmap)
static
int
clk_utmi_prepare
(
struct
clk_hw
*
hw
)
static
int
clk_utmi_prepare
(
struct
clk_hw
*
hw
)
{
{
struct
clk_hw
*
hw_parent
;
struct
clk_utmi
*
utmi
=
to_clk_utmi
(
hw
);
struct
clk_utmi
*
utmi
=
to_clk_utmi
(
hw
);
unsigned
int
uckr
=
AT91_PMC_UPLLEN
|
AT91_PMC_UPLLCOUNT
|
unsigned
int
uckr
=
AT91_PMC_UPLLEN
|
AT91_PMC_UPLLCOUNT
|
AT91_PMC_BIASEN
;
AT91_PMC_BIASEN
;
unsigned
int
utmi_ref_clk_freq
;
unsigned
long
parent_rate
;
/*
* If mainck rate is different from 12 MHz, we have to configure the
* FREQ field of the SFR_UTMICKTRIM register to generate properly
* the utmi clock.
*/
hw_parent
=
clk_hw_get_parent
(
hw
);
parent_rate
=
clk_hw_get_rate
(
hw_parent
);
switch
(
parent_rate
)
{
case
12000000
:
utmi_ref_clk_freq
=
0
;
break
;
case
16000000
:
utmi_ref_clk_freq
=
1
;
break
;
case
24000000
:
utmi_ref_clk_freq
=
2
;
break
;
/*
* Not supported on SAMA5D2 but it's not an issue since MAINCK
* maximum value is 24 MHz.
*/
case
48000000
:
utmi_ref_clk_freq
=
3
;
break
;
default:
pr_err
(
"UTMICK: unsupported mainck rate
\n
"
);
return
-
EINVAL
;
}
regmap_update_bits
(
utmi
->
regmap
,
AT91_CKGR_UCKR
,
uckr
,
uckr
);
if
(
utmi
->
regmap_sfr
)
{
regmap_update_bits
(
utmi
->
regmap_sfr
,
AT91_SFR_UTMICKTRIM
,
AT91_UTMICKTRIM_FREQ
,
utmi_ref_clk_freq
);
}
else
if
(
utmi_ref_clk_freq
)
{
pr_err
(
"UTMICK: sfr node required
\n
"
);
return
-
EINVAL
;
}
while
(
!
clk_utmi_ready
(
utmi
->
regmap
))
regmap_update_bits
(
utmi
->
regmap_pmc
,
AT91_CKGR_UCKR
,
uckr
,
uckr
);
while
(
!
clk_utmi_ready
(
utmi
->
regmap_pmc
))
cpu_relax
();
cpu_relax
();
return
0
;
return
0
;
...
@@ -53,21 +100,22 @@ static int clk_utmi_is_prepared(struct clk_hw *hw)
...
@@ -53,21 +100,22 @@ static int clk_utmi_is_prepared(struct clk_hw *hw)
{
{
struct
clk_utmi
*
utmi
=
to_clk_utmi
(
hw
);
struct
clk_utmi
*
utmi
=
to_clk_utmi
(
hw
);
return
clk_utmi_ready
(
utmi
->
regmap
);
return
clk_utmi_ready
(
utmi
->
regmap
_pmc
);
}
}
static
void
clk_utmi_unprepare
(
struct
clk_hw
*
hw
)
static
void
clk_utmi_unprepare
(
struct
clk_hw
*
hw
)
{
{
struct
clk_utmi
*
utmi
=
to_clk_utmi
(
hw
);
struct
clk_utmi
*
utmi
=
to_clk_utmi
(
hw
);
regmap_update_bits
(
utmi
->
regmap
,
AT91_CKGR_UCKR
,
AT91_PMC_UPLLEN
,
0
);
regmap_update_bits
(
utmi
->
regmap_pmc
,
AT91_CKGR_UCKR
,
AT91_PMC_UPLLEN
,
0
);
}
}
static
unsigned
long
clk_utmi_recalc_rate
(
struct
clk_hw
*
hw
,
static
unsigned
long
clk_utmi_recalc_rate
(
struct
clk_hw
*
hw
,
unsigned
long
parent_rate
)
unsigned
long
parent_rate
)
{
{
/* UTMI clk
is a fixed clk multiplier
*/
/* UTMI clk
rate is fixed.
*/
return
parent_rate
*
UTMI_FIXED_MUL
;
return
UTMI_RATE
;
}
}
static
const
struct
clk_ops
utmi_ops
=
{
static
const
struct
clk_ops
utmi_ops
=
{
...
@@ -78,7 +126,7 @@ static const struct clk_ops utmi_ops = {
...
@@ -78,7 +126,7 @@ static const struct clk_ops utmi_ops = {
};
};
static
struct
clk_hw
*
__init
static
struct
clk_hw
*
__init
at91_clk_register_utmi
(
struct
regmap
*
regmap
,
at91_clk_register_utmi
(
struct
regmap
*
regmap
_pmc
,
struct
regmap
*
regmap_sfr
,
const
char
*
name
,
const
char
*
parent_name
)
const
char
*
name
,
const
char
*
parent_name
)
{
{
struct
clk_utmi
*
utmi
;
struct
clk_utmi
*
utmi
;
...
@@ -97,7 +145,8 @@ at91_clk_register_utmi(struct regmap *regmap,
...
@@ -97,7 +145,8 @@ at91_clk_register_utmi(struct regmap *regmap,
init
.
flags
=
CLK_SET_RATE_GATE
;
init
.
flags
=
CLK_SET_RATE_GATE
;
utmi
->
hw
.
init
=
&
init
;
utmi
->
hw
.
init
=
&
init
;
utmi
->
regmap
=
regmap
;
utmi
->
regmap_pmc
=
regmap_pmc
;
utmi
->
regmap_sfr
=
regmap_sfr
;
hw
=
&
utmi
->
hw
;
hw
=
&
utmi
->
hw
;
ret
=
clk_hw_register
(
NULL
,
&
utmi
->
hw
);
ret
=
clk_hw_register
(
NULL
,
&
utmi
->
hw
);
...
@@ -114,17 +163,35 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
...
@@ -114,17 +163,35 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
struct
clk_hw
*
hw
;
struct
clk_hw
*
hw
;
const
char
*
parent_name
;
const
char
*
parent_name
;
const
char
*
name
=
np
->
name
;
const
char
*
name
=
np
->
name
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap
_pmc
,
*
regmap_sfr
;
parent_name
=
of_clk_get_parent_name
(
np
,
0
);
parent_name
=
of_clk_get_parent_name
(
np
,
0
);
of_property_read_string
(
np
,
"clock-output-names"
,
&
name
);
of_property_read_string
(
np
,
"clock-output-names"
,
&
name
);
regmap
=
syscon_node_to_regmap
(
of_get_parent
(
np
));
regmap
_pmc
=
syscon_node_to_regmap
(
of_get_parent
(
np
));
if
(
IS_ERR
(
regmap
))
if
(
IS_ERR
(
regmap
_pmc
))
return
;
return
;
hw
=
at91_clk_register_utmi
(
regmap
,
name
,
parent_name
);
/*
* If the device supports different mainck rates, this value has to be
* set in the UTMI Clock Trimming register.
* - 9x5: mainck supports several rates but it is indicated that a
* 12 MHz is needed in case of USB.
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
* the FREQ field of the UTMI Clock Trimming register is mandatory.
* - sama5d4: mainck is at 12 MHz.
*
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
*/
regmap_sfr
=
syscon_regmap_lookup_by_compatible
(
"atmel,sama5d3-sfr"
);
if
(
IS_ERR
(
regmap_sfr
))
{
regmap_sfr
=
syscon_regmap_lookup_by_compatible
(
"atmel,sama5d2-sfr"
);
if
(
IS_ERR
(
regmap_sfr
))
regmap_sfr
=
NULL
;
}
hw
=
at91_clk_register_utmi
(
regmap_pmc
,
regmap_sfr
,
name
,
parent_name
);
if
(
IS_ERR
(
hw
))
if
(
IS_ERR
(
hw
))
return
;
return
;
...
...
include/soc/at91/atmel-sfr.h
View file @
7a103f02
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
/* 0x08 ~ 0x0c: Reserved */
/* 0x08 ~ 0x0c: Reserved */
#define AT91_SFR_OHCIICR 0x10
/* OHCI INT Configuration Register */
#define AT91_SFR_OHCIICR 0x10
/* OHCI INT Configuration Register */
#define AT91_SFR_OHCIISR 0x14
/* OHCI INT Status Register */
#define AT91_SFR_OHCIISR 0x14
/* OHCI INT Status Register */
#define AT91_SFR_UTMICKTRIM 0x30
/* UTMI Clock Trimming Register */
#define AT91_SFR_I2SCLKSEL 0x90
/* I2SC Register */
#define AT91_SFR_I2SCLKSEL 0x90
/* I2SC Register */
/* Field definitions */
/* Field definitions */
...
@@ -28,5 +29,6 @@
...
@@ -28,5 +29,6 @@
AT91_OHCIICR_SUSPEND_B | \
AT91_OHCIICR_SUSPEND_B | \
AT91_OHCIICR_SUSPEND_C)
AT91_OHCIICR_SUSPEND_C)
#define AT91_UTMICKTRIM_FREQ GENMASK(1, 0)
#endif
/* _LINUX_MFD_SYSCON_ATMEL_SFR_H */
#endif
/* _LINUX_MFD_SYSCON_ATMEL_SFR_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