1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <arch_helpers.h> 10*91f16700Schasinglulu #include <drivers/delay_timer.h> 11*91f16700Schasinglulu #include <lib/bakery_lock.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <brcm_mhu.h> 14*91f16700Schasinglulu #include <platform_def.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include "m0_ipc.h" 17*91f16700Schasinglulu 18*91f16700Schasinglulu #define PLAT_MHU_INTR_REG AP_TO_SCP_MAILBOX1 19*91f16700Schasinglulu 20*91f16700Schasinglulu /* SCP MHU secure channel registers */ 21*91f16700Schasinglulu #define SCP_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG11 22*91f16700Schasinglulu #define SCP_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG11 23*91f16700Schasinglulu #define SCP_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG11 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* CPU MHU secure channel registers */ 26*91f16700Schasinglulu #define CPU_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG10 27*91f16700Schasinglulu #define CPU_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG10 28*91f16700Schasinglulu #define CPU_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG10 29*91f16700Schasinglulu 30*91f16700Schasinglulu static DEFINE_BAKERY_LOCK(bcm_lock); 31*91f16700Schasinglulu 32*91f16700Schasinglulu /* 33*91f16700Schasinglulu * Slot 31 is reserved because the MHU hardware uses this register bit to 34*91f16700Schasinglulu * indicate a non-secure access attempt. The total number of available slots is 35*91f16700Schasinglulu * therefore 31 [30:0]. 36*91f16700Schasinglulu */ 37*91f16700Schasinglulu #define MHU_MAX_SLOT_ID 30 38*91f16700Schasinglulu 39*91f16700Schasinglulu void mhu_secure_message_start(unsigned int slot_id) 40*91f16700Schasinglulu { 41*91f16700Schasinglulu int iter = 1000000; 42*91f16700Schasinglulu 43*91f16700Schasinglulu assert(slot_id <= MHU_MAX_SLOT_ID); 44*91f16700Schasinglulu 45*91f16700Schasinglulu bakery_lock_get(&bcm_lock); 46*91f16700Schasinglulu /* Make sure any previous command has finished */ 47*91f16700Schasinglulu do { 48*91f16700Schasinglulu if (!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) & 49*91f16700Schasinglulu (1 << slot_id))) 50*91f16700Schasinglulu break; 51*91f16700Schasinglulu 52*91f16700Schasinglulu udelay(1); 53*91f16700Schasinglulu 54*91f16700Schasinglulu } while (--iter); 55*91f16700Schasinglulu 56*91f16700Schasinglulu assert(iter != 0); 57*91f16700Schasinglulu } 58*91f16700Schasinglulu 59*91f16700Schasinglulu void mhu_secure_message_send(unsigned int slot_id) 60*91f16700Schasinglulu { 61*91f16700Schasinglulu uint32_t response, iter = 1000000; 62*91f16700Schasinglulu 63*91f16700Schasinglulu assert(slot_id <= MHU_MAX_SLOT_ID); 64*91f16700Schasinglulu assert(!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) & 65*91f16700Schasinglulu (1 << slot_id))); 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* Send command to SCP */ 68*91f16700Schasinglulu mmio_setbits_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); 69*91f16700Schasinglulu mmio_write_32(CRMU_MAIL_BOX0, MCU_IPC_MCU_CMD_SCPI); 70*91f16700Schasinglulu mmio_write_32(PLAT_BRCM_MHU_BASE + PLAT_MHU_INTR_REG, 0x1); 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Wait until IPC transport acknowledges reception of SCP command */ 73*91f16700Schasinglulu do { 74*91f16700Schasinglulu response = mmio_read_32(CRMU_MAIL_BOX0); 75*91f16700Schasinglulu if ((response & ~MCU_IPC_CMD_REPLY_MASK) == 76*91f16700Schasinglulu (MCU_IPC_CMD_DONE_MASK | MCU_IPC_MCU_CMD_SCPI)) 77*91f16700Schasinglulu break; 78*91f16700Schasinglulu 79*91f16700Schasinglulu udelay(1); 80*91f16700Schasinglulu 81*91f16700Schasinglulu } while (--iter); 82*91f16700Schasinglulu 83*91f16700Schasinglulu assert(iter != 0); 84*91f16700Schasinglulu } 85*91f16700Schasinglulu 86*91f16700Schasinglulu uint32_t mhu_secure_message_wait(void) 87*91f16700Schasinglulu { 88*91f16700Schasinglulu /* Wait for response from SCP */ 89*91f16700Schasinglulu uint32_t response, iter = 1000000; 90*91f16700Schasinglulu 91*91f16700Schasinglulu do { 92*91f16700Schasinglulu response = mmio_read_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT); 93*91f16700Schasinglulu if (!response) 94*91f16700Schasinglulu break; 95*91f16700Schasinglulu 96*91f16700Schasinglulu udelay(1); 97*91f16700Schasinglulu } while (--iter); 98*91f16700Schasinglulu assert(iter != 0); 99*91f16700Schasinglulu 100*91f16700Schasinglulu return response; 101*91f16700Schasinglulu } 102*91f16700Schasinglulu 103*91f16700Schasinglulu void mhu_secure_message_end(unsigned int slot_id) 104*91f16700Schasinglulu { 105*91f16700Schasinglulu assert(slot_id <= MHU_MAX_SLOT_ID); 106*91f16700Schasinglulu 107*91f16700Schasinglulu /* 108*91f16700Schasinglulu * Clear any response we got by writing one in the relevant slot bit to 109*91f16700Schasinglulu * the CLEAR register 110*91f16700Schasinglulu */ 111*91f16700Schasinglulu mmio_clrbits_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); 112*91f16700Schasinglulu bakery_lock_release(&bcm_lock); 113*91f16700Schasinglulu } 114*91f16700Schasinglulu 115*91f16700Schasinglulu void mhu_secure_init(void) 116*91f16700Schasinglulu { 117*91f16700Schasinglulu bakery_lock_init(&bcm_lock); 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* 120*91f16700Schasinglulu * The STAT register resets to zero. Ensure it is in the expected state, 121*91f16700Schasinglulu * as a stale or garbage value would make us think it's a message we've 122*91f16700Schasinglulu * already sent. 123*91f16700Schasinglulu */ 124*91f16700Schasinglulu mmio_write_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT, 0); 125*91f16700Schasinglulu mmio_write_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT, 0); 126*91f16700Schasinglulu } 127*91f16700Schasinglulu 128*91f16700Schasinglulu void plat_brcm_pwrc_setup(void) 129*91f16700Schasinglulu { 130*91f16700Schasinglulu mhu_secure_init(); 131*91f16700Schasinglulu } 132