1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2023, MediaTek Inc. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu /* TF-A system header */ 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu #include <lib/utils_def.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu /* Vendor header */ 12*91f16700Schasinglulu #include "apusys.h" 13*91f16700Schasinglulu #include "apusys_devapc.h" 14*91f16700Schasinglulu #include "apusys_devapc_def.h" 15*91f16700Schasinglulu #include <platform_def.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #define DUMP_APUSYS_DAPC (0) 18*91f16700Schasinglulu 19*91f16700Schasinglulu static const struct apc_dom_16 APU_NOC_DAPC_RCX[] = { 20*91f16700Schasinglulu /* ctrl index = 0 */ 21*91f16700Schasinglulu SLAVE_MD32_SRAM("slv16-0"), 22*91f16700Schasinglulu SLAVE_MD32_SRAM("slv16-1"), 23*91f16700Schasinglulu SLAVE_MD32_SRAM("slv16-2"), 24*91f16700Schasinglulu SLAVE_MD32_SRAM("slv16-3"), 25*91f16700Schasinglulu SLAVE_MD32_SRAM("slv16-4"), 26*91f16700Schasinglulu }; 27*91f16700Schasinglulu 28*91f16700Schasinglulu static const struct apc_dom_16 APU_CTRL_DAPC_AO[] = { 29*91f16700Schasinglulu /* ctrl index = 0 */ 30*91f16700Schasinglulu SLAVE_VCORE("apu_ao_ctl_o-0"), 31*91f16700Schasinglulu SLAVE_RPC("apu_ao_ctl_o-2"), 32*91f16700Schasinglulu SLAVE_PCU("apu_ao_ctl_o-3"), 33*91f16700Schasinglulu SLAVE_AO_CTRL("apu_ao_ctl_o-4"), 34*91f16700Schasinglulu SLAVE_PLL("apu_ao_ctl_o-5"), 35*91f16700Schasinglulu SLAVE_ACC("apu_ao_ctl_o-6"), 36*91f16700Schasinglulu SLAVE_SEC("apu_ao_ctl_o-7"), 37*91f16700Schasinglulu SLAVE_ARE0("apu_ao_ctl_o-8"), 38*91f16700Schasinglulu SLAVE_ARE1("apu_ao_ctl_o-9"), 39*91f16700Schasinglulu SLAVE_ARE2("apu_ao_ctl_o-10"), 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* ctrl index = 10 */ 42*91f16700Schasinglulu SLAVE_UNKNOWN("apu_ao_ctl_o-11"), 43*91f16700Schasinglulu SLAVE_AO_BCRM("apu_ao_ctl_o-12"), 44*91f16700Schasinglulu SLAVE_AO_DAPC_WRAP("apu_ao_ctl_o-13"), 45*91f16700Schasinglulu SLAVE_AO_DAPC_CON("apu_ao_ctl_o-14"), 46*91f16700Schasinglulu SLAVE_RCX_ACX_BULK("apu_ao_ctl_o-15"), 47*91f16700Schasinglulu SLAVE_UNKNOWN("apu_ao_ctl_o-16"), 48*91f16700Schasinglulu SLAVE_UNKNOWN("apu_ao_ctl_o-17"), 49*91f16700Schasinglulu SLAVE_APU_BULK("apu_ao_ctl_o-18"), 50*91f16700Schasinglulu SLAVE_ACX0_BCRM("apu_ao_ctl_o-20"), 51*91f16700Schasinglulu SLAVE_RPCTOP_LITE_ACX0("apu_ao_ctl_o-21"), 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* ctrl index = 20 */ 54*91f16700Schasinglulu SLAVE_ACX1_BCRM("apu_ao_ctl_o-22"), 55*91f16700Schasinglulu SLAVE_RPCTOP_LITE_ACX1("apu_ao_ctl_o-23"), 56*91f16700Schasinglulu SLAVE_RCX_TO_ACX0_0("apu_rcx2acx0_o-0"), 57*91f16700Schasinglulu SLAVE_RCX_TO_ACX0_1("apu_rcx2acx0_o-1"), 58*91f16700Schasinglulu SLAVE_SAE_TO_ACX0_0("apu_sae2acx0_o-0"), 59*91f16700Schasinglulu SLAVE_SAE_TO_ACX0_1("apu_sae2acx0_o-1"), 60*91f16700Schasinglulu SLAVE_RCX_TO_ACX1_0("apu_rcx2acx1_o-0"), 61*91f16700Schasinglulu SLAVE_RCX_TO_ACX1_1("apu_rcx2acx1_o-1"), 62*91f16700Schasinglulu SLAVE_SAE_TO_ACX1_0("apu_sae2acx1_o-0"), 63*91f16700Schasinglulu SLAVE_SAE_TO_ACX1_1("apu_sae2acx1_o-1"), 64*91f16700Schasinglulu }; 65*91f16700Schasinglulu 66*91f16700Schasinglulu static const struct apc_dom_16 APU_CTRL_DAPC_RCX[] = { 67*91f16700Schasinglulu /* ctrl index = 0 */ 68*91f16700Schasinglulu SLAVE_MD32_SYSCTRL0("md32_apb_s-0"), 69*91f16700Schasinglulu SLAVE_MD32_SYSCTRL1("md32_apb_s-1"), 70*91f16700Schasinglulu SLAVE_MD32_WDT("md32_apb_s-2"), 71*91f16700Schasinglulu SLAVE_MD32_CACHE("md32_apb_s-3"), 72*91f16700Schasinglulu SLAVE_RPC("apusys_ao-0"), 73*91f16700Schasinglulu SLAVE_PCU("apusys_ao-1"), 74*91f16700Schasinglulu SLAVE_AO_CTRL("apusys_ao-2"), 75*91f16700Schasinglulu SLAVE_PLL("apusys_ao-3"), 76*91f16700Schasinglulu SLAVE_ACC("apusys_ao-4"), 77*91f16700Schasinglulu SLAVE_SEC("apusys_ao-5"), 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* ctrl index = 10 */ 80*91f16700Schasinglulu SLAVE_ARE0("apusys_ao-6"), 81*91f16700Schasinglulu SLAVE_ARE1("apusys_ao-7"), 82*91f16700Schasinglulu SLAVE_ARE2("apusys_ao-8"), 83*91f16700Schasinglulu SLAVE_UNKNOWN("apusys_ao-9"), 84*91f16700Schasinglulu SLAVE_AO_BCRM("apusys_ao-10"), 85*91f16700Schasinglulu SLAVE_AO_DAPC_WRAP("apusys_ao-11"), 86*91f16700Schasinglulu SLAVE_AO_DAPC_CON("apusys_ao-12"), 87*91f16700Schasinglulu SLAVE_VCORE("apusys_ao-13"), 88*91f16700Schasinglulu SLAVE_ACX0_BCRM("apusys_ao-15"), 89*91f16700Schasinglulu SLAVE_ACX1_BCRM("apusys_ao-16"), 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* ctrl index = 20 */ 92*91f16700Schasinglulu SLAVE_NOC_AXI("noc_axi"), 93*91f16700Schasinglulu SLAVE_MD32_DBG("md32_dbg"), 94*91f16700Schasinglulu SLAVE_DBG_CRTL("apb_infra_dbg"), 95*91f16700Schasinglulu SLAVE_IOMMU0_BANK0("apu_n_mmu_r0"), 96*91f16700Schasinglulu SLAVE_IOMMU0_BANK1("apu_n_mmu_r1"), 97*91f16700Schasinglulu SLAVE_IOMMU0_BANK2("apu_n_mmu_r2"), 98*91f16700Schasinglulu SLAVE_IOMMU0_BANK3("apu_n_mmu_r3"), 99*91f16700Schasinglulu SLAVE_IOMMU0_BANK4("apu_n_mmu_r4"), 100*91f16700Schasinglulu SLAVE_IOMMU1_BANK0("apu_s_mmu_r0"), 101*91f16700Schasinglulu SLAVE_IOMMU1_BANK1("apu_s_mmu_r1"), 102*91f16700Schasinglulu 103*91f16700Schasinglulu /* ctrl index = 30 */ 104*91f16700Schasinglulu SLAVE_IOMMU1_BANK2("apu_s_mmu_r2"), 105*91f16700Schasinglulu SLAVE_IOMMU1_BANK3("apu_s_mmu_r3"), 106*91f16700Schasinglulu SLAVE_IOMMU1_BANK4("apu_s_mmu_r4"), 107*91f16700Schasinglulu SLAVE_S0_SSC("apu_s0_ssc_cfg"), 108*91f16700Schasinglulu SLAVE_N0_SSC("apu_n0_ssc_cfg"), 109*91f16700Schasinglulu SLAVE_ACP_SSC("apu_acp_ssc_cfg"), 110*91f16700Schasinglulu SLAVE_S1_SSC("apu_s1_ssc_cfg"), 111*91f16700Schasinglulu SLAVE_N1_SSC("apu_n1_ssc_cfg"), 112*91f16700Schasinglulu SLAVE_CFG("apu_rcx_cfg"), 113*91f16700Schasinglulu SLAVE_SEMA_STIMER("apu_sema_stimer"), 114*91f16700Schasinglulu 115*91f16700Schasinglulu /* ctrl index = 40 */ 116*91f16700Schasinglulu SLAVE_EMI_CFG("apu_emi_cfg"), 117*91f16700Schasinglulu SLAVE_LOG("apu_logtop"), 118*91f16700Schasinglulu SLAVE_CPE_SENSOR("apu_cpe_sensor"), 119*91f16700Schasinglulu SLAVE_CPE_COEF("apu_cpe_coef"), 120*91f16700Schasinglulu SLAVE_CPE_CTRL("apu_cpe_ctrl"), 121*91f16700Schasinglulu SLAVE_UNKNOWN("apu_xpu_rsi"), 122*91f16700Schasinglulu SLAVE_DFD_REG_SOC("apu_dfd"), 123*91f16700Schasinglulu SLAVE_SENSOR_WRAP_ACX0_DLA0("apu_sen_ac0_dla0"), 124*91f16700Schasinglulu SLAVE_SENSOR_WRAP_ACX0_DLA1("apu_sen_ac0_dla1"), 125*91f16700Schasinglulu SLAVE_SENSOR_WRAP_ACX0_VPU0("apu_sen_ac0_vpu"), 126*91f16700Schasinglulu 127*91f16700Schasinglulu /* ctrl index = 50 */ 128*91f16700Schasinglulu SLAVE_SENSOR_WRAP_ACX1_DLA0("apu_sen_ac1_dla0"), 129*91f16700Schasinglulu SLAVE_SENSOR_WRAP_ACX1_DLA1("apu_sen_ac1_dla1"), 130*91f16700Schasinglulu SLAVE_SENSOR_WRAP_ACX1_VPU0("apu_sen_ac1_vpu"), 131*91f16700Schasinglulu SLAVE_REVISER("noc_cfg-0"), 132*91f16700Schasinglulu SLAVE_NOC("noc_cfg-1"), 133*91f16700Schasinglulu SLAVE_BCRM("infra_bcrm"), 134*91f16700Schasinglulu SLAVE_DAPC_WRAP("infra_dapc_wrap"), 135*91f16700Schasinglulu SLAVE_DAPC_CON("infra_dapc_con"), 136*91f16700Schasinglulu SLAVE_NOC_DAPC_WRAP("noc_dapc_wrap"), 137*91f16700Schasinglulu SLAVE_NOC_DAPC_CON("noc_dapc_con"), 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* ctrl index = 60 */ 140*91f16700Schasinglulu SLAVE_NOC_BCRM("noc_bcrm"), 141*91f16700Schasinglulu SLAVE_ACS("apu_rcx_acs"), 142*91f16700Schasinglulu SLAVE_HSE("apu_hse"), 143*91f16700Schasinglulu }; 144*91f16700Schasinglulu 145*91f16700Schasinglulu static enum apusys_apc_err_status set_slave_ao_ctrl_apc(uint32_t slave, 146*91f16700Schasinglulu enum apusys_apc_domain_id domain_id, 147*91f16700Schasinglulu enum apusys_apc_perm_type perm) 148*91f16700Schasinglulu { 149*91f16700Schasinglulu uint32_t apc_register_index; 150*91f16700Schasinglulu uint32_t apc_set_index; 151*91f16700Schasinglulu uint32_t base; 152*91f16700Schasinglulu uint32_t clr_bit; 153*91f16700Schasinglulu uint32_t set_bit; 154*91f16700Schasinglulu 155*91f16700Schasinglulu if ((perm < 0) || (perm >= PERM_NUM)) { 156*91f16700Schasinglulu ERROR(MODULE_TAG "%s: permission type:0x%x is not supported!\n", __func__, perm); 157*91f16700Schasinglulu return APUSYS_APC_ERR_GENERIC; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu if ((slave >= APU_CTRL_DAPC_AO_SLAVE_NUM) || 161*91f16700Schasinglulu ((domain_id < 0) || (domain_id >= APU_CTRL_DAPC_AO_DOM_NUM))) { 162*91f16700Schasinglulu ERROR(MODULE_TAG "%s: out of boundary, slave:0x%x, domain_id:0x%x\n", 163*91f16700Schasinglulu __func__, slave, domain_id); 164*91f16700Schasinglulu return APUSYS_APC_ERR_GENERIC; 165*91f16700Schasinglulu } 166*91f16700Schasinglulu 167*91f16700Schasinglulu apc_register_index = slave / APU_CTRL_DAPC_AO_SLAVE_NUM_IN_1_DOM; 168*91f16700Schasinglulu apc_set_index = slave % APU_CTRL_DAPC_AO_SLAVE_NUM_IN_1_DOM; 169*91f16700Schasinglulu 170*91f16700Schasinglulu clr_bit = (DEVAPC_MASK << (apc_set_index * DEVAPC_DOM_SHIFT)); 171*91f16700Schasinglulu set_bit = (uint32_t)perm << (apc_set_index * DEVAPC_DOM_SHIFT); 172*91f16700Schasinglulu 173*91f16700Schasinglulu base = (APU_CTRL_DAPC_AO_BASE + domain_id * DEVAPC_DOM_SIZE + 174*91f16700Schasinglulu apc_register_index * DEVAPC_REG_SIZE); 175*91f16700Schasinglulu 176*91f16700Schasinglulu mmio_clrsetbits_32(base, clr_bit, set_bit); 177*91f16700Schasinglulu return APUSYS_APC_OK; 178*91f16700Schasinglulu } 179*91f16700Schasinglulu 180*91f16700Schasinglulu static enum apusys_apc_err_status set_slave_noc_dapc_rcx(uint32_t slave, 181*91f16700Schasinglulu enum apusys_apc_domain_id domain_id, 182*91f16700Schasinglulu enum apusys_apc_perm_type perm) 183*91f16700Schasinglulu { 184*91f16700Schasinglulu uint32_t apc_register_index; 185*91f16700Schasinglulu uint32_t apc_set_index; 186*91f16700Schasinglulu uint32_t base; 187*91f16700Schasinglulu uint32_t clr_bit; 188*91f16700Schasinglulu uint32_t set_bit; 189*91f16700Schasinglulu 190*91f16700Schasinglulu if ((perm >= PERM_NUM) || (perm < 0)) { 191*91f16700Schasinglulu ERROR(MODULE_TAG "%s: permission type:0x%x is not supported!\n", __func__, perm); 192*91f16700Schasinglulu return APUSYS_APC_ERR_GENERIC; 193*91f16700Schasinglulu } 194*91f16700Schasinglulu 195*91f16700Schasinglulu if ((slave >= APU_NOC_DAPC_RCX_SLAVE_NUM) || 196*91f16700Schasinglulu ((domain_id < 0) || (domain_id >= APU_NOC_DAPC_RCX_DOM_NUM))) { 197*91f16700Schasinglulu ERROR(MODULE_TAG "%s: out of boundary, slave:0x%x, domain_id:0x%x\n", 198*91f16700Schasinglulu __func__, slave, domain_id); 199*91f16700Schasinglulu return APUSYS_APC_ERR_GENERIC; 200*91f16700Schasinglulu } 201*91f16700Schasinglulu 202*91f16700Schasinglulu apc_register_index = slave / APU_NOC_DAPC_RCX_SLAVE_NUM_IN_1_DOM; 203*91f16700Schasinglulu apc_set_index = slave % APU_NOC_DAPC_RCX_SLAVE_NUM_IN_1_DOM; 204*91f16700Schasinglulu 205*91f16700Schasinglulu clr_bit = (DEVAPC_MASK << (apc_set_index * DEVAPC_DOM_SHIFT)); 206*91f16700Schasinglulu set_bit = ((uint32_t)perm) << (apc_set_index * DEVAPC_DOM_SHIFT); 207*91f16700Schasinglulu base = (APU_NOC_DAPC_RCX_BASE + domain_id * DEVAPC_DOM_SIZE + 208*91f16700Schasinglulu apc_register_index * DEVAPC_REG_SIZE); 209*91f16700Schasinglulu 210*91f16700Schasinglulu mmio_clrsetbits_32(base, clr_bit, set_bit); 211*91f16700Schasinglulu return APUSYS_APC_OK; 212*91f16700Schasinglulu } 213*91f16700Schasinglulu 214*91f16700Schasinglulu static enum apusys_apc_err_status set_slave_rcx_ctrl_apc(uint32_t slave, 215*91f16700Schasinglulu enum apusys_apc_domain_id domain_id, 216*91f16700Schasinglulu enum apusys_apc_perm_type perm) 217*91f16700Schasinglulu { 218*91f16700Schasinglulu uint32_t apc_register_index; 219*91f16700Schasinglulu uint32_t apc_set_index; 220*91f16700Schasinglulu uint32_t base; 221*91f16700Schasinglulu uint32_t clr_bit; 222*91f16700Schasinglulu uint32_t set_bit; 223*91f16700Schasinglulu 224*91f16700Schasinglulu if ((perm < 0) || (perm >= PERM_NUM)) { 225*91f16700Schasinglulu ERROR(MODULE_TAG "%s: permission type:0x%x is not supported!\n", __func__, perm); 226*91f16700Schasinglulu return APUSYS_APC_ERR_GENERIC; 227*91f16700Schasinglulu } 228*91f16700Schasinglulu 229*91f16700Schasinglulu if ((slave >= APU_CTRL_DAPC_RCX_SLAVE_NUM) || 230*91f16700Schasinglulu ((domain_id < 0) || (domain_id >= APU_CTRL_DAPC_RCX_DOM_NUM))) { 231*91f16700Schasinglulu ERROR(MODULE_TAG "%s: out of boundary, slave:0x%x, domain_id:0x%x\n", 232*91f16700Schasinglulu __func__, slave, domain_id); 233*91f16700Schasinglulu return APUSYS_APC_ERR_GENERIC; 234*91f16700Schasinglulu } 235*91f16700Schasinglulu 236*91f16700Schasinglulu apc_register_index = slave / APU_CTRL_DAPC_RCX_SLAVE_NUM_IN_1_DOM; 237*91f16700Schasinglulu apc_set_index = slave % APU_CTRL_DAPC_RCX_SLAVE_NUM_IN_1_DOM; 238*91f16700Schasinglulu 239*91f16700Schasinglulu clr_bit = (DEVAPC_MASK << (apc_set_index * DEVAPC_DOM_SHIFT)); 240*91f16700Schasinglulu set_bit = (uint32_t)perm << (apc_set_index * DEVAPC_DOM_SHIFT); 241*91f16700Schasinglulu base = (APU_CTRL_DAPC_RCX_BASE + domain_id * DEVAPC_DOM_SIZE + 242*91f16700Schasinglulu apc_register_index * DEVAPC_REG_SIZE); 243*91f16700Schasinglulu 244*91f16700Schasinglulu mmio_clrsetbits_32(base, clr_bit, set_bit); 245*91f16700Schasinglulu return APUSYS_APC_OK; 246*91f16700Schasinglulu } 247*91f16700Schasinglulu 248*91f16700Schasinglulu static void apusys_devapc_init(const char *name, uint32_t base) 249*91f16700Schasinglulu { 250*91f16700Schasinglulu mmio_write_32(APUSYS_DAPC_CON(base), APUSYS_DAPC_CON_VIO_MASK); 251*91f16700Schasinglulu } 252*91f16700Schasinglulu 253*91f16700Schasinglulu int apusys_devapc_ao_init(void) 254*91f16700Schasinglulu { 255*91f16700Schasinglulu enum apusys_apc_err_status ret; 256*91f16700Schasinglulu 257*91f16700Schasinglulu apusys_devapc_init("APUAPC_CTRL_AO", APU_CTRL_DAPC_AO_BASE); 258*91f16700Schasinglulu 259*91f16700Schasinglulu ret = SET_APUSYS_DAPC_V1(APU_CTRL_DAPC_AO, set_slave_ao_ctrl_apc); 260*91f16700Schasinglulu if (ret != APUSYS_APC_OK) { 261*91f16700Schasinglulu ERROR(MODULE_TAG "%s: set_apusys_ao_ctrl_dap FAILED!\n", __func__); 262*91f16700Schasinglulu return -1; 263*91f16700Schasinglulu } 264*91f16700Schasinglulu 265*91f16700Schasinglulu #if DUMP_APUSYS_DAPC 266*91f16700Schasinglulu DUMP_APUSYS_DAPC_V1(APU_CTRL_DAPC_AO); 267*91f16700Schasinglulu #endif 268*91f16700Schasinglulu 269*91f16700Schasinglulu return 0; 270*91f16700Schasinglulu } 271*91f16700Schasinglulu 272*91f16700Schasinglulu int apusys_devapc_rcx_init(void) 273*91f16700Schasinglulu { 274*91f16700Schasinglulu static bool apusys_devapc_rcx_init_called; 275*91f16700Schasinglulu enum apusys_apc_err_status ret; 276*91f16700Schasinglulu 277*91f16700Schasinglulu if (apusys_devapc_rcx_init_called == true) { 278*91f16700Schasinglulu INFO(MODULE_TAG "%s: init more than once!\n", __func__); 279*91f16700Schasinglulu return -1; 280*91f16700Schasinglulu } 281*91f16700Schasinglulu apusys_devapc_rcx_init_called = true; 282*91f16700Schasinglulu 283*91f16700Schasinglulu apusys_devapc_init("APUAPC_CTRL_RCX", APU_CTRL_DAPC_RCX_BASE); 284*91f16700Schasinglulu apusys_devapc_init("APUAPC_NOC_RCX", APU_NOC_DAPC_RCX_BASE); 285*91f16700Schasinglulu 286*91f16700Schasinglulu ret = SET_APUSYS_DAPC_V1(APU_CTRL_DAPC_RCX, set_slave_rcx_ctrl_apc); 287*91f16700Schasinglulu if (ret != APUSYS_APC_OK) { 288*91f16700Schasinglulu ERROR(MODULE_TAG "%s: set_slave_rcx_ctrl_apc FAILED!\n", __func__); 289*91f16700Schasinglulu return -1; 290*91f16700Schasinglulu } 291*91f16700Schasinglulu 292*91f16700Schasinglulu #if DUMP_APUSYS_DAPC 293*91f16700Schasinglulu DUMP_APUSYS_DAPC_V1(APU_CTRL_DAPC_RCX); 294*91f16700Schasinglulu #endif 295*91f16700Schasinglulu 296*91f16700Schasinglulu ret = SET_APUSYS_DAPC_V1(APU_NOC_DAPC_RCX, set_slave_noc_dapc_rcx); 297*91f16700Schasinglulu if (ret != APUSYS_APC_OK) { 298*91f16700Schasinglulu ERROR(MODULE_TAG "%s: set_slave_noc_dapc_rcx FAILED\n", __func__); 299*91f16700Schasinglulu return -1; 300*91f16700Schasinglulu } 301*91f16700Schasinglulu 302*91f16700Schasinglulu #if DUMP_APUSYS_DAPC 303*91f16700Schasinglulu DUMP_APUSYS_DAPC_V1(APU_NOC_DAPC_RCX); 304*91f16700Schasinglulu #endif 305*91f16700Schasinglulu 306*91f16700Schasinglulu return 0; 307*91f16700Schasinglulu } 308