2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-02-22 20:20:49 +03:00
/*
* Copyright ( c ) 2015 - 2016 MediaTek Inc .
* Author : Yong Wu < yong . wu @ mediatek . com >
*/
2022-08-17 15:46:07 +03:00
# include <linux/arm-smccc.h>
2016-02-22 20:20:49 +03:00
# include <linux/clk.h>
# include <linux/component.h>
# include <linux/device.h>
# include <linux/err.h>
# include <linux/io.h>
2022-01-13 14:10:56 +03:00
# include <linux/iopoll.h>
2017-08-21 14:00:21 +03:00
# include <linux/module.h>
2016-02-22 20:20:49 +03:00
# include <linux/of.h>
# include <linux/of_platform.h>
# include <linux/platform_device.h>
# include <linux/pm_runtime.h>
2022-08-17 15:46:07 +03:00
# include <linux/soc/mediatek/mtk_sip_svc.h>
2016-02-22 20:20:49 +03:00
# include <soc/mediatek/smi.h>
2016-06-08 12:50:59 +03:00
# include <dt-bindings/memory/mt2701-larb-port.h>
2021-01-11 14:18:49 +03:00
# include <dt-bindings/memory/mtk-memory-port.h>
2016-02-22 20:20:49 +03:00
2021-09-14 14:36:55 +03:00
/* SMI COMMON */
2021-09-14 14:37:01 +03:00
# define SMI_L1LEN 0x100
2022-05-18 12:10:38 +03:00
# define SMI_L1_ARB 0x200
2021-09-14 14:36:55 +03:00
# define SMI_BUS_SEL 0x220
# define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
/* All are MMU0 defaultly. Only specialize mmu1 here. */
# define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
2017-08-21 14:00:16 +03:00
2022-05-18 12:10:38 +03:00
# define SMI_READ_FIFO_TH 0x230
2021-09-14 14:37:01 +03:00
# define SMI_M4U_TH 0x234
# define SMI_FIFO_TH1 0x238
# define SMI_FIFO_TH2 0x23c
# define SMI_DCM 0x300
# define SMI_DUMMY 0x444
2021-09-14 14:36:55 +03:00
/* SMI LARB */
2022-01-13 14:10:56 +03:00
# define SMI_LARB_SLP_CON 0xc
# define SLP_PROT_EN BIT(0)
# define SLP_PROT_RDY BIT(16)
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
# define SMI_LARB_CMD_THRT_CON 0x24
# define SMI_LARB_THRT_RD_NU_LMT_MSK GENMASK(7, 4)
# define SMI_LARB_THRT_RD_NU_LMT (5 << 4)
# define SMI_LARB_SW_FLAG 0x40
# define SMI_LARB_SW_FLAG_1 0x1
# define SMI_LARB_OSTDL_PORT 0x200
# define SMI_LARB_OSTDL_PORTx(id) (SMI_LARB_OSTDL_PORT + (((id) & 0x1f) << 2))
2020-09-06 21:09:38 +03:00
2021-09-14 14:36:55 +03:00
/* Below are about mmu enable registers, they are different in SoCs */
/* gen1: mt2701 */
2016-06-08 12:50:59 +03:00
# define REG_SMI_SECUR_CON_BASE 0x5c0
/* every register control 8 port, register offset 0x4 */
# define REG_SMI_SECUR_CON_OFFSET(id) (((id) >> 3) << 2)
# define REG_SMI_SECUR_CON_ADDR(id) \
( REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET ( id ) )
/*
* every port have 4 bit to control , bit [ port + 3 ] control virtual or physical ,
* bit [ port + 2 : port + 1 ] control the domain , bit [ port ] control the security
* or non - security .
*/
# define SMI_SECUR_CON_VAL_MSK(id) (~(0xf << (((id) & 0x7) << 2)))
# define SMI_SECUR_CON_VAL_VIRT(id) BIT((((id) & 0x7) << 2) + 3)
/* mt2701 domain should be set to 3 */
# define SMI_SECUR_CON_VAL_DOMAIN(id) (0x3 << ((((id) & 0x7) << 2) + 1))
2021-09-14 14:36:55 +03:00
/* gen2: */
/* mt8167 */
# define MT8167_SMI_LARB_MMU_EN 0xfc0
/* mt8173 */
# define MT8173_SMI_LARB_MMU_EN 0xf00
/* general */
# define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
# define F_MMU_EN BIT(0)
# define BANK_SEL(id) ({ \
2021-01-11 14:19:11 +03:00
u32 _id = ( id ) & 0x3 ; \
( _id < < 8 | _id < < 10 | _id < < 12 | _id < < 14 ) ; \
} )
2017-08-21 14:00:16 +03:00
2021-09-14 14:37:01 +03:00
# define SMI_COMMON_INIT_REGS_NR 6
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
# define SMI_LARB_PORT_NR_MAX 32
# define MTK_SMI_FLAG_THRT_UPDATE BIT(0)
# define MTK_SMI_FLAG_SW_FLAG BIT(1)
2022-01-13 14:10:56 +03:00
# define MTK_SMI_FLAG_SLEEP_CTL BIT(2)
2022-08-17 15:46:07 +03:00
# define MTK_SMI_FLAG_CFG_PORT_SEC_CTL BIT(3)
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
# define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x)))
2021-09-14 14:37:01 +03:00
struct mtk_smi_reg_pair {
unsigned int offset ;
u32 value ;
} ;
2021-09-14 14:36:54 +03:00
enum mtk_smi_type {
2019-08-24 06:01:49 +03:00
MTK_SMI_GEN1 ,
2021-09-14 14:36:57 +03:00
MTK_SMI_GEN2 , /* gen2 smi common */
MTK_SMI_GEN2_SUB_COMM , /* gen2 smi sub common */
2019-08-24 06:01:49 +03:00
} ;
2021-09-14 14:36:53 +03:00
/* larbs: Require apb/smi clocks while gals is optional. */
static const char * const mtk_smi_larb_clks [ ] = { " apb " , " smi " , " gals " } ;
# define MTK_SMI_LARB_REQ_CLK_NR 2
# define MTK_SMI_LARB_OPT_CLK_NR 1
/*
* common : Require these four clocks in has_gals case . Otherwise , only apb / smi are required .
2021-09-14 14:36:58 +03:00
* sub common : Require apb / smi / gals0 clocks in has_gals case . Otherwise , only apb / smi are required .
2021-09-14 14:36:53 +03:00
*/
static const char * const mtk_smi_common_clks [ ] = { " apb " , " smi " , " gals0 " , " gals1 " } ;
2021-10-15 18:15:57 +03:00
# define MTK_SMI_CLK_NR_MAX ARRAY_SIZE(mtk_smi_common_clks)
2021-09-14 14:36:53 +03:00
# define MTK_SMI_COM_REQ_CLK_NR 2
# define MTK_SMI_COM_GALS_REQ_CLK_NR MTK_SMI_CLK_NR_MAX
2021-09-14 14:36:58 +03:00
# define MTK_SMI_SUB_COM_GALS_REQ_CLK_NR 3
2021-09-14 14:36:53 +03:00
2019-08-24 06:01:49 +03:00
struct mtk_smi_common_plat {
2021-09-14 14:36:54 +03:00
enum mtk_smi_type type ;
bool has_gals ;
u32 bus_sel ; /* Balance some larbs to enter mmu0 or mmu1 */
2021-09-14 14:37:01 +03:00
const struct mtk_smi_reg_pair * init ;
2019-08-24 06:01:49 +03:00
} ;
2016-06-08 12:50:59 +03:00
struct mtk_smi_larb_gen {
int port_in_larb [ MTK_LARB_NR_MAX + 1 ] ;
2022-08-17 15:46:06 +03:00
int ( * config_port ) ( struct device * dev ) ;
2019-08-24 06:01:48 +03:00
unsigned int larb_direct_to_common_mask ;
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
unsigned int flags_general ;
const u8 ( * ostd ) [ SMI_LARB_PORT_NR_MAX ] ;
2016-06-08 12:50:59 +03:00
} ;
2016-02-22 20:20:49 +03:00
struct mtk_smi {
2016-06-08 12:50:59 +03:00
struct device * dev ;
2021-09-14 14:36:53 +03:00
unsigned int clk_num ;
struct clk_bulk_data clks [ MTK_SMI_CLK_NR_MAX ] ;
2016-06-08 12:50:59 +03:00
struct clk * clk_async ; /*only needed by mt2701*/
2019-08-24 06:02:05 +03:00
union {
void __iomem * smi_ao_base ; /* only for gen1 */
void __iomem * base ; /* only for gen2 */
} ;
2021-09-14 14:36:57 +03:00
struct device * smi_common_dev ; /* for sub common */
2019-08-24 06:01:49 +03:00
const struct mtk_smi_common_plat * plat ;
2016-02-22 20:20:49 +03:00
} ;
struct mtk_smi_larb { /* larb: local arbiter */
2016-06-08 12:50:59 +03:00
struct mtk_smi smi ;
void __iomem * base ;
2021-09-14 14:36:57 +03:00
struct device * smi_common_dev ; /* common or sub-common dev */
2016-06-08 12:50:59 +03:00
const struct mtk_smi_larb_gen * larb_gen ;
int larbid ;
u32 * mmu ;
2021-01-11 14:19:11 +03:00
unsigned char * bank ;
2016-06-08 12:50:59 +03:00
} ;
2016-02-22 20:20:49 +03:00
static int
mtk_smi_larb_bind ( struct device * dev , struct device * master , void * data )
{
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
2019-08-24 06:02:08 +03:00
struct mtk_smi_larb_iommu * larb_mmu = data ;
2016-02-22 20:20:49 +03:00
unsigned int i ;
2019-08-24 06:02:07 +03:00
for ( i = 0 ; i < MTK_LARB_NR_MAX ; i + + ) {
2019-08-24 06:02:08 +03:00
if ( dev = = larb_mmu [ i ] . dev ) {
2019-08-24 06:02:07 +03:00
larb - > larbid = i ;
2019-08-24 06:02:08 +03:00
larb - > mmu = & larb_mmu [ i ] . mmu ;
2021-01-11 14:19:11 +03:00
larb - > bank = larb_mmu [ i ] . bank ;
2016-02-22 20:20:49 +03:00
return 0 ;
}
}
return - ENODEV ;
}
2021-09-14 14:36:55 +03:00
static void
mtk_smi_larb_unbind ( struct device * dev , struct device * master , void * data )
2017-08-21 14:00:16 +03:00
{
2021-09-14 14:36:55 +03:00
/* Do nothing as the iommu is always enabled. */
2017-08-21 14:00:16 +03:00
}
2016-06-08 12:50:59 +03:00
2021-09-14 14:36:55 +03:00
static const struct component_ops mtk_smi_larb_component_ops = {
. bind = mtk_smi_larb_bind ,
. unbind = mtk_smi_larb_unbind ,
} ;
2020-09-06 21:09:38 +03:00
2022-08-17 15:46:06 +03:00
static int mtk_smi_larb_config_port_gen1 ( struct device * dev )
2016-06-08 12:50:59 +03:00
{
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
const struct mtk_smi_larb_gen * larb_gen = larb - > larb_gen ;
struct mtk_smi * common = dev_get_drvdata ( larb - > smi_common_dev ) ;
int i , m4u_port_id , larb_port_num ;
u32 sec_con_val , reg_val ;
m4u_port_id = larb_gen - > port_in_larb [ larb - > larbid ] ;
larb_port_num = larb_gen - > port_in_larb [ larb - > larbid + 1 ]
- larb_gen - > port_in_larb [ larb - > larbid ] ;
for ( i = 0 ; i < larb_port_num ; i + + , m4u_port_id + + ) {
if ( * larb - > mmu & BIT ( i ) ) {
/* bit[port + 3] controls the virtual or physical */
sec_con_val = SMI_SECUR_CON_VAL_VIRT ( m4u_port_id ) ;
} else {
/* do not need to enable m4u for this port */
continue ;
}
reg_val = readl ( common - > smi_ao_base
+ REG_SMI_SECUR_CON_ADDR ( m4u_port_id ) ) ;
reg_val & = SMI_SECUR_CON_VAL_MSK ( m4u_port_id ) ;
reg_val | = sec_con_val ;
reg_val | = SMI_SECUR_CON_VAL_DOMAIN ( m4u_port_id ) ;
writel ( reg_val ,
common - > smi_ao_base
+ REG_SMI_SECUR_CON_ADDR ( m4u_port_id ) ) ;
}
2022-08-17 15:46:06 +03:00
return 0 ;
2016-06-08 12:50:59 +03:00
}
2022-08-17 15:46:06 +03:00
static int mtk_smi_larb_config_port_mt8167 ( struct device * dev )
2016-02-22 20:20:49 +03:00
{
2021-09-14 14:36:55 +03:00
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
writel ( * larb - > mmu , larb - > base + MT8167_SMI_LARB_MMU_EN ) ;
2022-08-17 15:46:06 +03:00
return 0 ;
2016-02-22 20:20:49 +03:00
}
2022-08-17 15:46:06 +03:00
static int mtk_smi_larb_config_port_mt8173 ( struct device * dev )
2021-09-14 14:36:55 +03:00
{
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
2016-02-22 20:20:49 +03:00
2021-09-14 14:36:55 +03:00
writel ( * larb - > mmu , larb - > base + MT8173_SMI_LARB_MMU_EN ) ;
2022-08-17 15:46:06 +03:00
return 0 ;
2021-09-14 14:36:55 +03:00
}
2016-06-08 12:50:59 +03:00
2022-08-17 15:46:06 +03:00
static int mtk_smi_larb_config_port_gen2_general ( struct device * dev )
2021-09-14 14:36:55 +03:00
{
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
u32 reg , flags_general = larb - > larb_gen - > flags_general ;
2021-11-24 11:50:42 +03:00
const u8 * larbostd = larb - > larb_gen - > ostd ? larb - > larb_gen - > ostd [ larb - > larbid ] : NULL ;
2022-08-17 15:46:07 +03:00
struct arm_smccc_res res ;
2021-09-14 14:36:55 +03:00
int i ;
if ( BIT ( larb - > larbid ) & larb - > larb_gen - > larb_direct_to_common_mask )
2022-08-17 15:46:06 +03:00
return 0 ;
2021-09-14 14:36:55 +03:00
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
if ( MTK_SMI_CAPS ( flags_general , MTK_SMI_FLAG_THRT_UPDATE ) ) {
reg = readl_relaxed ( larb - > base + SMI_LARB_CMD_THRT_CON ) ;
reg & = ~ SMI_LARB_THRT_RD_NU_LMT_MSK ;
reg | = SMI_LARB_THRT_RD_NU_LMT ;
writel_relaxed ( reg , larb - > base + SMI_LARB_CMD_THRT_CON ) ;
}
if ( MTK_SMI_CAPS ( flags_general , MTK_SMI_FLAG_SW_FLAG ) )
writel_relaxed ( SMI_LARB_SW_FLAG_1 , larb - > base + SMI_LARB_SW_FLAG ) ;
for ( i = 0 ; i < SMI_LARB_PORT_NR_MAX & & larbostd & & ! ! larbostd [ i ] ; i + + )
writel_relaxed ( larbostd [ i ] , larb - > base + SMI_LARB_OSTDL_PORTx ( i ) ) ;
2022-08-17 15:46:07 +03:00
/*
* When mmu_en bits are in security world , the bank_sel still is in the
* LARB_NONSEC_CON below . And the mmu_en bits of LARB_NONSEC_CON have no
* effect in this case .
*/
if ( MTK_SMI_CAPS ( flags_general , MTK_SMI_FLAG_CFG_PORT_SEC_CTL ) ) {
arm_smccc_smc ( MTK_SIP_KERNEL_IOMMU_CONTROL , IOMMU_ATF_CMD_CONFIG_SMI_LARB ,
larb - > larbid , * larb - > mmu , 0 , 0 , 0 , 0 , & res ) ;
if ( res . a0 ! = 0 ) {
dev_err ( dev , " Enable iommu fail, ret %ld \n " , res . a0 ) ;
return - EINVAL ;
}
}
2021-09-14 14:36:55 +03:00
for_each_set_bit ( i , ( unsigned long * ) larb - > mmu , 32 ) {
reg = readl_relaxed ( larb - > base + SMI_LARB_NONSEC_CON ( i ) ) ;
reg | = F_MMU_EN ;
reg | = BANK_SEL ( larb - > bank [ i ] ) ;
writel ( reg , larb - > base + SMI_LARB_NONSEC_CON ( i ) ) ;
}
2022-08-17 15:46:06 +03:00
return 0 ;
2021-09-14 14:36:55 +03:00
}
2020-09-06 21:09:38 +03:00
2022-08-17 15:46:08 +03:00
static const u8 mtk_smi_larb_mt8188_ostd [ ] [ SMI_LARB_PORT_NR_MAX ] = {
[ 0 ] = { 0x02 , 0x18 , 0x22 , 0x22 , 0x01 , 0x02 , 0x0a , } ,
[ 1 ] = { 0x12 , 0x02 , 0x14 , 0x14 , 0x01 , 0x18 , 0x0a , } ,
[ 2 ] = { 0x12 , 0x12 , 0x12 , 0x12 , 0x0a , } ,
[ 3 ] = { 0x12 , 0x12 , 0x12 , 0x12 , 0x28 , 0x28 , 0x0a , } ,
[ 4 ] = { 0x06 , 0x01 , 0x17 , 0x06 , 0x0a , 0x07 , 0x07 , } ,
[ 5 ] = { 0x02 , 0x01 , 0x04 , 0x02 , 0x06 , 0x01 , 0x06 , 0x0a , } ,
[ 6 ] = { 0x06 , 0x01 , 0x06 , 0x0a , } ,
[ 7 ] = { 0x0c , 0x0c , 0x12 , } ,
[ 8 ] = { 0x0c , 0x01 , 0x0a , 0x05 , 0x02 , 0x03 , 0x01 , 0x01 , 0x14 , 0x14 ,
0x0a , 0x14 , 0x1e , 0x01 , 0x0c , 0x0a , 0x05 , 0x02 , 0x02 , 0x05 ,
0x03 , 0x01 , 0x1e , 0x01 , 0x05 , } ,
[ 9 ] = { 0x1e , 0x01 , 0x0a , 0x0a , 0x01 , 0x01 , 0x03 , 0x1e , 0x1e , 0x10 ,
0x07 , 0x01 , 0x0a , 0x06 , 0x03 , 0x03 , 0x0e , 0x01 , 0x04 , 0x28 , } ,
[ 10 ] = { 0x03 , 0x20 , 0x01 , 0x20 , 0x01 , 0x01 , 0x14 , 0x0a , 0x0a , 0x0c ,
0x0a , 0x05 , 0x02 , 0x03 , 0x02 , 0x14 , 0x0a , 0x0a , 0x14 , 0x14 ,
0x14 , 0x01 , 0x01 , 0x14 , 0x1e , 0x01 , 0x05 , 0x03 , 0x02 , 0x28 , } ,
[ 11 ] = { 0x03 , 0x20 , 0x01 , 0x20 , 0x01 , 0x01 , 0x14 , 0x0a , 0x0a , 0x0c ,
0x0a , 0x05 , 0x02 , 0x03 , 0x02 , 0x14 , 0x0a , 0x0a , 0x14 , 0x14 ,
0x14 , 0x01 , 0x01 , 0x14 , 0x1e , 0x01 , 0x05 , 0x03 , 0x02 , 0x28 , } ,
[ 12 ] = { 0x03 , 0x20 , 0x01 , 0x20 , 0x01 , 0x01 , 0x14 , 0x0a , 0x0a , 0x0c ,
0x0a , 0x05 , 0x02 , 0x03 , 0x02 , 0x14 , 0x0a , 0x0a , 0x14 , 0x14 ,
0x14 , 0x01 , 0x01 , 0x14 , 0x1e , 0x01 , 0x05 , 0x03 , 0x02 , 0x28 , } ,
[ 13 ] = { 0x07 , 0x02 , 0x04 , 0x02 , 0x05 , 0x05 , 0x05 , 0x05 , 0x05 , 0x05 ,
0x07 , 0x02 , 0x04 , 0x02 , 0x05 , 0x05 , } ,
[ 14 ] = { 0x02 , 0x02 , 0x0c , 0x0c , 0x0c , 0x0c , 0x01 , 0x01 , 0x02 , 0x02 ,
0x02 , 0x02 , 0x0c , 0x0c , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 ,
0x02 , 0x02 , 0x01 , 0x01 , } ,
[ 15 ] = { 0x0c , 0x0c , 0x02 , 0x02 , 0x02 , 0x02 , 0x01 , 0x01 , 0x0c , 0x0c ,
0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x01 , 0x02 ,
0x0c , 0x01 , 0x01 , } ,
[ 16 ] = { 0x28 , 0x28 , 0x03 , 0x01 , 0x01 , 0x03 , 0x14 , 0x14 , 0x0a , 0x0d ,
0x03 , 0x05 , 0x0e , 0x01 , 0x01 , 0x05 , 0x06 , 0x0d , 0x01 , } ,
[ 17 ] = { 0x28 , 0x02 , 0x02 , 0x12 , 0x02 , 0x12 , 0x10 , 0x02 , 0x02 , 0x0a ,
0x12 , 0x02 , 0x02 , 0x0a , 0x16 , 0x02 , 0x04 , } ,
[ 18 ] = { 0x28 , 0x02 , 0x02 , 0x12 , 0x02 , 0x12 , 0x10 , 0x02 , 0x02 , 0x0a ,
0x12 , 0x02 , 0x02 , 0x0a , 0x16 , 0x02 , 0x04 , } ,
[ 19 ] = { 0x1a , 0x0e , 0x0a , 0x0a , 0x0c , 0x0e , 0x10 , } ,
[ 20 ] = { 0x1a , 0x0e , 0x0a , 0x0a , 0x0c , 0x0e , 0x10 , } ,
[ 21 ] = { 0x01 , 0x04 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 , 0x04 , 0x01 ,
0x01 , 0x01 , 0x04 , 0x0a , 0x06 , 0x01 , 0x01 , 0x01 , 0x0a , 0x06 ,
0x01 , 0x01 , 0x05 , 0x03 , 0x03 , 0x04 , 0x01 , } ,
[ 22 ] = { 0x28 , 0x19 , 0x0c , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 ,
0x01 , } ,
[ 23 ] = { 0x01 , 0x01 , 0x04 , 0x01 , 0x01 , 0x01 , 0x18 , 0x01 , 0x01 , } ,
[ 24 ] = { 0x12 , 0x06 , 0x12 , 0x06 , } ,
[ 25 ] = { 0x01 } ,
} ;
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
static const u8 mtk_smi_larb_mt8195_ostd [ ] [ SMI_LARB_PORT_NR_MAX ] = {
[ 0 ] = { 0x0a , 0xc , 0x22 , 0x22 , 0x01 , 0x0a , } , /* larb0 */
[ 1 ] = { 0x0a , 0xc , 0x22 , 0x22 , 0x01 , 0x0a , } , /* larb1 */
[ 2 ] = { 0x12 , 0x12 , 0x12 , 0x12 , 0x0a , } , /* ... */
[ 3 ] = { 0x12 , 0x12 , 0x12 , 0x12 , 0x28 , 0x28 , 0x0a , } ,
[ 4 ] = { 0x06 , 0x01 , 0x17 , 0x06 , 0x0a , } ,
[ 5 ] = { 0x06 , 0x01 , 0x17 , 0x06 , 0x06 , 0x01 , 0x06 , 0x0a , } ,
[ 6 ] = { 0x06 , 0x01 , 0x06 , 0x0a , } ,
[ 7 ] = { 0x0c , 0x0c , 0x12 , } ,
[ 8 ] = { 0x0c , 0x0c , 0x12 , } ,
[ 9 ] = { 0x0a , 0x08 , 0x04 , 0x06 , 0x01 , 0x01 , 0x10 , 0x18 , 0x11 , 0x0a ,
0x08 , 0x04 , 0x11 , 0x06 , 0x02 , 0x06 , 0x01 , 0x11 , 0x11 , 0x06 , } ,
[ 10 ] = { 0x18 , 0x08 , 0x01 , 0x01 , 0x20 , 0x12 , 0x18 , 0x06 , 0x05 , 0x10 ,
0x08 , 0x08 , 0x10 , 0x08 , 0x08 , 0x18 , 0x0c , 0x09 , 0x0b , 0x0d ,
0x0d , 0x06 , 0x10 , 0x10 , } ,
[ 11 ] = { 0x0e , 0x0e , 0x0e , 0x0e , 0x0e , 0x0e , 0x01 , 0x01 , 0x01 , 0x01 , } ,
[ 12 ] = { 0x09 , 0x09 , 0x05 , 0x05 , 0x0c , 0x18 , 0x02 , 0x02 , 0x04 , 0x02 , } ,
[ 13 ] = { 0x02 , 0x02 , 0x12 , 0x12 , 0x02 , 0x02 , 0x02 , 0x02 , 0x08 , 0x01 , } ,
[ 14 ] = { 0x12 , 0x12 , 0x02 , 0x02 , 0x02 , 0x02 , 0x16 , 0x01 , 0x16 , 0x01 ,
0x01 , 0x02 , 0x02 , 0x08 , 0x02 , } ,
[ 15 ] = { } ,
[ 16 ] = { 0x28 , 0x02 , 0x02 , 0x12 , 0x02 , 0x12 , 0x10 , 0x02 , 0x02 , 0x0a ,
0x12 , 0x02 , 0x0a , 0x16 , 0x02 , 0x04 , } ,
[ 17 ] = { 0x1a , 0x0e , 0x0a , 0x0a , 0x0c , 0x0e , 0x10 , } ,
[ 18 ] = { 0x12 , 0x06 , 0x12 , 0x06 , } ,
[ 19 ] = { 0x01 , 0x04 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 , 0x04 , 0x01 ,
0x01 , 0x01 , 0x04 , 0x0a , 0x06 , 0x01 , 0x01 , 0x01 , 0x0a , 0x06 ,
0x01 , 0x01 , 0x05 , 0x03 , 0x03 , 0x04 , 0x01 , } ,
[ 20 ] = { 0x01 , 0x04 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 , 0x04 , 0x01 ,
0x01 , 0x01 , 0x04 , 0x0a , 0x06 , 0x01 , 0x01 , 0x01 , 0x0a , 0x06 ,
0x01 , 0x01 , 0x05 , 0x03 , 0x03 , 0x04 , 0x01 , } ,
[ 21 ] = { 0x28 , 0x19 , 0x0c , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 , } ,
[ 22 ] = { 0x28 , 0x19 , 0x0c , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 , } ,
[ 23 ] = { 0x18 , 0x01 , } ,
[ 24 ] = { 0x01 , 0x01 , 0x04 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 ,
0x01 , 0x01 , } ,
[ 25 ] = { 0x02 , 0x02 , 0x02 , 0x28 , 0x16 , 0x02 , 0x02 , 0x02 , 0x12 , 0x16 ,
0x02 , 0x01 , } ,
[ 26 ] = { 0x02 , 0x02 , 0x02 , 0x28 , 0x16 , 0x02 , 0x02 , 0x02 , 0x12 , 0x16 ,
0x02 , 0x01 , } ,
[ 27 ] = { 0x02 , 0x02 , 0x02 , 0x28 , 0x16 , 0x02 , 0x02 , 0x02 , 0x12 , 0x16 ,
0x02 , 0x01 , } ,
[ 28 ] = { 0x1a , 0x0e , 0x0a , 0x0a , 0x0c , 0x0e , 0x10 , } ,
} ;
2016-06-08 12:50:59 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
. port_in_larb = {
LARB0_PORT_OFFSET , LARB1_PORT_OFFSET ,
LARB2_PORT_OFFSET , LARB3_PORT_OFFSET
} ,
. config_port = mtk_smi_larb_config_port_gen1 ,
} ;
2017-08-21 14:00:16 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
2019-08-24 06:01:48 +03:00
. config_port = mtk_smi_larb_config_port_gen2_general ,
. larb_direct_to_common_mask = BIT ( 8 ) | BIT ( 9 ) , /* bdpsys */
2017-08-21 14:00:16 +03:00
} ;
2020-01-08 09:41:30 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt6779 = {
. config_port = mtk_smi_larb_config_port_gen2_general ,
. larb_direct_to_common_mask =
BIT ( 4 ) | BIT ( 6 ) | BIT ( 11 ) | BIT ( 12 ) | BIT ( 13 ) ,
/* DUMMY | IPU0 | IPU1 | CCU | MDLA */
} ;
2021-09-14 14:36:55 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8167 = {
/* mt8167 do not need the port in larb */
. config_port = mtk_smi_larb_config_port_mt8167 ,
} ;
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
/* mt8173 do not need the port in larb */
. config_port = mtk_smi_larb_config_port_mt8173 ,
} ;
2019-08-24 06:02:02 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
. config_port = mtk_smi_larb_config_port_gen2_general ,
. larb_direct_to_common_mask = BIT ( 2 ) | BIT ( 3 ) | BIT ( 7 ) ,
/* IPU0 | IPU1 | CCU */
} ;
2022-01-13 14:10:57 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = {
. config_port = mtk_smi_larb_config_port_gen2_general ,
. flags_general = MTK_SMI_FLAG_SLEEP_CTL ,
} ;
2022-08-17 15:46:08 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
. config_port = mtk_smi_larb_config_port_gen2_general ,
. flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL ,
. ostd = mtk_smi_larb_mt8188_ostd ,
} ;
2020-11-03 08:42:00 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
. config_port = mtk_smi_larb_config_port_gen2_general ,
} ;
2021-09-14 14:37:00 +03:00
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = {
. config_port = mtk_smi_larb_config_port_gen2_general ,
2022-02-04 15:55:43 +03:00
. flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
MTK_SMI_FLAG_SLEEP_CTL ,
memory: mtk-smi: mt8195: Add initial setting for smi-larb
To improve the performance, We add some initial setting for smi larbs.
there are two part:
1), Each port has the special ostd(outstanding) value in each larb.
2), Two general settings for each larb.
a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good.
The HW default is 4, and we expect it is 5, thus, add a flag to update
it. This is only a DE recommendatory value, not a actual issue.
The register name(THRT_CON) means: throttling control, and the field
RD_NU_LMT means: Read Non-ultra commands limit.
This change means update the Read non-ultra command from 4 to 5 here.
b. SW_FLAG: Set 1 to the FLAG register. this is only for helping
debug. We could confirm if the larb is reset from this value is 1 or 0.
In some SoC, this setting maybe changed dynamically for some special case
like 4K, and this initial setting is enough in mt8195.
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
2021-09-14 14:37:02 +03:00
. ostd = mtk_smi_larb_mt8195_ostd ,
2021-09-14 14:37:00 +03:00
} ;
2016-06-08 12:50:59 +03:00
static const struct of_device_id mtk_smi_larb_of_ids [ ] = {
2021-09-14 14:36:55 +03:00
{ . compatible = " mediatek,mt2701-smi-larb " , . data = & mtk_smi_larb_mt2701 } ,
{ . compatible = " mediatek,mt2712-smi-larb " , . data = & mtk_smi_larb_mt2712 } ,
{ . compatible = " mediatek,mt6779-smi-larb " , . data = & mtk_smi_larb_mt6779 } ,
2022-05-18 12:10:38 +03:00
{ . compatible = " mediatek,mt6795-smi-larb " , . data = & mtk_smi_larb_mt8173 } ,
2021-09-14 14:36:55 +03:00
{ . compatible = " mediatek,mt8167-smi-larb " , . data = & mtk_smi_larb_mt8167 } ,
{ . compatible = " mediatek,mt8173-smi-larb " , . data = & mtk_smi_larb_mt8173 } ,
{ . compatible = " mediatek,mt8183-smi-larb " , . data = & mtk_smi_larb_mt8183 } ,
2022-01-13 14:10:57 +03:00
{ . compatible = " mediatek,mt8186-smi-larb " , . data = & mtk_smi_larb_mt8186 } ,
2022-08-17 15:46:08 +03:00
{ . compatible = " mediatek,mt8188-smi-larb " , . data = & mtk_smi_larb_mt8188 } ,
2021-09-14 14:36:55 +03:00
{ . compatible = " mediatek,mt8192-smi-larb " , . data = & mtk_smi_larb_mt8192 } ,
2021-09-14 14:37:00 +03:00
{ . compatible = " mediatek,mt8195-smi-larb " , . data = & mtk_smi_larb_mt8195 } ,
2016-06-08 12:50:59 +03:00
{ }
} ;
2022-01-13 14:10:56 +03:00
static int mtk_smi_larb_sleep_ctrl_enable ( struct mtk_smi_larb * larb )
{
int ret ;
u32 tmp ;
writel_relaxed ( SLP_PROT_EN , larb - > base + SMI_LARB_SLP_CON ) ;
ret = readl_poll_timeout_atomic ( larb - > base + SMI_LARB_SLP_CON ,
tmp , ! ! ( tmp & SLP_PROT_RDY ) , 10 , 1000 ) ;
if ( ret ) {
/* TODO: Reset this larb if it fails here. */
dev_err ( larb - > smi . dev , " sleep ctrl is not ready(0x%x). \n " , tmp ) ;
}
return ret ;
}
static void mtk_smi_larb_sleep_ctrl_disable ( struct mtk_smi_larb * larb )
{
writel_relaxed ( 0 , larb - > base + SMI_LARB_SLP_CON ) ;
}
2021-09-14 14:36:57 +03:00
static int mtk_smi_device_link_common ( struct device * dev , struct device * * com_dev )
{
struct platform_device * smi_com_pdev ;
struct device_node * smi_com_node ;
struct device * smi_com_dev ;
struct device_link * link ;
smi_com_node = of_parse_phandle ( dev - > of_node , " mediatek,smi " , 0 ) ;
if ( ! smi_com_node )
return - EINVAL ;
smi_com_pdev = of_find_device_by_node ( smi_com_node ) ;
of_node_put ( smi_com_node ) ;
if ( smi_com_pdev ) {
/* smi common is the supplier, Make sure it is ready before */
2022-06-01 15:01:18 +03:00
if ( ! platform_get_drvdata ( smi_com_pdev ) ) {
put_device ( & smi_com_pdev - > dev ) ;
2021-09-14 14:36:57 +03:00
return - EPROBE_DEFER ;
2022-06-01 15:01:18 +03:00
}
2021-09-14 14:36:57 +03:00
smi_com_dev = & smi_com_pdev - > dev ;
link = device_link_add ( dev , smi_com_dev ,
DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS ) ;
if ( ! link ) {
dev_err ( dev , " Unable to link smi-common dev \n " ) ;
2022-06-01 15:01:18 +03:00
put_device ( & smi_com_pdev - > dev ) ;
2021-09-14 14:36:57 +03:00
return - ENODEV ;
}
* com_dev = smi_com_dev ;
} else {
dev_err ( dev , " Failed to get the smi_common device \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2021-09-14 14:36:53 +03:00
static int mtk_smi_dts_clk_init ( struct device * dev , struct mtk_smi * smi ,
const char * const clks [ ] ,
unsigned int clk_nr_required ,
unsigned int clk_nr_optional )
{
int i , ret ;
for ( i = 0 ; i < clk_nr_required ; i + + )
smi - > clks [ i ] . id = clks [ i ] ;
ret = devm_clk_bulk_get ( dev , clk_nr_required , smi - > clks ) ;
if ( ret )
return ret ;
for ( i = clk_nr_required ; i < clk_nr_required + clk_nr_optional ; i + + )
smi - > clks [ i ] . id = clks [ i ] ;
ret = devm_clk_bulk_get_optional ( dev , clk_nr_optional ,
smi - > clks + clk_nr_required ) ;
smi - > clk_num = clk_nr_required + clk_nr_optional ;
return ret ;
}
2016-02-22 20:20:49 +03:00
static int mtk_smi_larb_probe ( struct platform_device * pdev )
{
struct mtk_smi_larb * larb ;
struct device * dev = & pdev - > dev ;
2021-09-14 14:36:53 +03:00
int ret ;
2016-02-22 20:20:49 +03:00
larb = devm_kzalloc ( dev , sizeof ( * larb ) , GFP_KERNEL ) ;
if ( ! larb )
return - ENOMEM ;
2017-08-04 04:32:25 +03:00
larb - > larb_gen = of_device_get_match_data ( dev ) ;
2021-09-14 14:36:59 +03:00
larb - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2016-02-22 20:20:49 +03:00
if ( IS_ERR ( larb - > base ) )
return PTR_ERR ( larb - > base ) ;
2021-09-14 14:36:53 +03:00
ret = mtk_smi_dts_clk_init ( dev , & larb - > smi , mtk_smi_larb_clks ,
MTK_SMI_LARB_REQ_CLK_NR , MTK_SMI_LARB_OPT_CLK_NR ) ;
if ( ret )
return ret ;
2016-02-22 20:20:49 +03:00
2021-09-14 14:36:53 +03:00
larb - > smi . dev = dev ;
2016-02-22 20:20:49 +03:00
2021-09-14 14:36:57 +03:00
ret = mtk_smi_device_link_common ( dev , & larb - > smi_common_dev ) ;
if ( ret < 0 )
return ret ;
2016-02-22 20:20:49 +03:00
pm_runtime_enable ( dev ) ;
platform_set_drvdata ( pdev , larb ) ;
2021-09-14 14:36:56 +03:00
ret = component_add ( dev , & mtk_smi_larb_component_ops ) ;
if ( ret )
goto err_pm_disable ;
return 0 ;
err_pm_disable :
pm_runtime_disable ( dev ) ;
device_link_remove ( dev , larb - > smi_common_dev ) ;
return ret ;
2016-02-22 20:20:49 +03:00
}
static int mtk_smi_larb_remove ( struct platform_device * pdev )
{
2021-04-10 12:11:16 +03:00
struct mtk_smi_larb * larb = platform_get_drvdata ( pdev ) ;
device_link_remove ( & pdev - > dev , larb - > smi_common_dev ) ;
2016-02-22 20:20:49 +03:00
pm_runtime_disable ( & pdev - > dev ) ;
component_del ( & pdev - > dev , & mtk_smi_larb_component_ops ) ;
return 0 ;
}
2019-08-24 06:02:04 +03:00
static int __maybe_unused mtk_smi_larb_resume ( struct device * dev )
{
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
const struct mtk_smi_larb_gen * larb_gen = larb - > larb_gen ;
int ret ;
2021-09-14 14:36:53 +03:00
ret = clk_bulk_prepare_enable ( larb - > smi . clk_num , larb - > smi . clks ) ;
2022-01-13 14:10:55 +03:00
if ( ret )
2019-08-24 06:02:04 +03:00
return ret ;
2022-01-13 14:10:56 +03:00
if ( MTK_SMI_CAPS ( larb - > larb_gen - > flags_general , MTK_SMI_FLAG_SLEEP_CTL ) )
mtk_smi_larb_sleep_ctrl_disable ( larb ) ;
2019-08-24 06:02:04 +03:00
/* Configure the basic setting for this larb */
2022-08-17 15:46:06 +03:00
return larb_gen - > config_port ( dev ) ;
2019-08-24 06:02:04 +03:00
}
static int __maybe_unused mtk_smi_larb_suspend ( struct device * dev )
{
struct mtk_smi_larb * larb = dev_get_drvdata ( dev ) ;
2022-01-13 14:10:56 +03:00
int ret ;
if ( MTK_SMI_CAPS ( larb - > larb_gen - > flags_general , MTK_SMI_FLAG_SLEEP_CTL ) ) {
ret = mtk_smi_larb_sleep_ctrl_enable ( larb ) ;
if ( ret )
return ret ;
}
2019-08-24 06:02:04 +03:00
2021-09-14 14:36:53 +03:00
clk_bulk_disable_unprepare ( larb - > smi . clk_num , larb - > smi . clks ) ;
2019-08-24 06:02:04 +03:00
return 0 ;
}
static const struct dev_pm_ops smi_larb_pm_ops = {
SET_RUNTIME_PM_OPS ( mtk_smi_larb_suspend , mtk_smi_larb_resume , NULL )
2019-10-09 14:59:33 +03:00
SET_LATE_SYSTEM_SLEEP_PM_OPS ( pm_runtime_force_suspend ,
pm_runtime_force_resume )
2019-08-24 06:02:04 +03:00
} ;
2016-02-22 20:20:49 +03:00
static struct platform_driver mtk_smi_larb_driver = {
. probe = mtk_smi_larb_probe ,
2016-06-08 12:50:59 +03:00
. remove = mtk_smi_larb_remove ,
2016-02-22 20:20:49 +03:00
. driver = {
. name = " mtk-smi-larb " ,
. of_match_table = mtk_smi_larb_of_ids ,
2019-08-24 06:02:04 +03:00
. pm = & smi_larb_pm_ops ,
2016-02-22 20:20:49 +03:00
}
} ;
2022-05-18 12:10:38 +03:00
static const struct mtk_smi_reg_pair mtk_smi_common_mt6795_init [ SMI_COMMON_INIT_REGS_NR ] = {
{ SMI_L1_ARB , 0x1b } ,
{ SMI_M4U_TH , 0xce810c85 } ,
{ SMI_FIFO_TH1 , 0x43214c8 } ,
{ SMI_READ_FIFO_TH , 0x191f } ,
} ;
2021-09-14 14:37:01 +03:00
static const struct mtk_smi_reg_pair mtk_smi_common_mt8195_init [ SMI_COMMON_INIT_REGS_NR ] = {
{ SMI_L1LEN , 0xb } ,
{ SMI_M4U_TH , 0xe100e10 } ,
{ SMI_FIFO_TH1 , 0x506090a } ,
{ SMI_FIFO_TH2 , 0x506090a } ,
{ SMI_DCM , 0x4f1 } ,
{ SMI_DUMMY , 0x1 } ,
} ;
2019-08-24 06:01:49 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_gen1 = {
2021-09-14 14:36:54 +03:00
. type = MTK_SMI_GEN1 ,
2019-08-24 06:01:49 +03:00
} ;
static const struct mtk_smi_common_plat mtk_smi_common_gen2 = {
2021-09-14 14:36:54 +03:00
. type = MTK_SMI_GEN2 ,
2019-08-24 06:01:49 +03:00
} ;
2020-01-08 09:41:30 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt6779 = {
2021-09-14 14:36:54 +03:00
. type = MTK_SMI_GEN2 ,
. has_gals = true ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 2 ) | F_MMU1_LARB ( 4 ) |
F_MMU1_LARB ( 5 ) | F_MMU1_LARB ( 6 ) | F_MMU1_LARB ( 7 ) ,
2020-01-08 09:41:30 +03:00
} ;
2022-05-18 12:10:38 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt6795 = {
. type = MTK_SMI_GEN2 ,
. bus_sel = F_MMU1_LARB ( 0 ) ,
. init = mtk_smi_common_mt6795_init ,
} ;
2019-08-24 06:02:02 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
2021-09-14 14:36:54 +03:00
. type = MTK_SMI_GEN2 ,
2019-08-24 06:02:02 +03:00
. has_gals = true ,
2019-08-24 06:02:05 +03:00
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 2 ) | F_MMU1_LARB ( 5 ) |
F_MMU1_LARB ( 7 ) ,
2019-08-24 06:02:02 +03:00
} ;
2022-01-13 14:10:57 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt8186 = {
. type = MTK_SMI_GEN2 ,
. has_gals = true ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 4 ) | F_MMU1_LARB ( 7 ) ,
} ;
2022-08-17 15:46:08 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vdo = {
. type = MTK_SMI_GEN2 ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 5 ) | F_MMU1_LARB ( 7 ) ,
. init = mtk_smi_common_mt8195_init ,
} ;
static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
. type = MTK_SMI_GEN2 ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 2 ) | F_MMU1_LARB ( 7 ) ,
. init = mtk_smi_common_mt8195_init ,
} ;
2020-11-03 08:42:00 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
2021-09-14 14:36:54 +03:00
. type = MTK_SMI_GEN2 ,
2020-11-03 08:42:00 +03:00
. has_gals = true ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 2 ) | F_MMU1_LARB ( 5 ) |
F_MMU1_LARB ( 6 ) ,
} ;
2021-09-14 14:37:00 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt8195_vdo = {
. type = MTK_SMI_GEN2 ,
. has_gals = true ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 3 ) | F_MMU1_LARB ( 5 ) |
F_MMU1_LARB ( 7 ) ,
2021-09-14 14:37:01 +03:00
. init = mtk_smi_common_mt8195_init ,
2021-09-14 14:37:00 +03:00
} ;
static const struct mtk_smi_common_plat mtk_smi_common_mt8195_vpp = {
. type = MTK_SMI_GEN2 ,
. has_gals = true ,
. bus_sel = F_MMU1_LARB ( 1 ) | F_MMU1_LARB ( 2 ) | F_MMU1_LARB ( 7 ) ,
2021-09-14 14:37:01 +03:00
. init = mtk_smi_common_mt8195_init ,
2021-09-14 14:37:00 +03:00
} ;
static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8195 = {
. type = MTK_SMI_GEN2_SUB_COMM ,
. has_gals = true ,
} ;
2023-04-07 12:13:51 +03:00
static const struct mtk_smi_common_plat mtk_smi_common_mt8365 = {
. type = MTK_SMI_GEN2 ,
. bus_sel = F_MMU1_LARB ( 2 ) | F_MMU1_LARB ( 4 ) ,
} ;
2016-06-08 12:50:59 +03:00
static const struct of_device_id mtk_smi_common_of_ids [ ] = {
2021-09-14 14:36:55 +03:00
{ . compatible = " mediatek,mt2701-smi-common " , . data = & mtk_smi_common_gen1 } ,
{ . compatible = " mediatek,mt2712-smi-common " , . data = & mtk_smi_common_gen2 } ,
{ . compatible = " mediatek,mt6779-smi-common " , . data = & mtk_smi_common_mt6779 } ,
2022-05-18 12:10:38 +03:00
{ . compatible = " mediatek,mt6795-smi-common " , . data = & mtk_smi_common_mt6795 } ,
2021-09-14 14:36:55 +03:00
{ . compatible = " mediatek,mt8167-smi-common " , . data = & mtk_smi_common_gen2 } ,
{ . compatible = " mediatek,mt8173-smi-common " , . data = & mtk_smi_common_gen2 } ,
{ . compatible = " mediatek,mt8183-smi-common " , . data = & mtk_smi_common_mt8183 } ,
2022-01-13 14:10:57 +03:00
{ . compatible = " mediatek,mt8186-smi-common " , . data = & mtk_smi_common_mt8186 } ,
2022-08-17 15:46:08 +03:00
{ . compatible = " mediatek,mt8188-smi-common-vdo " , . data = & mtk_smi_common_mt8188_vdo } ,
{ . compatible = " mediatek,mt8188-smi-common-vpp " , . data = & mtk_smi_common_mt8188_vpp } ,
2021-09-14 14:36:55 +03:00
{ . compatible = " mediatek,mt8192-smi-common " , . data = & mtk_smi_common_mt8192 } ,
2021-09-14 14:37:00 +03:00
{ . compatible = " mediatek,mt8195-smi-common-vdo " , . data = & mtk_smi_common_mt8195_vdo } ,
{ . compatible = " mediatek,mt8195-smi-common-vpp " , . data = & mtk_smi_common_mt8195_vpp } ,
{ . compatible = " mediatek,mt8195-smi-sub-common " , . data = & mtk_smi_sub_common_mt8195 } ,
2023-04-07 12:13:51 +03:00
{ . compatible = " mediatek,mt8365-smi-common " , . data = & mtk_smi_common_mt8365 } ,
2016-06-08 12:50:59 +03:00
{ }
} ;
2016-02-22 20:20:49 +03:00
static int mtk_smi_common_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct mtk_smi * common ;
2021-09-14 14:36:53 +03:00
int ret , clk_required = MTK_SMI_COM_REQ_CLK_NR ;
2016-02-22 20:20:49 +03:00
common = devm_kzalloc ( dev , sizeof ( * common ) , GFP_KERNEL ) ;
if ( ! common )
return - ENOMEM ;
common - > dev = dev ;
2019-08-24 06:01:49 +03:00
common - > plat = of_device_get_match_data ( dev ) ;
2016-02-22 20:20:49 +03:00
2021-09-14 14:36:58 +03:00
if ( common - > plat - > has_gals ) {
if ( common - > plat - > type = = MTK_SMI_GEN2 )
clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR ;
else if ( common - > plat - > type = = MTK_SMI_GEN2_SUB_COMM )
clk_required = MTK_SMI_SUB_COM_GALS_REQ_CLK_NR ;
}
2021-09-14 14:36:53 +03:00
ret = mtk_smi_dts_clk_init ( dev , common , mtk_smi_common_clks , clk_required , 0 ) ;
if ( ret )
return ret ;
2019-08-24 06:02:01 +03:00
2016-06-08 12:50:59 +03:00
/*
* for mtk smi gen 1 , we need to get the ao ( always on ) base to config
* m4u port , and we need to enable the aync clock for transform the smi
* clock into emi clock domain , but for mtk smi gen2 , there ' s no smi ao
* base .
*/
2021-09-14 14:36:54 +03:00
if ( common - > plat - > type = = MTK_SMI_GEN1 ) {
2021-09-14 14:36:59 +03:00
common - > smi_ao_base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2016-06-08 12:50:59 +03:00
if ( IS_ERR ( common - > smi_ao_base ) )
return PTR_ERR ( common - > smi_ao_base ) ;
common - > clk_async = devm_clk_get ( dev , " async " ) ;
if ( IS_ERR ( common - > clk_async ) )
return PTR_ERR ( common - > clk_async ) ;
2017-08-10 08:17:32 +03:00
ret = clk_prepare_enable ( common - > clk_async ) ;
if ( ret )
return ret ;
2019-08-24 06:02:05 +03:00
} else {
2021-09-14 14:36:59 +03:00
common - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2019-08-24 06:02:05 +03:00
if ( IS_ERR ( common - > base ) )
return PTR_ERR ( common - > base ) ;
2016-06-08 12:50:59 +03:00
}
2021-09-14 14:36:57 +03:00
/* link its smi-common if this is smi-sub-common */
if ( common - > plat - > type = = MTK_SMI_GEN2_SUB_COMM ) {
ret = mtk_smi_device_link_common ( dev , & common - > smi_common_dev ) ;
if ( ret < 0 )
return ret ;
}
2016-02-22 20:20:49 +03:00
pm_runtime_enable ( dev ) ;
platform_set_drvdata ( pdev , common ) ;
return 0 ;
}
static int mtk_smi_common_remove ( struct platform_device * pdev )
{
2021-09-14 14:36:57 +03:00
struct mtk_smi * common = dev_get_drvdata ( & pdev - > dev ) ;
if ( common - > plat - > type = = MTK_SMI_GEN2_SUB_COMM )
device_link_remove ( & pdev - > dev , common - > smi_common_dev ) ;
2016-02-22 20:20:49 +03:00
pm_runtime_disable ( & pdev - > dev ) ;
return 0 ;
}
2019-08-24 06:02:04 +03:00
static int __maybe_unused mtk_smi_common_resume ( struct device * dev )
{
struct mtk_smi * common = dev_get_drvdata ( dev ) ;
2021-09-14 14:37:01 +03:00
const struct mtk_smi_reg_pair * init = common - > plat - > init ;
u32 bus_sel = common - > plat - > bus_sel ; /* default is 0 */
int ret , i ;
2019-08-24 06:02:04 +03:00
2021-09-14 14:36:53 +03:00
ret = clk_bulk_prepare_enable ( common - > clk_num , common - > clks ) ;
if ( ret )
2019-08-24 06:02:04 +03:00
return ret ;
2019-08-24 06:02:05 +03:00
2021-09-14 14:37:01 +03:00
if ( common - > plat - > type ! = MTK_SMI_GEN2 )
return 0 ;
for ( i = 0 ; i < SMI_COMMON_INIT_REGS_NR & & init & & init [ i ] . offset ; i + + )
writel_relaxed ( init [ i ] . value , common - > base + init [ i ] . offset ) ;
writel ( bus_sel , common - > base + SMI_BUS_SEL ) ;
2019-08-24 06:02:04 +03:00
return 0 ;
}
static int __maybe_unused mtk_smi_common_suspend ( struct device * dev )
{
struct mtk_smi * common = dev_get_drvdata ( dev ) ;
2021-09-14 14:36:53 +03:00
clk_bulk_disable_unprepare ( common - > clk_num , common - > clks ) ;
2019-08-24 06:02:04 +03:00
return 0 ;
}
static const struct dev_pm_ops smi_common_pm_ops = {
SET_RUNTIME_PM_OPS ( mtk_smi_common_suspend , mtk_smi_common_resume , NULL )
2019-10-09 14:59:33 +03:00
SET_LATE_SYSTEM_SLEEP_PM_OPS ( pm_runtime_force_suspend ,
pm_runtime_force_resume )
2019-08-24 06:02:04 +03:00
} ;
2016-02-22 20:20:49 +03:00
static struct platform_driver mtk_smi_common_driver = {
. probe = mtk_smi_common_probe ,
. remove = mtk_smi_common_remove ,
. driver = {
. name = " mtk-smi-common " ,
. of_match_table = mtk_smi_common_of_ids ,
2019-08-24 06:02:04 +03:00
. pm = & smi_common_pm_ops ,
2016-02-22 20:20:49 +03:00
}
} ;
2021-01-21 09:24:27 +03:00
static struct platform_driver * const smidrivers [ ] = {
& mtk_smi_common_driver ,
& mtk_smi_larb_driver ,
} ;
2016-02-22 20:20:49 +03:00
static int __init mtk_smi_init ( void )
{
2021-01-21 09:24:27 +03:00
return platform_register_drivers ( smidrivers , ARRAY_SIZE ( smidrivers ) ) ;
2016-02-22 20:20:49 +03:00
}
2017-08-21 14:00:21 +03:00
module_init ( mtk_smi_init ) ;
2021-01-26 09:00:55 +03:00
static void __exit mtk_smi_exit ( void )
{
platform_unregister_drivers ( smidrivers , ARRAY_SIZE ( smidrivers ) ) ;
}
module_exit ( mtk_smi_exit ) ;
MODULE_DESCRIPTION ( " MediaTek SMI driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;