-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
drivers: clk: sam: update main, generic and PLL clocks for Microchip sama7g54 #6651
Conversation
9af5c20
to
aeb9792
Compare
aeb9792
to
3a57dd3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment on "drivers: clk: sam: update to support main system bus clock for sama7g5". Once addressed, please add to this commit:
Acked-by: Jerome Forissier <[email protected]>
core/drivers/clk/sam/at91_master.c
Outdated
struct clk_master *master = hw->priv; | ||
size_t i = 0; | ||
|
||
for (; i < hw->num_parents; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (i = 0; i < hw->num_parents; i++)
(and please keep the initialization size_t i = 0;
regardless).
core/drivers/clk/sam/at91_master.c
Outdated
return i; | ||
|
||
EMSG("Can't get correct parent of clock \"%s\"", hw->name); | ||
return -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return type size_t
is unsigned, should be changed.
uint8_t safe_div; | ||
}; | ||
|
||
static inline bool sam9x60_pll_ready(vaddr_t base, int id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove inline keyword. Not needed from a source file, it's rather used only from header files.
{ | ||
unsigned int status = io_read32(base + AT91_PMC_PLL_ISR0); | ||
|
||
return !!(status & BIT(id)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return status & BIT(id);
is enough.
Or even return io_read32(base + AT91_PMC_PLL_ISR0) & BIT(id);
|
||
freq = parent_rate * (frac->mul + 1) + | ||
UDIV_ROUND_NEAREST((unsigned long long)parent_rate * frac->frac, | ||
(1 << 22)); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
{ | ||
struct sam9x60_pll_core *core = &frac->core; | ||
vaddr_t regmap = frac->core.base; | ||
unsigned int val = 0, cfrac = 0, cmul = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
define 1 local variable per line.
core/drivers/clk/sam/at91_master.c
Outdated
io_write32(master->base + AT91_PMC_MCR_V2, master->id); | ||
val = io_read32(master->base + AT91_PMC_MCR_V2); | ||
master->parent = (val & AT91_PMC_MCR_V2_CSS_MSK) | ||
>> AT91_PMC_MCR_V2_CSS_SHIFT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- master->parent = (val & AT91_PMC_MCR_V2_CSS_MSK)
- >> AT91_PMC_MCR_V2_CSS_SHIFT;
+ master->parent = (val & AT91_PMC_MCR_V2_CSS_MSK) >>
+ AT91_PMC_MCR_V2_CSS_SHIFT;
unsigned int i = 0; | ||
|
||
if (gck->mux_table) { | ||
for (; i < 8; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comment as for previous commit: for (i = 0; i < 8; i++)
if (gck->mux_table[i] == gck->parent_id) | ||
return i; | ||
EMSG("Can't get correct parent of clock \"%s\"", clk->name); | ||
return -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_t
is unsigned.
#define PLL_DIV_MAX PLL_DIV_MASK | ||
#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) | ||
#define PLL_MUL(reg, layout) ({ \ | ||
typeof(layout) __layout = layout; \ |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
#define PLL_MUL_MASK(layout) ((layout)->mul_mask) | ||
#define PLL_MUL_MAX(layout) (PLL_MUL_MASK(layout) + 1) | ||
#define PLL_ICPR_SHIFT(id) ((id) * 16) | ||
#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SHIFT_U64(0xffff, PLL_ICPR_SHIFT(id))
3a57dd3
to
894d186
Compare
@etienne-lms Updated according to the comments, review tags added and rebased on the latest |
894d186
to
acaeafe
Compare
Timeout added for waiting PLL clock ready. |
core/drivers/clk/sam/at91_master.c
Outdated
return i; | ||
|
||
EMSG("Can't get correct parent of clock \"%s\"", hw->name); | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0 seems a valid return index. I think it's safe to panic()
here since this is not awaited.
if (gck->mux_table[i] == gck->parent_id) | ||
return i; | ||
EMSG("Can't get correct parent of clock \"%s\"", clk->name); | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could safely panic here IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can remove the useless return 0
instruction.
Ditto in clk_sama7g5_master_get_parent()
.
cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift; | ||
|
||
if (sam9x60_frac_pll_ready(regmap, core->id) && | ||
(cmul == frac->mul && cfrac == frac->frac)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could remove the inner parentheses:
if (sam9x60_frac_pll_ready(regmap, core->id) &&
cmul == frac->mul && cfrac == frac->frac)
AT91_PMC_PLL_UPDT_UPDATE | core->id); | ||
|
||
while (!sam9x60_pll_ready(regmap, core->id)) | ||
if (timeout_elapsed(timeout)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend to use IO_READ32_POLL_TIMEOUT()
macro the handle case where this function is called from a threaded context that is rescheduled between sam9x60_pll_ready()
call and timeout_elapsed()
call.
* divider that provide the closest rate to the requested one. | ||
*/ | ||
nmul = rate / parent_rate; | ||
nmul += (rate % parent_rate) / parent_rate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think (rate % parent_rate) / parent_rate
will always be 0.
(1 << 22)); | ||
} | ||
|
||
/* Check if resulted rate is a valid. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- /* Check if resulted rate is a valid. */
+ /* Check if resulted rate is a valid. */
AT91_PMC_PLL_UPDT_UPDATE | core->id); | ||
|
||
while (!sam9x60_pll_ready(regmap, core->id)) | ||
; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handle timeout with IO_READ32_POLL_TIMEOUT()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank for your comments.
Commits updated according to the comments expect the using of IO_READ32_POLL_TIMEOUT()
. The reason is that udelay()
is used in the macro and there will be an assert failure while booting.
udelay()
depends on plat_get_freq()
which requires the initialization of freq
(done by early_init_late(get_freq_from_dt);
). Some PLL clocks need to be initialized before calling get_freq_from_dt
, once the delay is called with non-initialized freq
an assert failure will occur.
AT91_PMC_PLL_UPDT_UPDATE | core->id); | ||
|
||
while (!sam9x60_pll_ready(regmap, core->id)) | ||
; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto about timeout handling
{ | ||
struct sam9x60_pll_core *core = &div->core; | ||
vaddr_t regmap = core->base; | ||
unsigned int val = 0, cdiv = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsigned int cdiv = 0;
unsigned int val = 0;
02aa760
to
7839069
Compare
Update |
7839069
to
ae36028
Compare
Missing offset of PLL ISR register while adding |
ae36028
to
80b5ef2
Compare
if (gck->mux_table[i] == gck->parent_id) | ||
return i; | ||
EMSG("Can't get correct parent of clock \"%s\"", clk->name); | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can remove the useless return 0
instruction.
Ditto in clk_sama7g5_master_get_parent()
.
AT91_PMC_PLL_UPDT_UPDATE | core->id); | ||
|
||
if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) | ||
EMSG("PLL not ready"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ret = TEE_ERROR_xxx
if WAIT_PLL_READY_TIMEOUT()
returns true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return TEE_ERROR_BUSY;
added, thanks.
AT91_PMC_PLL_UPDT_UPDATE | core->id); | ||
|
||
if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) | ||
EMSG("PLL not ready"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return an error to code sam9x60_div_pll_set()
and sam9x60_div_pll_set_rate_chg()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the return code.
struct sam9x60_div *div = hw->priv; | ||
struct sam9x60_pll_core *core = &div->core; | ||
vaddr_t regmap = core->base; | ||
unsigned int val, cdiv; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsigned int cdiv = 0;
unsigned int val = 0;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
80b5ef2
to
cdb9edd
Compare
@@ -0,0 +1,517 @@ | |||
// SPDX-License-Identifier: GPL-2.0+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
license model issue
// SPDX-License-Identifier: GPL-2.0+ | ||
/* | ||
* Copyright (C) 2019 Microchip Technology Inc. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can remove this empty inline comment line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the empty line and updated the license model, thanks.
cdb9edd
to
c6e3cc7
Compare
master->chg_pid = chg_pid; | ||
master->mux_table = mux_table; | ||
|
||
io_write32(master->base + AT91_PMC_MCR_V2, master->id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI make builds fail on AT91_PMC_MCR_V2*
macros not being defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The definitions of these macros are added in #6630, you can find them in core/drivers/clk/sam/at91_pmc.h
.
It's better to integrate #6630 before this PR, thanks.
That's not how it works. If you need a commit from another PR, please add it here too, and mention that it does not need to be reviewed here due to being in pending PR xxx. This way things are clear and CI can be trusted. |
c6e3cc7
to
a8aac5a
Compare
if (_c) \ | ||
break; \ | ||
} \ | ||
!(_c); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would replace !(_c);
with !io_read32((base) + AT91_PMC_PLL_ISR0) & BIT(id);
. Explanations in #6297 (comment).
I would also replace base
and id
arguments name with _base
and _id
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_base
and _id
updated. The !(_c)
not replaced due to interrupt status register AT91_PMC_PLL_ISR0
has read-clear behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then, you need to find another way to address the case where the TEE thread has been rescheduled while this macro is executing.
Edited: Discard this comment, it was stupid as your timeout detection based on a trial counter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As delay by a timer/counter can not be used here, add wait_cycles()
to determine the timeout.
{ | ||
vaddr_t regmap = core->base; | ||
uint32_t ena_msk = enable ? core->layout->endiv_mask : 0; | ||
uint32_t ena_val = enable ? (1 << core->layout->endiv_shift) : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint32_t ena_val = enable ? BIT(core->layout->endiv_shift) : 0;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, thanks.
bool enable) | ||
{ | ||
vaddr_t regmap = core->base; | ||
uint32_t ena_msk = enable ? core->layout->endiv_mask : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: s/ena_msk/enable_mask/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced msk
with mask
.
@TonyHan11, could you rebase your series now that #6630 is merged? |
a8aac5a
to
156cb23
Compare
Rebased to the latest |
856d518
to
f0f0b94
Compare
Last update of |
free(master); | ||
return NULL; | ||
} | ||
return hw; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: we usually add an empty line before the final return instruction in a function block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty lines added before each of the final return, thanks.
@@ -140,6 +151,7 @@ struct clk * | |||
at91_clk_register_generated(struct pmc_data *pmc, | |||
const struct clk_pcr_layout *layout, | |||
const char *name, struct clk **parents, | |||
uint32_t *mux_table, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems mux_parent
here is always a 8 cell array reference. I suggest you define that in the argument type, if applicable: s/uin32t_t *mux_parent
/uint32_t mux_parent[8]
/
This would ensure line 76 and 90 will not overflow gck->mux_table
size.
From clk_generated_set_parent()
above, gck->mux_table
size is related to the number of possible parents for the clock. Maybe use this info in clk_generated_get_parent()
, instead of 8?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added mux_table_size
variable after uint32_t *mux_table
in the struct and use it to avoid accessing beyond gck->mux_table
.
The mux_table
is used for sama7g5 support as the clock source of sama7g5_gck
are from different PLL. For sama5d2 the sources are fixed and no mux is used.
@@ -186,6 +186,14 @@ at91_clk_register_master_div(struct pmc_data *pmc, | |||
const struct clk_master_layout *layout, | |||
const struct clk_master_charac *charac); | |||
|
|||
struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It suggest that you state somewhere that both parent
and mux_table
have num_parents
cells.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mux_table_size
added and assigned equal to num_parents
in at91_clk_register_generated()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An inline description comment could clarify that when mux_table
is not NULL it shall hold num_parents
cells. This is only a suggestion.
f0f0b94
to
bf3f164
Compare
parent_rate); | ||
|
||
tmprate += UDIV_ROUND_NEAREST((uint64_t)nfrac * parent_rate, | ||
(1 << 22)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could remove the inner parentheses
@@ -72,16 +73,30 @@ static TEE_Result clk_generated_set_parent(struct clk *clk, size_t index) | |||
if (index >= clk_get_num_parents(clk)) | |||
return TEE_ERROR_BAD_PARAMETERS; | |||
|
|||
gck->parent_id = index; | |||
if (gck->mux_table) { | |||
if (index > gck->mux_table_size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function get read clk->num_parents
hence I think it's not needed to duplicate that info in struct clk_generated
.
@@ -186,6 +186,14 @@ at91_clk_register_master_div(struct pmc_data *pmc, | |||
const struct clk_master_layout *layout, | |||
const struct clk_master_charac *charac); | |||
|
|||
struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An inline description comment could clarify that when mux_table
is not NULL it shall hold num_parents
cells. This is only a suggestion.
bf3f164
to
2992836
Compare
Updated according to the comments, thank you @etienne-lms |
core/drivers/clk/sam/at91_clk.h
Outdated
@@ -186,6 +186,17 @@ at91_clk_register_master_div(struct pmc_data *pmc, | |||
const struct clk_master_layout *layout, | |||
const struct clk_master_charac *charac); | |||
|
|||
/* | |||
* @mux_table: when mux_table is not NULL it shll hold 'num_prents' cells |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @mux_table: when @mux_table is not NULL it shall hold @num_parents cells
core/drivers/clk/sam/at91_master.c
Outdated
unsigned long div = 0; | ||
|
||
div = UDIV_ROUND_NEAREST(parent_rate, rate); | ||
if ((div > (1 << (MASTER_PRES_MAX - 1))) || (div & (div - 1))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: s/div & (div - 1)
/!IS_POWER_OF_TWO(div)
/
wait_cycles(100); \ | ||
} \ | ||
!(_c); \ | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add an indentation tab to each line
#define WAIT_PLL_READY_TIMEOUT(_base, _id) \
({ \
uint32_t __timeout = 0; \
uint32_t _c = 0; \
\
while (__timeout++ < 500) { \
_c = io_read32((_base) + AT91_PMC_PLL_ISR0) & BIT(_id); \
if (_c) \
break; \
wait_cycles(100); \
} \
!(_c); \
})
unsigned int i = 0; | ||
|
||
if (gck->mux_table) { | ||
for (i = 0; i < gck->mux_table_size; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: clk_generated_set_parent()
relies on index >= clk_get_num_parents(clk)
and here on gck->mux_table_size
. For consistency, I think you could remove field mux_table_size
from struct clk_generated
and use clk_get_num_parents(clk)
here also (or use straight clk->num_parents
as done in clk_sama7g5_master_xxx()
).
typeof(layout) __layout = layout; \ | ||
\ | ||
(((reg) >> (__layout)->mul_shift) & (__layout)->mul_mask); \ | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an indentation tab (and can drop a pair of parentheses):
#define PLL_MUL(reg, layout) \
({ \
typeof(layout) __layout = layout; \
\
((reg) >> (__layout)->mul_shift) & (__layout)->mul_mask; \
})
2992836
to
d383e20
Compare
Updated according to the comments, thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acked-by: Etienne Carriere <[email protected]>
with this last comment addressed.
core/drivers/clk/sam/at91_clk.h
Outdated
@@ -186,6 +203,17 @@ at91_clk_register_master_div(struct pmc_data *pmc, | |||
const struct clk_master_layout *layout, | |||
const struct clk_master_charac *charac); | |||
|
|||
/* | |||
* @mux_table: when @mux_table is not NULL it shall hold @num_prents cells |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/@num_prents/@num_parents/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated and added Acked-by
, thank you.
Add functions for configuring sama7g5 main system bus clock. Signed-off-by: Tony Han <[email protected]> Acked-by: Jerome Forissier <[email protected]> Acked-by: Etienne Carriere <[email protected]>
Add a mux table for select from different generic clock source. Signed-off-by: Tony Han <[email protected]> Acked-by: Jerome Forissier <[email protected]> Acked-by: Etienne Carriere <[email protected]>
As PLL is compatible for sama7g5 and sam9x60, add sam9x60 PLL functions for configuring sama7g5 PLL. Signed-off-by: Tony Han <[email protected]> Acked-by: Jerome Forissier <[email protected]> Acked-by: Etienne Carriere <[email protected]>
d383e20
to
3d34ea7
Compare
IBART error ignored, branch needs re-basing. |
No description provided.