123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- * Copyright (c) 2016-2020, Broadcom
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <stdint.h>
- #include <common/debug.h>
- #include <lib/mmio.h>
- #include <dmu.h>
- #define IHOST0_CONFIG_ROOT 0x66000000
- #define IHOST1_CONFIG_ROOT 0x66002000
- #define IHOST2_CONFIG_ROOT 0x66004000
- #define IHOST3_CONFIG_ROOT 0x66006000
- #define A72_CRM_PLL_PWR_ON 0x00000070
- #define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R 4
- #define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R 5
- #define A72_CRM_PLL_CHNL_BYPS_EN 0x000000ac
- #define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R 0
- #define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK 0x0000ec1f
- #define A72_CRM_PLL_CMD 0x00000080
- #define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R 0
- #define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R 1
- #define A72_CRM_PLL_STATUS 0x00000084
- #define A72_CRM_PLL_STATUS__PLL0_LOCK_R 9
- #define A72_CRM_PLL0_CTRL1 0x00000100
- #define A72_CRM_PLL0_CTRL2 0x00000104
- #define A72_CRM_PLL0_CTRL3 0x00000108
- #define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12
- #define A72_CRM_PLL0_CTRL4 0x0000010c
- #define A72_CRM_PLL0_CTRL4__PLL0_KP_R 0
- #define A72_CRM_PLL0_CTRL4__PLL0_KI_R 4
- #define A72_CRM_PLL0_CTRL4__PLL0_KA_R 7
- #define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R 10
- #define PLL_MODE_VCO 0x0
- #define PLL_MODE_BYPASS 0x1
- #define PLL_RESET_TYPE_PLL 0x1
- #define PLL_RESET_TYPE_POST 0x2
- #define PLL_VCO 0x1
- #define PLL_POSTDIV 0x2
- #define ARM_FREQ_3G PLL_FREQ_FULL
- #define ARM_FREQ_1P5G PLL_FREQ_HALF
- #define ARM_FREQ_750M PLL_FREQ_QRTR
- static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num)
- {
- unsigned int ihostx_config_root;
- switch (cluster_num) {
- case 0:
- default:
- ihostx_config_root = IHOST0_CONFIG_ROOT;
- break;
- case 1:
- ihostx_config_root = IHOST1_CONFIG_ROOT;
- break;
- case 2:
- ihostx_config_root = IHOST2_CONFIG_ROOT;
- break;
- case 3:
- ihostx_config_root = IHOST3_CONFIG_ROOT;
- break;
- }
- return ihostx_config_root;
- }
- static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num,
- unsigned int reset_type)
- {
- unsigned long ihostx_config_root;
- unsigned int pll_rst_ctrl;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
- // PLL reset
- if (reset_type & PLL_RESET_TYPE_PLL) {
- pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
- }
- // post-div channel reset
- if (reset_type & PLL_RESET_TYPE_POST) {
- pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
- }
- mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
- }
- static void ARMCOE_crm_pllSetMode(unsigned int cluster_num, unsigned int mode)
- {
- unsigned long ihostx_config_root;
- unsigned int pll_byp_ctrl;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- pll_byp_ctrl = mmio_read_32(ihostx_config_root +
- A72_CRM_PLL_CHNL_BYPS_EN);
- if (mode == PLL_MODE_VCO) {
- // use PLL DCO output
- pll_byp_ctrl &=
- ~BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
- } else {
- // use PLL bypass sources
- pll_byp_ctrl |=
- BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
- }
- mmio_write_32(ihostx_config_root + A72_CRM_PLL_CHNL_BYPS_EN,
- pll_byp_ctrl);
- }
- static void ARMCOE_crm_pllFreqSet(unsigned int cluster_num,
- unsigned int ihost_pll_freq_sel,
- unsigned int pdiv)
- {
- unsigned int ndiv_int;
- unsigned int ndiv_frac_low, ndiv_frac_high;
- unsigned long ihostx_config_root;
- ndiv_frac_low = 0x0;
- ndiv_frac_high = 0x0;
- if (ihost_pll_freq_sel == ARM_FREQ_3G) {
- ndiv_int = 0x78;
- } else if (ihost_pll_freq_sel == ARM_FREQ_1P5G) {
- ndiv_int = 0x3c;
- } else if (ihost_pll_freq_sel == ARM_FREQ_750M) {
- ndiv_int = 0x1e;
- } else {
- return;
- }
- ndiv_int &= 0x3FF; // low 10 bits
- ndiv_frac_low &= 0x3FF;
- ndiv_frac_high &= 0x3FF;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL1, ndiv_frac_low);
- mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL2, ndiv_frac_high);
- mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL3,
- ndiv_int |
- ((pdiv << A72_CRM_PLL0_CTRL3__PLL0_PDIV_R & 0xF000)));
- mmio_write_32(ihostx_config_root + A72_CRM_PLL0_CTRL4,
- /* From Section 10 of PLL spec */
- (3 << A72_CRM_PLL0_CTRL4__PLL0_KP_R) |
- /* From Section 10 of PLL spec */
- (2 << A72_CRM_PLL0_CTRL4__PLL0_KI_R) |
- /* Normal mode (i.e. not fast-locking) */
- (0 << A72_CRM_PLL0_CTRL4__PLL0_KA_R) |
- /* 50 MHz */
- (50 << A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R));
- }
- static void ARMCOE_crm_pllDeassertReset(unsigned int cluster_num,
- unsigned int reset_type)
- {
- unsigned long ihostx_config_root;
- unsigned int pll_rst_ctrl;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
- // PLL reset
- if (reset_type & PLL_RESET_TYPE_PLL) {
- pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
- }
- // post-div channel reset
- if (reset_type & PLL_RESET_TYPE_POST) {
- pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
- }
- mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
- }
- static void ARMCOE_crm_pllUpdate(unsigned int cluster_num, unsigned int type)
- {
- unsigned long ihostx_config_root;
- unsigned int pll_cmd;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- pll_cmd = mmio_read_32(ihostx_config_root + A72_CRM_PLL_CMD);
- // VCO update
- if (type & PLL_VCO) {
- pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R);
- }
- // post-div channel update
- if (type & PLL_POSTDIV) {
- pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R);
- }
- mmio_write_32(ihostx_config_root+A72_CRM_PLL_CMD, pll_cmd);
- }
- static void insert_delay(unsigned int delay)
- {
- volatile unsigned int index;
- for (index = 0; index < delay; index++)
- ;
- }
- /*
- * Returns 1 if PLL locked within certain interval
- */
- static unsigned int ARMCOE_crm_pllIsLocked(unsigned int cluster_num)
- {
- unsigned long ihostx_config_root;
- unsigned int lock_status;
- unsigned int i;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- /* wait a while for pll to lock before returning from this function */
- for (i = 0; i < 1500; i++) {
- insert_delay(256);
- lock_status = mmio_read_32(ihostx_config_root +
- A72_CRM_PLL_STATUS);
- if (lock_status & BIT(A72_CRM_PLL_STATUS__PLL0_LOCK_R))
- return 1;
- }
- ERROR("PLL of Cluster #%u failed to lock\n", cluster_num);
- return 0;
- }
- /*
- * ihost PLL Variable Frequency Configuration
- *
- * Frequency Limit {VCO,ARM} (GHz):
- * 0 - no limit,
- * 1 - {3.0,1.5},
- * 2 - {4.0,2.0},
- * 3 - {5.0,2.5}
- */
- uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel)
- {
- NOTICE("cluster: %u, freq_sel:0x%x\n", cluster_num, ihost_pll_freq_sel);
- //bypass PLL
- ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_BYPASS);
- //assert reset
- ARMCOE_crm_pllAssertReset(cluster_num,
- PLL_RESET_TYPE_PLL | PLL_RESET_TYPE_POST);
- //set ndiv_int for different freq
- ARMCOE_crm_pllFreqSet(cluster_num, ihost_pll_freq_sel, 0x1);
- //de-assert reset
- ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_PLL);
- ARMCOE_crm_pllUpdate(cluster_num, PLL_VCO);
- //waiting for PLL lock
- ARMCOE_crm_pllIsLocked(cluster_num);
- ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_POST);
- //disable bypass PLL
- ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_VCO);
- return 0;
- }
- uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num)
- {
- unsigned long ihostx_config_root;
- uint32_t ndiv_int;
- uint32_t ihost_pll_freq_sel;
- ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
- ndiv_int = mmio_read_32(ihostx_config_root+A72_CRM_PLL0_CTRL3) & 0x3FF;
- if (ndiv_int == 0x78) {
- ihost_pll_freq_sel = ARM_FREQ_3G;
- } else if (ndiv_int == 0x3c) {
- ihost_pll_freq_sel = ARM_FREQ_1P5G;
- } else if (ndiv_int == 0x1e) {
- ihost_pll_freq_sel = ARM_FREQ_750M;
- } else {
- /* return unlimit otherwise*/
- ihost_pll_freq_sel = 0;
- }
- return ihost_pll_freq_sel;
- }
|