hw/misc/imx6_ccm: Add PLL3 and CAN clock
Add fixed frequency (480 MHz) PLL3, of which the FlexCAN clock is derived, and compute FlexCAN frequency based on the divider configuration (CCM_CSCMR2). The clock frequency will be used for computing timestamps in FlexCAN emulator. Signed-off-by: Matyáš Bobek <matyas.bobek@gmail.com> Signed-off-by: Pavel Pisa <pisa@fel.cvut.cz> Tested-by: Pavel Pisa <pisa@fel.cvut.cz> Reviewed-by: Bernhard Beschow <shentey@gmail.com> Reviewed-by: Pavel Pisa <pisa@fel.cvut.cz> Message-id: 95da33074f8b79842566d61e4e04448b1e622080.1782140438.git.matyas.bobek@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Matyáš Bobek committed
Jun 22, 2026 at 18:08 UTC
9f61499c4add725e91b294d92deeedb894512a14
4 files changed
+31
hw/misc/imx6_ccm.c
+24
@@ -257,6 +257,15 @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
257
return freq;
258
}
259
260
+static uint64_t imx6_analog_get_pll3_clk(IMX6CCMState *dev)
261
+{
262
+ uint64_t freq = 480000000;
263
+
264
+ trace_imx6_analog_get_pll3_clk(freq);
265
+
266
+ return freq;
267
+}
268
+
269
static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
270
{
271
uint64_t freq = 0;
@@ -344,6 +353,18 @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
353
return freq;
354
}
355
356
+static uint64_t imx6_ccm_get_can_clk(IMX6CCMState *dev)
357
+{
358
+ uint64_t freq = 0;
359
+
360
+ freq = imx6_analog_get_pll3_clk(dev) / 8;
361
+ freq /= (1 + EXTRACT(dev->ccm[CCM_CSCMR2], CAN_CLK_PODF));
362
+
363
+ trace_imx6_ccm_get_can_clk(freq);
364
+
365
+ return freq;
366
+}
367
+
368
static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
369
{
370
uint32_t freq = 0;
@@ -358,6 +379,9 @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
379
case CLK_IPG_HIGH:
380
freq = imx6_ccm_get_per_clk(s);
381
break;
382
+ case CLK_CAN:
383
+ freq = imx6_ccm_get_can_clk(s);
384
+ break;
385
case CLK_32k:
386
freq = CKIL_FREQ;
387
break;
hw/misc/trace-events
+2
@@ -242,11 +242,13 @@ imx6_analog_get_periph_clk(uint32_t freq) "freq = %u Hz"
242
imx6_analog_get_pll2_clk(uint32_t freq) "freq = %u Hz"
243
imx6_analog_get_pll2_pfd0_clk(uint32_t freq) "freq = %u Hz"
244
imx6_analog_get_pll2_pfd2_clk(uint32_t freq) "freq = %u Hz"
245
+imx6_analog_get_pll3_clk(uint32_t freq) "freq = %u Hz"
246
imx6_analog_read(const char *reg, uint32_t value) "reg[%s] => 0x%" PRIx32
247
imx6_analog_write(const char *reg, uint32_t value) "reg[%s] <= 0x%" PRIx32
248
imx6_ccm_get_ahb_clk(uint32_t freq) "freq = %u Hz"
249
imx6_ccm_get_ipg_clk(uint32_t freq) "freq = %u Hz"
250
imx6_ccm_get_per_clk(uint32_t freq) "freq = %u Hz"
251
+imx6_ccm_get_can_clk(uint32_t freq) "freq = %u Hz"
252
imx6_ccm_get_clock_frequency(unsigned clock, uint32_t freq) "(Clock = %d) = %u"
253
imx6_ccm_read(const char *reg, uint32_t value) "reg[%s] => 0x%" PRIx32
254
imx6_ccm_reset(void) ""
include/hw/misc/imx6_ccm.h
+4
@@ -164,6 +164,10 @@
164
#define PERCLK_PODF_SHIFT (0)
165
#define PERCLK_PODF_LENGTH (6)
166
167
+/* CCM_CSCMR2 */
168
+#define CAN_CLK_PODF_SHIFT (2)
169
+#define CAN_CLK_PODF_LENGTH (6)
170
+
171
/* CCM_ANALOG_PFD_528 */
172
#define PFD0_FRAC_SHIFT (0)
173
#define PFD0_FRAC_LENGTH (6)
include/hw/misc/imx_ccm.h
+1
@@ -46,6 +46,7 @@ typedef enum {
46
CLK_EXT,
47
CLK_HIGH_DIV,
48
CLK_HIGH,
49
+ CLK_CAN,
50
} IMXClk;
51
52
struct IMXCCMClass {