Hi,
I am trying to writing a bare metal OS in iMX8MQ EVK.
The OS is loaded by uboot to DDR @address: 0x60900000. The OS is running in EL2 of AArch64.
The is the system counter return value when boot my OS.
System counter return 6b497049
CNTID: 0 , CNTSR: 256 , CNTCV 1799998267
But i can't get any interrupt from GIC.
System Counter Address:
static void *sys_ctr_rd_base = 0x306a0000;
static void *sys_ctr_cmp_base = 0x306b0000;
This is my code
int enable_timer(void)
{
uint64_t current_time;
uint32_t rd;
uint32_t i = 0;
//
// Configure the interrupt controller
//
rd = initGIC();
//
// Configure and enable the System Counter
//
printf("configure and enable the sytem couner \n");
setSystemCounterBaseAddr(0x306c0000); // Address of the System Counter
initSystemCounter(SYSTEM_COUNTER_CNTCR_nHDBG,
SYSTEM_COUNTER_CNTCR_FREQ0,
SYSTEM_COUNTER_CNTCR_nSCALE);
for (i = 10; i<50; i++) {
setIntPriority(i, rd, 0);
setIntGroup(i, rd, 2);
SetSPIRoute(i, 0, gicdirouter_ModeAny); // Route INTID to (this core)
ConfigureSPI(i, gicdicfgr_Level); // Set INTID as level-sensitive
enableInt(i, rd);
}
printf("Configure non-secure physical timer\n");
// Configure the Non-secure Physical Timer
// This uses the TVAL/timer to fire the timer in X ticks
~ current_time = getPhysicalCount();
~ setNSEL2PhysicalCompValue(current_time + 100000);
+ //setNSEL2PhysicalTimerValue(2000);
+ setNSEL2PhysicalTimerCtrl(CNTP_CTL_ENABLE);
}
uint32_t initGIC(void)
{
uint32_t rd;
printf("setGIC addr\n");
// Set location of GIC
setGICAddr((void*)0x38800000, (void*)0x38880000);
printf("Enable GIC\n");
// Set location of GIC
// Enable GIC
enableGIC();
printf("Get the ID of the Redistributor connected to this PE\n");
// Get the ID of the Redistributor connected to this PE
rd = getRedistID(getAffinity());
printf("Mark this core as beign active\n");
// Mark this core as beign active
wakeUpRedist(rd);
// Configure the CPU interface
// This assumes that the SRE bits are already set
setPriorityMask(0xFF);
printf("enableGroup0Ints skipped\n");
//enableGroup0Ints();
printf("enableGroup1Ints\n");
enableGroup1Ints();
return rd;
}
+ void sysctr_timer_enable(int enable)
+ {
+ unsigned int val;
+
+ val = mymmio_read_32(sys_ctr_cmp_base + CMPCR);
+ val &= ~SYS_CTR_EN;
+ if (enable)
+ val |= SYS_CTR_EN;
+
+ mymmio_write_32(sys_ctr_cmp_base + CMPCR, val);
+ }
+
+ unsigned long sysctr_read_counter(void)
+ {
+ unsigned int cnt_hi, tmp_hi, cnt_lo;
+
+ cnt_hi = mymmio_read_32(sys_ctr_rd_base + CNTCV_HI);
+ cnt_lo = mymmio_read_32(sys_ctr_rd_base + CNTCV_LO);
+ tmp_hi = mymmio_read_32(sys_ctr_rd_base + CNTCV_HI);
+
+ return ((unsigned long) cnt_hi << 32) | cnt_lo;
+ }
+ int sysctr_set_next_event(unsigned long delta)
+ {
+ unsigned int cmp_hi, cmp_lo;
+ unsigned long next;
+
+ sysctr_timer_enable(false);
+
+ next = sysctr_read_counter();
+
+ next += delta;
+
+ cmp_hi = (next >> 32) & 0x00fffff;
+ cmp_lo = next & 0xffffffff;
+
+ mymmio_write_32(sys_ctr_cmp_base + CMPCV_HI, cmp_hi);
+ mymmio_write_32(sys_ctr_cmp_base + CMPCV_LO, cmp_lo);
+
+ sysctr_timer_enable(true);
+
+ return 0;
+ }
For system counter, we found that the interrupt ID should be 79 instead of 47. There are 32 bits shift. The driver code is similar with the Linux kernel driver in drivers/clocksource/timer-imx-sysctr.c
Hi zhang
one can refer to linux gpt interrupt example, described in sect.2.1.3.3 Timer
Source Code Structure, sect.2.1.2.4 Interrupt Source Code Structure
attached Linux Manual.
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi, Ignorpadykov
Thanks. I will try to review the code of GPT in the Linux kernel.
BTW, according to the i.MX_Referenc_Manul, The i.MX 8M used the
System Counter instead of GP. And I tried to programming the GPT by myself, it doesn't work.
The following tables describes the different timers used.
Timer | Description |
General Purpose Timer (GPT) | GPT is configured to generate a periodic interrupt at a certain interval (every 10 ms). Used by i.MX 6 to go into WFI mode. Used by i.MX 6 and i.MX 7. |
Enhanced Periodic Interrupt Timer (EPIT) | Available on i.MX 6 and i.MX 7. |
Arm Arch Timer | i.MX 8 usage instead of GPT |
System Counter Timer | i.MX 8M and i.MX 8X usage instead of GP |
This is the code from the Linux kernel. There is no iMX8MQ support.
572 TIMER_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
573 TIMER_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
574 TIMER_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt);
575 TIMER_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
576 TIMER_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
577 TIMER_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
578 TIMER_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
579 TIMER_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
580 TIMER_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
581 TIMER_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
582 TIMER_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
583 TIMER_OF_DECLARE(imx6sll_timer, "fsl,imx6sll-gpt", imx6dl_timer_init_dt);
584 TIMER_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
585 TIMER_OF_DECLARE(imx6ul_timer, "fsl,imx6ul-gpt", imx6dl_timer_init_dt);
586 TIMER_OF_DECLARE(mx7d_timer, "fsl,imx7d-gpt", imx6dl_timer_init_dt);
587 #ifdef CONFIG_ARM64
588 subsys_initcall(imx8qxp_timer_init);
589 #endif
from source.codeaurora.org/external/imx/linux-imx/tree/arch/arm64/boot/dts/freescale/fsl-imx8mq.dtsi
it is compatible with "mx7d_timer, "fsl,imx7d-gpt"
gpt1: gpt@302d0000 {
compatible = "fsl,imx8mq-gpt", "fsl,imx7d-gpt";
fsl-imx8mq.dtsi\freescale\dts\boot\arm64\arch - linux-imx - i.MX Linux kernel
Best regards
igor
The GPT driver doesn't work in my side. I could read the timer count, but there is no interrupt from GIC.
I don't know what is missing.
nxp has special service for helping with porting custom software
Commercial Support and Engineering Services | NXP
Best regards
igor