// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2024 AVM Computersysteme Vertriebs GmbH */ #include #include #include #include "bspchip.h" #define RLX_CS_CNT_INIT_VAL 0xfffffff #define RLX_CS_DIV_FACTOR 250 #define RLX_CS_HZ (BSP_SYSCLK / RLX_CS_DIV_FACTOR) /* Taken from bspchip.h and adjusted to work with ioremap */ #define RLX_TC_REG_BASE 0x18003200 #define RLX_TC_REG_LENGTH 0x6C #define RLX_TC1CTL (BSP_TC1CTL - BSP_TC_BASE) #define RLX_TC1DATA (BSP_TC1DATA - BSP_TC_BASE) #define RLX_TC1INT (BSP_TC1INT - BSP_TC_BASE) #define RLX_TC1CNT (BSP_TC1CNT - BSP_TC_BASE) static void __iomem *rlx_tc_base_addr; static void rlx_cs_enable(void) { u32 ctl; u32 tc_int; /* Wipe clock config */ ctl = 0; writel(ctl, rlx_tc_base_addr + RLX_TC1CTL); writel(RLX_CS_CNT_INIT_VAL, rlx_tc_base_addr + RLX_TC1DATA); /* Setup clock*/ ctl = BSP_TCEN | BSP_TCMODE_TIMER | RLX_CS_DIV_FACTOR; writel(ctl, rlx_tc_base_addr + RLX_TC1CTL); tc_int = readl(rlx_tc_base_addr + RLX_TC1INT); writel(tc_int & ~BSP_TCIE, rlx_tc_base_addr + RLX_TC1INT); } int rlx_cs_setup(void) { int errval; /* Get the proper address of the registers*/ rlx_tc_base_addr = ioremap(RLX_TC_REG_BASE, RLX_TC_REG_LENGTH); if (!rlx_tc_base_addr) { printk("rlx cs: Could not retrieve base address for timer registers."); return -EFAULT; } /* setup clocksource */ rlx_cs_enable(); errval = clocksource_mmio_init(rlx_tc_base_addr + RLX_TC1CNT, "rlx cs", RLX_CS_HZ, 200, 28, clocksource_mmio_readl_up); if (errval) printk("rlx cs: Could not initialize clocksource!"); return errval; }