Feat:Clock:Init!

OSC freq,PLLC,PLLX,PLLU,PLLP,UART clock bring up
This commit is contained in:
hydrogenium2020 2024-01-31 16:40:19 +08:00
parent b5d514cfac
commit d4a5b5f87f
5 changed files with 454 additions and 25 deletions

View File

@ -22,6 +22,97 @@
#include "util.h" #include "util.h"
#include "types.h" #include "types.h"
enum {
OSC_FREQ_13 = 0,
OSC_FREQ_16P8 = 1,
OSC_FREQ_19P2 = 4,
OSC_FREQ_38P4 = 5,
OSC_FREQ_12 = 8,
OSC_FREQ_48 = 9,
OSC_FREQ_26 = 12
};
/* This table defines the frequency dividers for every PLL to turn the external
* OSC clock into the frequencies defined by TEGRA_PLL*_KHZ in soc/clock.h.
* All PLLs have three dividers (n, m and p), with the governing formula for
* the output frequency being CF = (IN / m), VCO = CF * n and OUT = VCO / (2^p).
* All divisor configurations must meet the PLL's constraints for VCO and CF:
* PLLX: 12 MHz < CF < 50 MHz, 700 MHz < VCO < 3000 MHz
* PLLC: 12 MHz < CF < 50 MHz, 600 MHz < VCO < 1400 MHz
* PLLM: 12 MHz < CF < 50 MHz, 400 MHz < VCO < 1066 MHz
* PLLP: 1 MHz < CF < 6 MHz, 200 MHz < VCO < 700 MHz
* PLLD: 1 MHz < CF < 6 MHz, 500 MHz < VCO < 1000 MHz
* PLLU: 1 MHz < CF < 6 MHz, 480 MHz < VCO < 960 MHz
* PLLDP: 12 MHz < CF < 38 MHz, 600 MHz < VCO < 1200 MHz
* (values taken from Linux' drivers/clk/tegra/clk-tegra124.c). */
struct {
int khz;
struct pllcx_dividers pllx; /* target: CONFIG_PLLX_KHZ */
struct pllcx_dividers pllc; /* target: 600 MHz */
/* PLLM is set up dynamically by clock_sdram(). */
/* PLLP is hardwired to 408 MHz in HW (unless we set BASE_OVRD). */
struct pllu_dividers pllu; /* target; 960 MHz */
struct pllcx_dividers plldp; /* target; 270 MHz */
/* PLLDP treats p differently (OUT = VCO / (p + 1) for p < 6). */
} static const osc_table[16] = {
[OSC_FREQ_12] = {
.khz = 12000,
.pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0},
.pllc = {.n = 50, .m = 1, .p = 0},
.pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2},
.plldp = {.n = 90, .m = 1, .p = 3},
},
[OSC_FREQ_13] = {
.khz = 13000,
.pllx = {.n = TEGRA_PLLX_KHZ / 13000, .m = 1, .p = 0},
.pllc = {.n = 46, .m = 1, .p = 0}, /* 598.0 MHz */
.pllu = {.n = 960, .m = 13, .p = 0, .cpcon = 12, .lfcon = 2},
.plldp = {.n = 83, .m = 1, .p = 3}, /* 269.8 MHz */
},
[OSC_FREQ_16P8] = {
.khz = 16800,
.pllx = {.n = TEGRA_PLLX_KHZ / 16800, .m = 1, .p = 0},
.pllc = {.n = 71, .m = 1, .p = 1}, /* 596.4 MHz */
.pllu = {.n = 400, .m = 7, .p = 0, .cpcon = 5, .lfcon = 2},
.plldp = {.n = 64, .m = 1, .p = 3}, /* 268.8 MHz */
},
[OSC_FREQ_19P2] = {
.khz = 19200,
.pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0},
.pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */
.pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2},
.plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */
},
[OSC_FREQ_26] = {
.khz = 26000,
.pllx = {.n = TEGRA_PLLX_KHZ / 26000, .m = 1, .p = 0},
.pllc = {.n = 23, .m = 1, .p = 0}, /* 598.0 MHz */
.pllu = {.n = 960, .m = 26, .p = 0, .cpcon = 12, .lfcon = 2},
.plldp = {.n = 83, .m = 2, .p = 3}, /* 269.8 MHz */
},
/* These oscillators get predivided as PLL inputs... n/m/p divisors for
* 38.4 should always match 19.2, and 48 should always match 12. */
[OSC_FREQ_38P4] = {
.khz = 38400,
.pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0},
.pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */
.pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2},
.plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */
},
[OSC_FREQ_48] = {
.khz = 48000,
.pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0},
.pllc = {.n = 50, .m = 1, .p = 0},
.pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2},
.plldp = {.n = 90, .m = 1, .p = 3},
},
};
enum {
SCLK_SYS_STATE_STDBY,
SCLK_SYS_STATE_IDLE,
SCLK_SYS_STATE_RUN,
SCLK_SYS_STATE_IRQ = 4U,
SCLK_SYS_STATE_FIQ = 8U,
};
void clock_enable(const clk_rst_t *clk) void clock_enable(const clk_rst_t *clk)
{ {
// Put clock into reset. // Put clock into reset.
@ -47,26 +138,179 @@ void clock_disable(const clk_rst_t *clk)
CLOCK(clk->enable) &= ~BIT(clk->index); CLOCK(clk->enable) &= ~BIT(clk->index);
} }
//For NS Switch static void init_pll(u32 pll_base_offset, u32 pll_misc_offset, const union pll_fields pll, u32 lock)
/*
* CLK_OSC - 38.4 MHz crystal.
* CLK_M - 19.2 MHz (osc/2).
* CLK_S - 32.768 KHz (from PMIC).
* SCLK - 204MHz init (-> 408MHz -> OC).
* HCLK - 204MHz init (-> 408MHz -> OC).
* PCLK - 68MHz init (-> 136MHz -> OC/4).
*/
//For P1761(Ardbeg,Fuze F1)
/*
* CLK_OSC - 12 MHz crystal.
* CLK_M - 12 MHz (osc/2).
* CLK_S - 32.768 KHz (from PMIC).
* SCLK - 127.5MHz init (-> 408MHz -> OC).
* HCLK - 127.5MHz init (-> 408MHz -> OC).
* PCLK - 31.875?MHz init (-> 136MHz -> OC/4).
*/
void config_oscillators()
{ {
//TODO: rename
u32 dividers = pll.div.n << PLL_BASE_DIVN_SHIFT |
pll.div.m << PLL_BASE_DIVM_SHIFT |
pll.div.p << PLL_BASE_DIVP_SHIFT;
u32 misc_con = pll.div.cpcon << PLL_MISC_CPCON_SHIFT |
pll.div.lfcon << PLL_MISC_LFCON_SHIFT;
/* Write dividers but BYPASS the PLL while we're messing with it. */
CLOCK(pll_base_offset)=dividers | (1<<CLK_RST_CONTROLLER_PLLC_BASE_PLLC_BYPASS_SHIFT);
/*
* Set Lock bit, CPCON and LFCON fields (default to 0 if it doesn't
* exist for this PLL)
*/
CLOCK(pll_misc_offset)=(lock | misc_con);
/* Enable PLL and take it back out of BYPASS */
CLOCK(pll_base_offset)=dividers | (1 << CLK_RST_CONTROLLER_PLLC_BASE_PLLC_ENABLE_SHIFT);
/* Wait for lock ready */
while (!(CLOCK(pll_base_offset) & (1 << CLK_RST_CONTROLLER_PLLC_BASE_PLLC_LOCK_SHIFT)));
} }
/* From Coreboot */
/* Clock configuration. */
void config_oscillators()
{
// clock_get_osc_bits()
// Copied from coreboot
// OSC_FREQ_13 = 0,
// OSC_FREQ_16P8 = 1,
// OSC_FREQ_19P2 = 4,
// OSC_FREQ_38P4 = 5,
// OSC_FREQ_12 = 8,
// OSC_FREQ_48 = 9,
// OSC_FREQ_26 = 12
//
// 8 is 12mhz
//TODO other osc freq porting
u32 clk_osc_bit=(CLOCK(CLK_RST_CONTROLLER_OSC_CTRL)&CLK_OSC_FREQ_MASK)>>CLK_OSC_FREQ_SHIFT;
/* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC2)=(0x2b << 17 | 0xb << 9);
// static const osc_table[16] = {
// [OSC_FREQ_12] = {
// .khz = 12000,
// .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0},
// .pllc = {.n = 50, .m = 1, .p = 0},
// .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2},
// .plldp = {.n = 90, .m = 1, .p = 3},
// },
/* Max out the AVP clock before everything else (need PLLC for that). */
init_pll(CLK_RST_CONTROLLER_PLLC_BASE,CLK_RST_CONTROLLER_PLLC_MISC,osc_table[clk_osc_bit].pllc,(1 << CLK_RST_CONTROLLER_PLLC_MISC_PLLC_LOCK_ENABLE_SHIFT));
printf_("[x] PLLC setup\n");
/* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA
* features section in the TRM). */
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE)=
TEGRA_HCLK_RATIO << CLK_RST_CONTROLLER_CLK_SYSTEM_RATE_AHB_RATE_SHIFT |
TEGRA_PCLK_RATIO << CLK_RST_CONTROLLER_CLK_SYSTEM_RATE_APB_RATE_SHIFT;
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT)=CLK_DIVIDER(TEGRA_PLLC_KHZ, TEGRA_SCLK_KHZ)
<< CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RATIO_SHIFT | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_CLKEN_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RSTN_SHIFT);
/* sclk = 300 MHz */
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY)=
CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SYS_STATE_RUN << CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SYS_STATE_SHIFT |
CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_PLLC_OUT1 <<CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_SHIFT;
printf_("[x] System Clock:300 Mhz\n");
// Read oscillator drive strength from OSC_EDPD_OVER.XOFS and copy
// to OSC_CTRL.XOFS and set XOE. --copied from lp0
/*
* Ambiguous quote from u-boot. TODO: what's this mean?
* "should update same value in PMC_OSC_EDPD_OVER XOFS
* field for warmboot "
*/
u32 xofs = (PMC(APBDEV_PMC_OSC_EDPD_OVER) &
PMC_XOFS_MASK) >> PMC_XOFS_SHIFT;
/*Change the oscillator drive strength (from U-Boot -- why?) */
u32 osc_ctrl = CLOCK(CLK_RST_CONTROLLER_OSC_CTRL);
osc_ctrl &= ~CLK_OSC_XOFS_MASK;
osc_ctrl |= (xofs << CLK_OSC_XOFS_SHIFT);
osc_ctrl |= CLK_OSC_XOE;
CLOCK(CLK_RST_CONTROLLER_OSC_CTRL)=osc_ctrl;
/* Disable IDDQ for PLLX before we set it up (from U-Boot -- why?) */
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ.
/* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */
//pll2 ovr shift should be 18?
CLOCK(CLK_RST_CONTROLLER_PLLP_OUTA)=((CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RATIO_SHIFT) |
(1 << CLK_RST_CONTROLLER_PLLP_OUTA_PLLP_OUT1_OVRRIDE_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_CLKEN_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RSTN_SHIFT)) << PLL_OUT1_SHIFT |
(CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RATIO_SHIFT) |
(1 << CLK_RST_CONTROLLER_PLLP_OUTA_PLLP_OUT1_OVRRIDE_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_CLKEN_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RSTN_SHIFT)) << PLL_OUT2_SHIFT);
CLOCK(CLK_RST_CONTROLLER_PLLP_OUTB)= ((CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RATIO_SHIFT) |
(1 << CLK_RST_CONTROLLER_PLLP_OUTA_PLLP_OUT1_OVRRIDE_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_CLKEN_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RSTN_SHIFT)) << PLL_OUT3_SHIFT |
(CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RATIO_SHIFT) |
(1 << CLK_RST_CONTROLLER_PLLP_OUTA_PLLP_OUT1_OVRRIDE_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_CLKEN_SHIFT) | (1 << CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RSTN_SHIFT)) << PLL_OUT4_SHIFT);
init_pll(CLK_RST_CONTROLLER_PLLX_BASE,CLK_RST_CONTROLLER_PLLX_MISC,osc_table[clk_osc_bit].pllx,(1 << CLK_RST_CONTROLLER_PLLX_MISC_PLLX_LOCK_ENABLE_SHIFT));
init_pll(CLK_RST_CONTROLLER_PLLU_BASE,CLK_RST_CONTROLLER_PLLU_MISC,osc_table[clk_osc_bit].pllu,(1 << CLK_RST_CONTROLLER_PLLU_MISC_PLLU_LOCK_ENABLE_SHIFT));
//TODO usb device init later
/* Graphics just has to be different. There's a few more bits we
* need to set in here, but it makes sense just to restrict all the
* special bits to this one function. Imported form graphics_pll(void)
*/
/* the vendor code sets the dither bit (28)
* an undocumented bit (24)
* and clamp while we mess with it (22)
* Dither is pretty important to display port
* so we really do need to handle these bits.
* I'm not willing to not clamp it, even if
* it might "mostly work" with it not set,
* I don't want to find out in a few months
* that it is needed.
*/
u32 scfg = (1<<28) | (1<<24) | (1<<22);
CLOCK(CLK_RST_CONTROLLER_PLLDP_SS_CFG)=scfg;
init_pll(CLK_RST_CONTROLLER_PLLDP_BASE, CLK_RST_CONTROLLER_PLLDP_MISC,
osc_table[clk_osc_bit].plldp, (1 << CLK_RST_CONTROLLER_PLLDP_MISC_0_PLLDP_LOCK_ENABLE_SHIFT));
/* leave dither and undoc bits set, release clamp */
scfg = (1<<28) | (1<<24);
CLOCK(CLK_RST_CONTROLLER_PLLDP_SS_CFG)=scfg;
/* disp1 will be set when panel information (pixel clock) is
* retrieved (clock_display).
*/
printf_("[X] PLLP,PLLX,PLLU,PLLDP setup\n");
}
static const clk_rst_t _clock_uart[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, 2 },
};
void clock_enable_uart(u32 idx)
{
clock_enable(&_clock_uart[idx]);
}
#define UART_SRC_CLK_DIV_EN BIT(24)
int clock_uart_use_src_div(u32 idx, u32 baud)
{
u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000;
if (baud == 3000000)
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 15;
else if (baud == 1000000)
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49;
else
{
CLOCK(_clock_uart[idx].source) = clk_src_div | 2;
return 1;
}
return 0;
}

View File

@ -26,12 +26,192 @@ typedef struct _clk_rst_t
u8 clk_src; u8 clk_src;
u8 clk_div; u8 clk_div;
} clk_rst_t; } clk_rst_t;
/* soc-specific */
#define TEGRA_CLK_M_KHZ 12000
#define TEGRA_PLLX_KHZ 2000000
#define TEGRA_PLLP_KHZ (408000)
#define TEGRA_PLLC_KHZ (600000)
#define TEGRA_PLLD_KHZ (925000)
#define TEGRA_PLLU_KHZ (960000)
#define TEGRA_SCLK_KHZ (300000)
#define TEGRA_HCLK_RATIO 1
#define TEGRA_HCLK_KHZ (TEGRA_SCLK_KHZ / (1 + TEGRA_HCLK_RATIO))
#define TEGRA_PCLK_RATIO 0
#define TEGRA_PCLK_KHZ (TEGRA_HCLK_KHZ / (1 + TEGRA_PCLK_RATIO))
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50
#define CLK_OSC_DRIVE_STRENGTH 7
//PLLC
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80
#define CLK_RST_CONTROLLER_PLLC_MISC 0x8c
#define CLK_RST_CONTROLLER_PLLC_MISC_PLLC_LOCK_ENABLE_SHIFT 24
#define CLK_RST_CONTROLLER_PLLC_MISC2 0x88
#define CLK_RST_CONTROLLER_PLLC_BASE_PLLC_BYPASS_SHIFT 31
#define CLK_RST_CONTROLLER_PLLC_OUT 0x84
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE_AHB_RATE_SHIFT 4
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE_APB_RATE_SHIFT 0
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY 0x28
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SYS_STATE_SHIFT 28
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SYS_STATE_IDLE 1
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SYS_STATE_RUN 2
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_PLLC_OUT1 1
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_PLLP_OUT4 2
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_PLLP_OUT3 3
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_PLLP_OUT2 4
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE_SHIFT 4
//PLLP
#define CLK_RST_CONTROLLER_PLLP_OUTA 0xA4
#define CLK_RST_CONTROLLER_PLLP_OUTB 0xA8
#define CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RATIO_SHIFT 8
#define CLK_RST_CONTROLLER_PLLP_OUTA_PLLP_OUT1_OVRRIDE_SHIFT 2
#define CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_CLKEN_SHIFT 1
#define CLK_RST_CONTROLLER_PLLM_OUT_PLLM_OUT1_RSTN_SHIFT 0
//PLLX
#define PLLX_MISC3_IDDQ (1U << 3)
#define CLK_RST_CONTROLLER_PLLX_BASE 0xe0
#define CLK_RST_CONTROLLER_PLLX_MISC 0xe4
#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518
#define CLK_RST_CONTROLLER_PLLX_MISC_PLLX_LOCK_ENABLE_SHIFT 18
//PLLU
#define CLK_RST_CONTROLLER_PLLU_BASE 0xc0
#define CLK_RST_CONTROLLER_PLLU_MISC 0xcc
#define CLK_RST_CONTROLLER_PLLU_MISC_PLLU_LOCK_ENABLE_SHIFT 22
//PLLDP (Graphis PLL)
#define CLK_RST_CONTROLLER_PLLDP_SS_CFG 0x598
#define CLK_RST_CONTROLLER_PLLDP_BASE 0x590
#define CLK_RST_CONTROLLER_PLLDP_MISC 0x594
#define CLK_RST_CONTROLLER_PLLDP_MISC_0_PLLDP_LOCK_ENABLE_SHIFT 30
#define PLL_OUT1_SHIFT 0
#define PLL_OUT2_SHIFT 16
#define PLL_OUT3_SHIFT 0
#define PLL_OUT4_SHIFT 16
#define PLL_BASE_DIVN_SHIFT 8
#define PLL_BASE_DIVM_SHIFT 0
#define PLL_BASE_DIVP_SHIFT 20
#define PLL_MISC_CPCON_SHIFT 8
#define PLL_MISC_LFCON_SHIFT 4
#define CLK_RST_CONTROLLER_PLLC_BASE_PLLC_ENABLE_SHIFT 30
#define CLK_RST_CONTROLLER_PLLC_BASE_PLLC_LOCK_SHIFT 27
#define PLLCX_BASE_LOCK BIT(27)
#define DIV_ROUND_UP(x, y) ({ \
__typeof__(x) _div_local_x = (x); \
__typeof__(y) _div_local_y = (y); \
(_div_local_x + _div_local_y - 1) / _div_local_y; \
})
#define CLK_DIVIDER(REF, FREQ) (DIV_ROUND_UP(((REF) * 2), (FREQ)) - 2)
//MC
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19c
#define CLK_RST_CONTROLLER_CLK_ENB_H_SET 0x328
#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284
#define CLK_RST_CONTROLLER_RST_DEV_H_SET 0x308
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3a4
//Reset
#define CLK_RST_CONTROLLER_RST_DEVICES_L 0x4
#define CLK_RST_CONTROLLER_RST_DEVICES_H 0x8
#define CLK_RST_CONTROLLER_RST_DEVICES_U 0xC
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L 0x10
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_H 0x14
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U 0x18
//UART
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA 0x178
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB 0x17C
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC 0x1A0
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTD 0x1C0
enum CLK_L_DEV
{
CLK_L_UARTA = 6,
CLK_L_UARTB = 7,
};
enum CLK_H_DEV
{
CLK_H_UARTC = 23,
};
enum CLK_U_DEV
{
CLK_U_UARTD = 1,
};
enum {
CLK_OSC_XOE = 0x1 << 0,
CLK_OSC_XOFS_SHIFT = 4,
CLK_OSC_XOFS_MASK = 0x3f << CLK_OSC_XOFS_SHIFT,
CLK_OSC_FREQ_SHIFT = 28,
CLK_OSC_FREQ_MASK = 0xf << CLK_OSC_FREQ_SHIFT
};
struct pll_dividers {
u32 n : 10;
u32 m : 8;
u32 p : 4;
u32 cpcon : 4;
u32 lfcon : 4;
u32 : 2;
};
/* Some PLLs have more restrictive divider bit lengths or are missing some
* fields. Make sure to use the right struct in the osc_table definition to get
* compile-time checking, but keep the bits aligned with struct pll_dividers so
* they can be used interchangeably at run time. Add new formats as required. */
struct pllcx_dividers {
u32 n : 8;
u32 : 2;
u32 m : 8;
u32 p : 4;
u32 : 10;
};
struct pllpad_dividers {
u32 n : 10;
u32 m : 5;
u32 : 3;
u32 p : 3;
u32 : 1;
u32 cpcon : 4;
u32 : 6;
};
struct pllu_dividers {
u32 n : 10;
u32 m : 5;
u32 : 3;
u32 p : 1;
u32 : 3;
u32 cpcon : 4;
u32 lfcon : 4;
u32 : 2;
};
union __attribute__((transparent_union)) pll_fields {
u32 raw;
struct pll_dividers div;
struct pllcx_dividers cx;
struct pllpad_dividers pad;
struct pllu_dividers u;
};
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_0 0x19c
void clock_enable(const clk_rst_t *clk); void clock_enable(const clk_rst_t *clk);
void clock_disable(const clk_rst_t *clk); void clock_disable(const clk_rst_t *clk);
void clock_enable_cl_dvfs(); void clock_enable_cl_dvfs();
void clock_enable_i2c(u32 idx); void clock_enable_i2c(u32 idx);
void clock_enable_uart(u32 idx);
void config_oscillators(); void config_oscillators();
int clock_uart_use_src_div(u32 idx, u32 baud);

View File

@ -15,3 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "types.h" #include "types.h"
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
enum {
PMC_XOFS_SHIFT = 1,
PMC_XOFS_MASK = 0x3f << PMC_XOFS_SHIFT
};