drivers: clock_control: Add clock driver for Intel SoC FPGA Agilex
Add clock driver for Intel SoC FPGA Agilex. Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
This commit is contained in:
parent
5b6c59397e
commit
0c34373720
5 changed files with 350 additions and 0 deletions
|
@ -48,3 +48,6 @@ else()
|
||||||
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_STM32WLX clock_stm32l4_l5_wb_wl.c)
|
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_STM32WLX clock_stm32l4_l5_wb_wl.c)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_AGILEX clock_agilex_ll.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_AGILEX clock_agilex.c)
|
||||||
|
|
57
drivers/clock_control/clock_agilex.c
Normal file
57
drivers/clock_control/clock_agilex.c
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021, Intel Corporation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <drivers/clock_control.h>
|
||||||
|
#include <drivers/clock_control/clock_agilex_ll.h>
|
||||||
|
#include <dt-bindings/clock/intel_socfpga_clock.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <soc.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
|
||||||
|
|
||||||
|
static int clk_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
LOG_INF("Intel Clock driver initialized");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_get_rate(const struct device *dev,
|
||||||
|
clock_control_subsys_t sub_system,
|
||||||
|
uint32_t *rate)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
struct clock_attr *attr = (struct clock_attr *)(sub_system);
|
||||||
|
|
||||||
|
switch (attr->clock_id) {
|
||||||
|
case INTEL_SOCFPGA_CLOCK_MPU:
|
||||||
|
*rate = get_mpu_clk();
|
||||||
|
break;
|
||||||
|
case INTEL_SOCFPGA_CLOCK_WDT:
|
||||||
|
*rate = get_wdt_clk();
|
||||||
|
break;
|
||||||
|
case INTEL_SOCFPGA_CLOCK_UART:
|
||||||
|
*rate = get_uart_clk();
|
||||||
|
break;
|
||||||
|
case INTEL_SOCFPGA_CLOCK_MMC:
|
||||||
|
*rate = get_mmc_clk();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clock_control_driver_api clk_api = {
|
||||||
|
.get_rate = clk_get_rate
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE_DT_DEFINE(DT_NODELABEL(clock), clk_init, NULL, NULL, NULL,
|
||||||
|
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||||
|
&clk_api);
|
144
drivers/clock_control/clock_agilex_ll.c
Normal file
144
drivers/clock_control/clock_agilex_ll.c
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021, Intel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <arch/common/sys_bitops.h>
|
||||||
|
#include <drivers/clock_control/clock_agilex_ll.h>
|
||||||
|
#include <socfpga_system_manager.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Intel SoC re-use Arm Trusted Firmware (ATF) driver code in Zephyr.
|
||||||
|
* The migrated ATF driver code uses mmio_X macro to access the register.
|
||||||
|
* The following macros map mmio_X to Zephyr compatible function for
|
||||||
|
* register access. This allow Zephyr to re-use the ATF driver codes
|
||||||
|
* without massive changes.
|
||||||
|
*/
|
||||||
|
#define mmio_write_32(addr, data) sys_write32((data), (addr))
|
||||||
|
#define mmio_read_32(addr) sys_read32((addr))
|
||||||
|
#define mmio_setbits_32(addr, mask) sys_set_bits((addr), (mask))
|
||||||
|
#define mmio_clrbits_32(addr, mask) sys_clear_bits((addr), (mask))
|
||||||
|
|
||||||
|
/* Extract reference clock from platform clock source */
|
||||||
|
uint32_t get_ref_clk(uint32_t pllglob)
|
||||||
|
{
|
||||||
|
uint32_t arefclkdiv, ref_clk;
|
||||||
|
uint32_t scr_reg;
|
||||||
|
|
||||||
|
switch (CLKMGR_PSRC(pllglob)) {
|
||||||
|
case CLKMGR_PLLGLOB_PSRC_EOSC1:
|
||||||
|
scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
|
||||||
|
ref_clk = mmio_read_32(scr_reg);
|
||||||
|
break;
|
||||||
|
case CLKMGR_PLLGLOB_PSRC_INTOSC:
|
||||||
|
ref_clk = CLKMGR_INTOSC_HZ;
|
||||||
|
break;
|
||||||
|
case CLKMGR_PLLGLOB_PSRC_F2S:
|
||||||
|
scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
|
||||||
|
ref_clk = mmio_read_32(scr_reg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ref_clk = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
|
||||||
|
ref_clk /= arefclkdiv;
|
||||||
|
|
||||||
|
return ref_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate clock frequency based on parameter */
|
||||||
|
uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
|
||||||
|
{
|
||||||
|
uint32_t clk_psrc, mdiv, ref_clk;
|
||||||
|
uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
|
||||||
|
|
||||||
|
clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
|
||||||
|
|
||||||
|
switch (CLKMGR_PSRC(clk_psrc)) {
|
||||||
|
case CLKMGR_PSRC_MAIN:
|
||||||
|
pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
|
||||||
|
pllc_reg = CLKMGR_MAINPLL + main_pllc;
|
||||||
|
pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
|
||||||
|
break;
|
||||||
|
case CLKMGR_PSRC_PER:
|
||||||
|
pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM;
|
||||||
|
pllc_reg = CLKMGR_PERPLL + per_pllc;
|
||||||
|
pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
|
||||||
|
mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
|
||||||
|
ref_clk *= mdiv;
|
||||||
|
|
||||||
|
pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
|
||||||
|
|
||||||
|
return ref_clk / pllc_div;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return L3 interconnect clock */
|
||||||
|
uint32_t get_l3_clk(void)
|
||||||
|
{
|
||||||
|
uint32_t l3_clk;
|
||||||
|
|
||||||
|
l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
|
||||||
|
CLKMGR_PERPLL_PLLC1);
|
||||||
|
return l3_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate clock frequency to be used for mpu */
|
||||||
|
uint32_t get_mpu_clk(void)
|
||||||
|
{
|
||||||
|
uint32_t mpu_clk = 0;
|
||||||
|
|
||||||
|
mpu_clk = get_clk_freq(CLKMGR_MAINPLL_MPUCLK, CLKMGR_MAINPLL_PLLC0,
|
||||||
|
CLKMGR_PERPLL_PLLC0);
|
||||||
|
return mpu_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate clock frequency to be used for watchdog timer */
|
||||||
|
uint32_t get_wdt_clk(void)
|
||||||
|
{
|
||||||
|
uint32_t l3_clk, l4_sys_clk;
|
||||||
|
|
||||||
|
l3_clk = get_l3_clk();
|
||||||
|
l4_sys_clk = l3_clk / 4;
|
||||||
|
|
||||||
|
return l4_sys_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate clock frequency to be used for UART driver */
|
||||||
|
uint32_t get_uart_clk(void)
|
||||||
|
{
|
||||||
|
uint32_t data32, l3_clk, l4_sp_clk;
|
||||||
|
|
||||||
|
l3_clk = get_l3_clk();
|
||||||
|
|
||||||
|
data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
|
||||||
|
data32 = (data32 >> 16) & 0x3;
|
||||||
|
|
||||||
|
l4_sp_clk = l3_clk >> data32;
|
||||||
|
|
||||||
|
return l4_sp_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate clock frequency to be used for SDMMC driver */
|
||||||
|
uint32_t get_mmc_clk(void)
|
||||||
|
{
|
||||||
|
uint32_t data32, mmc_clk;
|
||||||
|
|
||||||
|
mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR,
|
||||||
|
CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
|
||||||
|
|
||||||
|
data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
|
||||||
|
data32 = (data32 & 0x7ff) + 1;
|
||||||
|
mmc_clk = (mmc_clk / data32) / 4;
|
||||||
|
|
||||||
|
return mmc_clk;
|
||||||
|
}
|
130
include/drivers/clock_control/clock_agilex_ll.h
Normal file
130
include/drivers/clock_control/clock_agilex_ll.h
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021, Intel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLOCKMANAGER_H
|
||||||
|
#define CLOCKMANAGER_H
|
||||||
|
|
||||||
|
#include <socfpga_handoff.h>
|
||||||
|
|
||||||
|
/* Clock Manager Registers */
|
||||||
|
#define CLKMGR_OFFSET 0xffd10000
|
||||||
|
|
||||||
|
#define CLKMGR_CTRL 0x0
|
||||||
|
#define CLKMGR_STAT 0x4
|
||||||
|
#define CLKMGR_INTRCLR 0x14
|
||||||
|
|
||||||
|
/* Main PLL Group */
|
||||||
|
#define CLKMGR_MAINPLL 0xffd10024
|
||||||
|
#define CLKMGR_MAINPLL_EN 0x0
|
||||||
|
#define CLKMGR_MAINPLL_BYPASS 0xc
|
||||||
|
#define CLKMGR_MAINPLL_MPUCLK 0x18
|
||||||
|
#define CLKMGR_MAINPLL_NOCCLK 0x1c
|
||||||
|
#define CLKMGR_MAINPLL_NOCDIV 0x20
|
||||||
|
#define CLKMGR_MAINPLL_PLLGLOB 0x24
|
||||||
|
#define CLKMGR_MAINPLL_FDBCK 0x28
|
||||||
|
#define CLKMGR_MAINPLL_MEM 0x2c
|
||||||
|
#define CLKMGR_MAINPLL_MEMSTAT 0x30
|
||||||
|
#define CLKMGR_MAINPLL_PLLC0 0x34
|
||||||
|
#define CLKMGR_MAINPLL_PLLC1 0x38
|
||||||
|
#define CLKMGR_MAINPLL_VCOCALIB 0x3c
|
||||||
|
#define CLKMGR_MAINPLL_PLLC2 0x40
|
||||||
|
#define CLKMGR_MAINPLL_PLLC3 0x44
|
||||||
|
#define CLKMGR_MAINPLL_PLLM 0x48
|
||||||
|
#define CLKMGR_MAINPLL_LOSTLOCK 0x54
|
||||||
|
|
||||||
|
/* Peripheral PLL Group */
|
||||||
|
#define CLKMGR_PERPLL 0xffd1007c
|
||||||
|
#define CLKMGR_PERPLL_EN 0x0
|
||||||
|
#define CLKMGR_PERPLL_BYPASS 0xc
|
||||||
|
#define CLKMGR_PERPLL_EMACCTL 0x18
|
||||||
|
#define CLKMGR_PERPLL_GPIODIV 0x1c
|
||||||
|
#define CLKMGR_PERPLL_PLLGLOB 0x20
|
||||||
|
#define CLKMGR_PERPLL_FDBCK 0x24
|
||||||
|
#define CLKMGR_PERPLL_MEM 0x28
|
||||||
|
#define CLKMGR_PERPLL_MEMSTAT 0x2c
|
||||||
|
#define CLKMGR_PERPLL_PLLC0 0x30
|
||||||
|
#define CLKMGR_PERPLL_PLLC1 0x34
|
||||||
|
#define CLKMGR_PERPLL_VCOCALIB 0x38
|
||||||
|
#define CLKMGR_PERPLL_PLLC2 0x3c
|
||||||
|
#define CLKMGR_PERPLL_PLLC3 0x40
|
||||||
|
#define CLKMGR_PERPLL_PLLM 0x44
|
||||||
|
#define CLKMGR_PERPLL_LOSTLOCK 0x50
|
||||||
|
|
||||||
|
/* Altera Group */
|
||||||
|
#define CLKMGR_ALTERA 0xffd100d0
|
||||||
|
#define CLKMGR_ALTERA_JTAG 0x0
|
||||||
|
#define CLKMGR_ALTERA_EMACACTR 0x4
|
||||||
|
#define CLKMGR_ALTERA_EMACBCTR 0x8
|
||||||
|
#define CLKMGR_ALTERA_EMACPTPCTR 0xc
|
||||||
|
#define CLKMGR_ALTERA_GPIODBCTR 0x10
|
||||||
|
#define CLKMGR_ALTERA_SDMMCCTR 0x14
|
||||||
|
#define CLKMGR_ALTERA_S2FUSER0CTR 0x18
|
||||||
|
#define CLKMGR_ALTERA_S2FUSER1CTR 0x1c
|
||||||
|
#define CLKMGR_ALTERA_PSIREFCTR 0x20
|
||||||
|
#define CLKMGR_ALTERA_EXTCNTRST 0x24
|
||||||
|
|
||||||
|
/* Membus */
|
||||||
|
#define CLKMGR_MEM_REQ BIT(24)
|
||||||
|
#define CLKMGR_MEM_WR BIT(25)
|
||||||
|
#define CLKMGR_MEM_ERR BIT(26)
|
||||||
|
#define CLKMGR_MEM_WDAT_OFFSET 16
|
||||||
|
#define CLKMGR_MEM_ADDR 0x4027
|
||||||
|
#define CLKMGR_MEM_WDAT 0x80
|
||||||
|
|
||||||
|
/* Clock Manager Macros */
|
||||||
|
#define CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001
|
||||||
|
#define CLKMGR_STAT_BUSY_E_BUSY 0x1
|
||||||
|
#define CLKMGR_STAT_BUSY(x) (((x) & 0x00000001) >> 0)
|
||||||
|
#define CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100) >> 8)
|
||||||
|
#define CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00010000) >> 16)
|
||||||
|
#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004
|
||||||
|
#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008
|
||||||
|
#define CLKMGR_INTOSC_HZ 460000000
|
||||||
|
|
||||||
|
/* Main PLL Macros */
|
||||||
|
#define CLKMGR_MAINPLL_EN_RESET 0x000000ff
|
||||||
|
|
||||||
|
/* Peripheral PLL Macros */
|
||||||
|
#define CLKMGR_PERPLL_EN_RESET 0x00000fff
|
||||||
|
#define CLKMGR_PERPLL_EN_SDMMCCLK BIT(5)
|
||||||
|
#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff)
|
||||||
|
|
||||||
|
/* Altera Macros */
|
||||||
|
#define CLKMGR_ALTERA_EXTCNTRST_RESET 0xff
|
||||||
|
|
||||||
|
/* Shared Macros */
|
||||||
|
#define CLKMGR_PSRC(x) (((x) & 0x00030000) >> 16)
|
||||||
|
#define CLKMGR_PSRC_MAIN 0
|
||||||
|
#define CLKMGR_PSRC_PER 1
|
||||||
|
|
||||||
|
#define CLKMGR_PLLGLOB_PSRC_EOSC1 0x0
|
||||||
|
#define CLKMGR_PLLGLOB_PSRC_INTOSC 0x1
|
||||||
|
#define CLKMGR_PLLGLOB_PSRC_F2S 0x2
|
||||||
|
|
||||||
|
#define CLKMGR_PLLM_MDIV(x) ((x) & 0x000003ff)
|
||||||
|
#define CLKMGR_PLLGLOB_PD_SET_MSK 0x00000001
|
||||||
|
#define CLKMGR_PLLGLOB_RST_SET_MSK 0x00000002
|
||||||
|
|
||||||
|
#define CLKMGR_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8)
|
||||||
|
#define CLKMGR_PLLGLOB_AREFCLKDIV(x) (((x) & 0x00000f00) >> 8)
|
||||||
|
#define CLKMGR_PLLGLOB_DREFCLKDIV(x) (((x) & 0x00003000) >> 12)
|
||||||
|
|
||||||
|
#define CLKMGR_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000003ff)
|
||||||
|
#define CLKMGR_VCOCALIB_MSCNT_SET(x) (((x) << 16) & 0x00ff0000)
|
||||||
|
|
||||||
|
#define CLKMGR_CLR_LOSTLOCK_BYPASS 0x20000000
|
||||||
|
|
||||||
|
struct clock_attr {
|
||||||
|
uint32_t clock_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void config_clkmgr_handoff(struct handoff *hoff_ptr);
|
||||||
|
uint32_t get_mpu_clk(void);
|
||||||
|
uint32_t get_wdt_clk(void);
|
||||||
|
uint32_t get_uart_clk(void);
|
||||||
|
uint32_t get_mmc_clk(void);
|
||||||
|
|
||||||
|
#endif
|
16
include/dt-bindings/clock/intel_socfpga_clock.h
Normal file
16
include/dt-bindings/clock/intel_socfpga_clock.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021, Intel Corporation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_INTEL_SOCFPGA_CLOCK_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_INTEL_SOCFPGA_CLOCK_H_
|
||||||
|
|
||||||
|
#define INTEL_SOCFPGA_CLOCK_MPU 0
|
||||||
|
#define INTEL_SOCFPGA_CLOCK_WDT 1
|
||||||
|
#define INTEL_SOCFPGA_CLOCK_UART 2
|
||||||
|
#define INTEL_SOCFPGA_CLOCK_MMC 3
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_INTEL_SOCFPGA_CLOCK_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue