IR: the device-tree clock fix does not take effect #43
Labels
No labels
blocked-physical
cleanup
hardware
infra
kernel
P1-critical
P2-high
P3-normal
P4-later
reliability
security
upstream
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
tiagoagueda/a80#43
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Split out of #16, which is otherwise resolved.
IR decodes correctly only while
probe/irclk.kois loaded, which writes the clock register byhand. The proper device-tree fix does not work.
On the IR consumer node (
ir@8002000):These are correct and reach the DTB —
assigned-clock-parentsresolves toclk-24M(phandle
0x08),assigned-clock-ratesis 8000000, and the device probes (rc0exists). Butafter a reboot the mux still reads 0 and the clock is still 2048 Hz. Tried on the provider node
too, same result.
Why, probably
r_ir_clkis registered withCLK_OF_DECLARE_DRIVER, so it exists both as an early clock(registered at
of_clk_init()time) and as a platform driver.of_clk_set_defaults()runsat probe (
drivers/base/platform.c:1497) and the composite does useclk_mux_ops, which has.set_parent— so the machinery should work. The suspicion is that it acts on a differentinstance than the one the IR device resolves. Not yet confirmed.
The better fix
Rather than forcing the parent per board, give the sunxi factors clock a
determine_ratethatcan choose a parent. Then
sunxi-cir's ownclk_set_rate(8000000)would do the right thingby itself, on every sunxi SoC using a mod0 clock.
This is arguably a latent bug beyond this board: the A31 has the identical clock description
(
sun4i-a10-mod0-clkwith<&rtc CLK_OSC32K>, <&osc24M>) and nothing forces its mux either. Itonly works there because of what its bootloader happens to leave behind.
drivers/clk/sunxi/clk-factors.c) — lists: linux-clk, linux-sunxipatches/linux-dts-sun9i-ir-clk/(committed with the caveat in itsmessage that it does not take effect)
⚠️ Nothing has been submitted upstream. See 42-upstreaming.md.
Re-scoped rather than fixed, because the diagnosis in this issue is wrong - and so is the fix it
proposes. Measured on the running board with a throwaway module (
probe/irclkdbg.ko) thatreplays what
__set_clk_parents()does, one call at a time, printing every return value.The device tree was never the problem
So:
assigned-clock-parentsworks.of_clk_set_defaults()reaches the right instance, resolvesboth clocks, and
clk_set_parent()returns 0 and moves the mux. TheCLK_OF_DECLARE_DRIVERdouble-instance theory in the original post is not what is happening.
clk_factors_determine_rate()already picks the right parent.clk_round_rate(8 MHz)returns exactly 8000000 from osc24M. The "better fix" proposed above - give the factors clock a
determine_ratethat can choose a parent - would change nothing, because it already has one andit already chooses correctly.
sunxi-cir's ownclk_set_rate(SUNXI_IR_BASE_CLK)in probe, which runsafter
of_clk_set_defaults()and reparents the clock back to osc32k while returning success.clk_factors_set_rate()only read-modify-writes the n/k/m/p fields, so it is not clobbering themux. This is a genuine CCF reparent.
It lands on parent[0] no matter what is asked
set_parent(osc24M)thenset_rate(8M)set_rate(8M)thenset_parent(osc24M)set_rate(8M)againset_rate(12 MHz)- unreachable from osc32kclk_set_rate_range(1 MHz, 24 MHz)The last two are the damning ones.
clk_set_rate()selects a parent that physically cannotproduce the requested rate, ignores an explicit rate floor, and reports success - while
clk_round_rate(), on the same clock in the same state, answers correctly.What this means
No ordering of the public clk API produces 8 MHz on osc24M, so this cannot be fixed from the
device tree at all. The DT patch in
patches/linux-dts-sun9i-ir-clk/describes the hardwarecorrectly and should stay, but it will never be sufficient on its own.
probe/irclk.kois still the only thing that makes IR work, and it works precisely because itbypasses the CCF and writes the register.
Next step
Instrument
clk_calc_new_rates()/clk_change_rate()to find where the parent chosen bydetermine_rateis lost between the round and the set. The candidates worth printing arecore->new_parent,core->new_parent_index, and whatclk_composite_set_rate_and_parent()receives - a composite with both
rate_ops->set_rateandmux_ops->set_parenttakes that pathrather than plain
set_rate.Worth restating the wider claim in the original post, which still holds and is now better
supported: the A31 has the identical clock description and nothing forces its mux either, so if
this is a core bug rather than something specific to how sunxi builds the composite, it is latent
on more than this board.
The title should probably change too - it is not that "the device-tree clock fix does not take
effect", it is that
clk_set_rate()reparents away from it.