You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
7.2 KiB
263 lines
7.2 KiB
/* |
|
* Copyright (c) 2020 Antmicro <www.antmicro.com> |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#ifndef LITEX_MMCM_H |
|
#define LITEX_MMCM_H |
|
|
|
#include <zephyr/types.h> |
|
|
|
/* Common values */ |
|
#define PICOS_IN_SEC 1000000000000 |
|
#define BITS_PER_BYTE 8 |
|
|
|
/* MMCM specific numbers */ |
|
#define CLKOUT_MAX 7 |
|
#define DELAY_TIME_MAX 63 |
|
#define PHASE_MUX_MAX 7 |
|
#define HIGH_LOW_TIME_REG_MAX 63 |
|
#define PHASE_MUX_RES_FACTOR 8 |
|
|
|
/* DRP registers index */ |
|
#define DRP_RESET 0 |
|
#define DRP_LOCKED 1 |
|
#define DRP_READ 2 |
|
#define DRP_WRITE 3 |
|
#define DRP_DRDY 4 |
|
#define DRP_ADR 5 |
|
#define DRP_DAT_W 6 |
|
#define DRP_DAT_R 7 |
|
|
|
/* Base address */ |
|
#define DRP_BASE DT_REG_ADDR_BY_IDX(MMCM, 0) |
|
/* Register address */ |
|
#define DRP_ADDR_RESET DT_REG_ADDR_BY_NAME(MMCM, drp_reset) |
|
#define DRP_ADDR_LOCKED DT_REG_ADDR_BY_NAME(MMCM, drp_locked) |
|
#define DRP_ADDR_READ DT_REG_ADDR_BY_NAME(MMCM, drp_read) |
|
#define DRP_ADDR_WRITE DT_REG_ADDR_BY_NAME(MMCM, drp_write) |
|
#define DRP_ADDR_DRDY DT_REG_ADDR_BY_NAME(MMCM, drp_drdy) |
|
#define DRP_ADDR_ADR DT_REG_ADDR_BY_NAME(MMCM, drp_adr) |
|
#define DRP_ADDR_DAT_W DT_REG_ADDR_BY_NAME(MMCM, drp_dat_w) |
|
#define DRP_ADDR_DAT_R DT_REG_ADDR_BY_NAME(MMCM, drp_dat_r) |
|
|
|
/* Devicetree global defines */ |
|
#define LOCK_TIMEOUT DT_PROP(MMCM, litex_lock_timeout) |
|
#define DRDY_TIMEOUT DT_PROP(MMCM, litex_drdy_timeout) |
|
#define DIVCLK_DIVIDE_MIN DT_PROP(MMCM, litex_divclk_divide_min) |
|
#define DIVCLK_DIVIDE_MAX DT_PROP(MMCM, litex_divclk_divide_max) |
|
#define CLKFBOUT_MULT_MIN DT_PROP(MMCM, litex_clkfbout_mult_min) |
|
#define CLKFBOUT_MULT_MAX DT_PROP(MMCM, litex_clkfbout_mult_max) |
|
#define VCO_FREQ_MIN DT_PROP(MMCM, litex_vco_freq_min) |
|
#define VCO_FREQ_MAX DT_PROP(MMCM, litex_vco_freq_max) |
|
#define CLKOUT_DIVIDE_MIN DT_PROP(MMCM, litex_clkout_divide_min) |
|
#define CLKOUT_DIVIDE_MAX DT_PROP(MMCM, litex_clkout_divide_max) |
|
#define VCO_MARGIN DT_PROP(MMCM, litex_vco_margin) |
|
|
|
#define CLKOUT_INIT(N) \ |
|
BUILD_ASSERT(CLKOUT_DUTY_DEN(N) > 0 && \ |
|
CLKOUT_DUTY_NUM(N) > 0 && \ |
|
CLKOUT_DUTY_NUM(N) <= CLKOUT_DUTY_DEN(N), \ |
|
"Invalid default duty"); \ |
|
BUILD_ASSERT(CLKOUT_ID(N) < NCLKOUT, "Invalid CLKOUT index"); \ |
|
lcko = &ldev->clkouts[N]; \ |
|
lcko->id = CLKOUT_ID(N); \ |
|
\ |
|
lcko->clkout_div = clkout_div; \ |
|
lcko->def.freq = CLKOUT_FREQ(N); \ |
|
lcko->def.phase = CLKOUT_PHASE(N); \ |
|
lcko->def.duty.num = CLKOUT_DUTY_NUM(N); \ |
|
lcko->def.duty.den = CLKOUT_DUTY_DEN(N); \ |
|
lcko->margin.m = CLKOUT_MARGIN(N); \ |
|
lcko->margin.exp = CLKOUT_MARGIN_EXP(N); |
|
|
|
/* Devicetree clkout defines */ |
|
#define CLKOUT_EXIST(N) DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(clk##N)) |
|
#define CLKOUT_ID(N) DT_REG_ADDR(DT_NODELABEL(clk##N)) |
|
#define CLKOUT_FREQ(N) DT_PROP(DT_NODELABEL(clk##N), \ |
|
litex_clock_frequency) |
|
#define CLKOUT_PHASE(N) DT_PROP(DT_NODELABEL(clk##N), \ |
|
litex_clock_phase) |
|
#define CLKOUT_DUTY_NUM(N) DT_PROP(DT_NODELABEL(clk##N), \ |
|
litex_clock_duty_num) |
|
#define CLKOUT_DUTY_DEN(N) DT_PROP(DT_NODELABEL(clk##N), \ |
|
litex_clock_duty_den) |
|
#define CLKOUT_MARGIN(N) DT_PROP(DT_NODELABEL(clk##N), \ |
|
litex_clock_margin) |
|
#define CLKOUT_MARGIN_EXP(N) DT_PROP(DT_NODELABEL(clk##N), \ |
|
litex_clock_margin_exp) |
|
|
|
/* Register values */ |
|
#define FULL_REG_16 0xFFFF |
|
#define ZERO_REG 0x0 |
|
#define KEEP_IN_MUL_REG1 0xF000 |
|
#define KEEP_IN_MUL_REG2 0xFF3F |
|
#define KEEP_IN_DIV 0xC000 |
|
#define REG1_FREQ_MASK 0xF000 |
|
#define REG2_FREQ_MASK 0x803F |
|
#define REG1_DUTY_MASK 0xF000 |
|
#define REG2_DUTY_MASK 0xFF7F |
|
#define REG1_PHASE_MASK 0x1FFF |
|
#define REG2_PHASE_MASK 0xFCC0 |
|
#define FILT1_MASK 0x66FF |
|
#define FILT2_MASK 0x666F |
|
#define LOCK1_MASK 0xFC00 |
|
#define LOCK23_MASK 0x8000 |
|
/* Control bits extraction masks */ |
|
#define HL_TIME_MASK 0x3F |
|
#define FRAC_MASK 0x7 |
|
#define EDGE_MASK 0x1 |
|
#define NO_CNT_MASK 0x1 |
|
#define FRAC_EN_MASK 0x1 |
|
#define PHASE_MUX_MASK 0x7 |
|
|
|
/* Bit groups start position in DRP registers */ |
|
#define HIGH_TIME_POS 6 |
|
#define LOW_TIME_POS 0 |
|
#define PHASE_MUX_POS 13 |
|
#define FRAC_POS 12 |
|
#define FRAC_EN_POS 11 |
|
#define FRAC_WF_R_POS 10 |
|
#define EDGE_POS 7 |
|
#define NO_CNT_POS 6 |
|
#define EDGE_DIVREG_POS 13 |
|
#define NO_CNT_DIVREG_POS 12 |
|
#define DELAY_TIME_POS 0 |
|
|
|
/* MMCM Register addresses */ |
|
#define POWER_REG 0x28 |
|
#define DIV_REG 0x16 |
|
#define LOCK_REG1 0x18 |
|
#define LOCK_REG2 0x19 |
|
#define LOCK_REG3 0x1A |
|
#define FILT_REG1 0x4E |
|
#define FILT_REG2 0x4F |
|
#define CLKOUT0_REG1 0x08 |
|
#define CLKOUT0_REG2 0x09 |
|
#define CLKOUT1_REG1 0x0A |
|
#define CLKOUT1_REG2 0x0B |
|
#define CLKOUT2_REG1 0x0C |
|
#define CLKOUT2_REG2 0x0D |
|
#define CLKOUT3_REG1 0x0E |
|
#define CLKOUT3_REG2 0x0F |
|
#define CLKOUT4_REG1 0x10 |
|
#define CLKOUT4_REG2 0x11 |
|
#define CLKOUT5_REG1 0x06 |
|
#define CLKOUT5_REG2 0x07 |
|
#define CLKOUT6_REG1 0x12 |
|
#define CLKOUT6_REG2 0x13 |
|
#define CLKFBOUT_REG1 0x14 |
|
#define CLKFBOUT_REG2 0x15 |
|
|
|
/* Basic structure for DRP registers */ |
|
struct litex_drp_reg { |
|
uint32_t addr; |
|
uint32_t size; |
|
}; |
|
|
|
struct litex_clk_range { |
|
uint32_t min; |
|
uint32_t max; |
|
}; |
|
|
|
struct clk_duty { |
|
uint32_t num; |
|
uint32_t den; |
|
}; |
|
|
|
struct litex_clk_default { |
|
struct clk_duty duty; |
|
int phase; |
|
uint32_t freq; |
|
}; |
|
|
|
struct litex_clk_glob_params { |
|
uint64_t freq; |
|
uint32_t div; |
|
uint32_t mul; |
|
}; |
|
|
|
/* Divider configuration bits group */ |
|
struct litex_clk_div_params { |
|
uint8_t high_time; |
|
uint8_t low_time; |
|
uint8_t no_cnt; |
|
uint8_t edge; |
|
}; |
|
|
|
/* Phase configuration bits group */ |
|
struct litex_clk_phase_params { |
|
uint8_t phase_mux; |
|
uint8_t delay_time; |
|
uint8_t mx; |
|
}; |
|
|
|
/* Fractional configuration bits group */ |
|
struct litex_clk_frac_params { |
|
uint8_t frac_en; |
|
uint8_t frac; |
|
uint8_t phase_mux_f; |
|
uint8_t frac_wf_r; |
|
uint8_t frac_wf_f; |
|
}; |
|
|
|
struct litex_clk_params { |
|
struct clk_duty duty; |
|
int phase; |
|
uint32_t freq; |
|
uint32_t period_off; |
|
uint8_t div; |
|
}; |
|
|
|
struct litex_clk_timeout { |
|
uint32_t lock; |
|
uint32_t drdy; |
|
}; |
|
|
|
/* Basic structure for MMCM reg addresses */ |
|
struct litex_clk_clkout_addr { |
|
uint8_t reg1; |
|
uint8_t reg2; |
|
}; |
|
|
|
/* Structure for all MMCM regs */ |
|
struct litex_clk_regs_addr { |
|
struct litex_clk_clkout_addr clkout[CLKOUT_MAX]; |
|
}; |
|
|
|
struct litex_clk_clkout_margin { |
|
uint32_t m; /* margin factor scaled to integer */ |
|
uint32_t exp; |
|
}; |
|
|
|
struct litex_clk_device { |
|
uint32_t *base; |
|
/*struct clk_hw clk_hw;*/ |
|
struct litex_clk_clkout *clkouts; /* array of clock outputs */ |
|
struct litex_clk_timeout timeout; /* timeouts for wait functions*/ |
|
struct litex_clk_glob_params g_config; /* general MMCM settings */ |
|
struct litex_clk_glob_params ts_g_config;/* settings to set*/ |
|
struct litex_clk_range divclk; /* divclk_divide_range */ |
|
struct litex_clk_range clkfbout; /* clkfbout_mult_frange */ |
|
struct litex_clk_range vco; /* vco_freq_range */ |
|
uint8_t *update_clkout; /* which clkout needs update */ |
|
uint32_t vco_margin; |
|
uint32_t nclkout; |
|
}; |
|
|
|
struct litex_clk_clkout { |
|
uint32_t *base; |
|
struct litex_clk_device *ldev; /* global data */ |
|
struct litex_clk_default def; /* DTS defaults */ |
|
struct litex_clk_params config; /* real CLKOUT settings */ |
|
struct litex_clk_params ts_config; /* CLKOUT settings to set */ |
|
struct litex_clk_div_params div; /* CLKOUT configuration groups*/ |
|
struct litex_clk_phase_params phase; |
|
struct litex_clk_frac_params frac; |
|
struct litex_clk_range clkout_div; /* clkout_divide_range */ |
|
struct litex_clk_clkout_margin margin; |
|
uint32_t id; |
|
}; |
|
|
|
#endif /* LITEX_MMCM_H */
|
|
|