soc/mediatek/mt8196: Add MMinfra driver support

MMinfra is the Multimedia Infrastructure. All the Multimedia modules
depend on it. This file adds some initial settings for MMinfra.

Test=Build pass
BUG=b:317009620

Signed-off-by: Xueqi Zhang <xueqi.zhang@mediatek.corp-partner.google.com>
Change-Id: Ie86f141a0957fc60d4973875c0dbcbdb57be1f75
Reviewed-on: https://review.coreboot.org/c/coreboot/+/85188
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yidi Lin <yidilin@google.com>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
Xueqi Zhang 2024-03-22 11:06:53 +08:00 committed by Yidi Lin
commit 78560f9958
5 changed files with 160 additions and 1 deletions

View file

@ -15,6 +15,7 @@ bootblock-y += bootblock.c
bootblock-y += ../common/bootblock.c bootblock.c
bootblock-y += ../common/early_init.c
bootblock-y += ../common/lastbus_v2.c lastbus.c
bootblock-y += mminfra.c
bootblock-y += ../common/mmu_operations.c
bootblock-y += mtcmos.c
bootblock-$(CONFIG_PCI) += ../common/pcie.c pcie.c

View file

@ -4,6 +4,7 @@
#include <bootblock_common.h>
#include <soc/early_init.h>
#include <soc/lastbus_v2.h>
#include <soc/mminfra.h>
#include <soc/mmu_operations.h>
#include <soc/pll.h>
#include <soc/spm_mtcmos.h>
@ -17,6 +18,7 @@ void bootblock_soc_init(void)
mtk_wdt_init();
mt_pll_init();
mtcmos_init();
mminfra_post_init();
mt_pll_post_init();
mtcmos_post_init();
early_init_clear();

View file

@ -142,6 +142,7 @@ enum {
SSR_TOP_BASE = IO_PHYS + 0x08000000,
APINFRA_SSR_AO_DEBUG_BASE = IO_PHYS + 0x080F1000,
AUDIO_BASE = IO_PHYS + 0x0A110000,
VLP_AO_BASE = IO_PHYS + 0x0C000000,
VLPCFG_BASE = IO_PHYS + 0x0C001000,
SPM_BASE = IO_PHYS + 0x0C004000,
SPM_PBUS_BASE = IO_PHYS + 0x0C00D000,
@ -171,7 +172,13 @@ enum {
MMVOTE_CAM_MAIN_R1A_BASE = IO_PHYS + 0x1A000000,
MMVOTE_CCU_MAIN_BASE = IO_PHYS + 0x1C800000,
MMVOTE_DISP_VDISP_AO_CONFIG_BASE = IO_PHYS + 0x1E800000,
MMUP_AO_DEBUG_BASE = IO_PHYS + 0x21A22000,
MMINFRA_CONFIG = IO_PHYS + 0x20000000,
MMINFRA_SEC_CONFIG = IO_PHYS + 0x20010000,
MMINFRA_AO_CONFIG = IO_PHYS + 0x20080000,
MMINFRA_BUS_HRE_BASE = IO_PHYS + 0x200A0000,
MMINFRA_BUS_HRE2_BASE = IO_PHYS + 0x200B0000,
MMINFRA1_CONFIG = IO_PHYS + 0x20A00000,
MMUP_AO_DEBUG_BASE = IO_PHYS + 0x21A22000,
MMVOTE_BASE = IO_PHYS + 0x21B00000,
MMPC_BASE = IO_PHYS + 0x21B50000,
MMSYS_CONFIG_BASE = IO_PHYS + 0x22000000,

View file

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MMINFRA_H__
#define __SOC_MEDIATEK_MMINFRA_H__
/* mminfra_ao */
#define MMINFRA_GCE_PROT_EN (MMINFRA_AO_CONFIG + 0x428)
/* mminfra0 */
#define MMINFRA_MM0_GALS_PROT_RX_EN (MMINFRA_CONFIG + 0x9C0)
#define MMINFRA_MM0_GALS_PROT_RX_RDY (MMINFRA_CONFIG + 0x9C4)
#define MMINFRA_MM0_GALS_PROT_TX_EN (MMINFRA_CONFIG + 0x9C8)
#define MMINFRA_MM0_GALS_PROT_TX_RDY (MMINFRA_CONFIG + 0x9CC)
#define MMINFRA_MM1_GALS_PROT_RX_EN (MMINFRA_CONFIG + 0x9D0)
#define MMINFRA_MM1_GALS_PROT_RX_RDY (MMINFRA_CONFIG + 0x9D4)
#define MMINFRA_MM1_GALS_PROT_TX_EN (MMINFRA_CONFIG + 0x9D8)
#define MMINFRA_MM1_GALS_PROT_TX_RDY (MMINFRA_CONFIG + 0x9DC)
#define GCE_D_SLEEPPORT_RX_EN BIT(0)
#define GCE_D_HAND_SLEEPPORT_RX_EN BIT(1)
#define GCE_D_HAND_SLEEPPORT_TX_EN BIT(2)
#define GCE_M_SLEEPPORT_RX_EN BIT(8)
#define GCE_M_HAND_SLEEPPORT_RX_EN BIT(9)
#define GCE_M_HAND_SLEEPPORT_TX_EN BIT(10)
#define VLP_AO_RSVD6 (VLP_AO_BASE + 0x918)
/* mmpc */
#define MMPC_PM_BOOT_UP_PWR_CON (MMPC_BASE + 0x1B8)
#define MM_INFRA0_PM_BOOT_UP BIT(16)
#define MM_INFRA1_PM_BOOT_UP BIT(17)
void mminfra_post_init(void);
#endif

View file

@ -0,0 +1,114 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
#include <device/mmio.h>
#include <soc/addressmap.h>
#include <soc/mminfra.h>
#include <soc/spm_mtcmos.h>
#include <stddef.h>
#include <string.h>
#include <timer.h>
#include <types.h>
#define TIMEOUT_US 20
static void wait_for_write_done(u32 write_reg, u32 status_reg, u32 val)
{
write32p(write_reg, val);
if (!wait_us(TIMEOUT_US, read32p(status_reg) == val))
die("Wait write done timeout\n");
}
static void mm_gce_lock_prot_en(void)
{
setbits32p(MMINFRA_GCE_PROT_EN,
GCE_D_SLEEPPORT_RX_EN | GCE_D_HAND_SLEEPPORT_RX_EN |
GCE_D_HAND_SLEEPPORT_TX_EN | GCE_M_SLEEPPORT_RX_EN |
GCE_M_HAND_SLEEPPORT_RX_EN | GCE_M_HAND_SLEEPPORT_TX_EN);
}
static void mm_gce_release_prot_en(void)
{
write32p(MMINFRA_GCE_PROT_EN, 0);
}
static void mm_infra0_lock_prot_en(void)
{
wait_for_write_done(MMINFRA_MM0_GALS_PROT_TX_EN,
MMINFRA_MM0_GALS_PROT_TX_RDY, 0xff);
wait_for_write_done(MMINFRA_MM0_GALS_PROT_RX_EN,
MMINFRA_MM0_GALS_PROT_RX_RDY, 0xfffff);
}
static void mm_infra0_release_prot_en(void)
{
write32p(MMINFRA_MM0_GALS_PROT_RX_EN, 0);
write32p(MMINFRA_MM0_GALS_PROT_TX_EN, 0);
}
static void mm_infra1_lock_prot_en(void)
{
mm_gce_lock_prot_en();
wait_for_write_done(MMINFRA_MM1_GALS_PROT_TX_EN,
MMINFRA_MM1_GALS_PROT_TX_RDY, 0x3f);
wait_for_write_done(MMINFRA_MM1_GALS_PROT_RX_EN,
MMINFRA_MM1_GALS_PROT_RX_RDY, 0xf);
}
static void mm_infra1_release_prot_en(void)
{
write32p(MMINFRA_MM1_GALS_PROT_RX_EN, 0);
write32p(MMINFRA_MM1_GALS_PROT_TX_EN, 0);
mm_gce_release_prot_en();
}
static int pd_mm_infra0_pre_on(void)
{
setbits32p(MMPC_PM_BOOT_UP_PWR_CON, MM_INFRA0_PM_BOOT_UP | MM_INFRA1_PM_BOOT_UP);
return 0;
}
static int pd_mm_infra0_post_on(void)
{
mm_infra0_release_prot_en();
return 0;
}
static int pd_mm_infra0_pre_off(void)
{
mm_infra0_lock_prot_en();
return 0;
}
static int pd_mm_infra1_post_on(void)
{
mm_infra1_release_prot_en();
write32p(VLP_AO_RSVD6, 0x1);
return 0;
}
static int pd_mm_infra1_pre_off(void)
{
mm_infra1_lock_prot_en();
return 0;
}
static struct mtcmos_cb mm_infra0_pb_cb = {
.pre_on = pd_mm_infra0_pre_on,
.post_on = pd_mm_infra0_post_on,
.pre_off = pd_mm_infra0_pre_off,
};
static struct mtcmos_cb mm_infra1_pb_cb = {
.post_on = pd_mm_infra1_post_on,
.pre_off = pd_mm_infra1_pre_off,
};
void mminfra_post_init(void)
{
if (mtcmos_cb_register(MTCMOS_ID_MM_INFRA0, &mm_infra0_pb_cb))
return;
mtcmos_cb_register(MTCMOS_ID_MM_INFRA1, &mm_infra1_pb_cb);
}