Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: mediatek: pm-domains: Add support for mt8192

Add the needed board data to support mt8192 SoC.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Weiyi Lu <weiyi.lu@mediatek.com>
Link: https://lore.kernel.org/r/20201030113622.201188-17-enric.balletbo@collabora.com
Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>

authored by

Weiyi Lu and committed by
Matthias Brugger
a49d5e7a c1f3163d

+353
+292
drivers/soc/mediatek/mt8192-pm-domains.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __SOC_MEDIATEK_MT8192_PM_DOMAINS_H 4 + #define __SOC_MEDIATEK_MT8192_PM_DOMAINS_H 5 + 6 + #include "mtk-pm-domains.h" 7 + #include <dt-bindings/power/mt8192-power.h> 8 + 9 + /* 10 + * MT8192 power domain support 11 + */ 12 + 13 + static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { 14 + [MT8192_POWER_DOMAIN_AUDIO] = { 15 + .sta_mask = BIT(21), 16 + .ctl_offs = 0x0354, 17 + .sram_pdn_bits = GENMASK(8, 8), 18 + .sram_pdn_ack_bits = GENMASK(12, 12), 19 + .bp_infracfg = { 20 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_AUDIO, 21 + MT8192_TOP_AXI_PROT_EN_2_SET, 22 + MT8192_TOP_AXI_PROT_EN_2_CLR, 23 + MT8192_TOP_AXI_PROT_EN_2_STA1), 24 + }, 25 + }, 26 + [MT8192_POWER_DOMAIN_CONN] = { 27 + .sta_mask = PWR_STATUS_CONN, 28 + .ctl_offs = 0x0304, 29 + .sram_pdn_bits = 0, 30 + .sram_pdn_ack_bits = 0, 31 + .bp_infracfg = { 32 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN, 33 + MT8192_TOP_AXI_PROT_EN_SET, 34 + MT8192_TOP_AXI_PROT_EN_CLR, 35 + MT8192_TOP_AXI_PROT_EN_STA1), 36 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN_2ND, 37 + MT8192_TOP_AXI_PROT_EN_SET, 38 + MT8192_TOP_AXI_PROT_EN_CLR, 39 + MT8192_TOP_AXI_PROT_EN_STA1), 40 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CONN, 41 + MT8192_TOP_AXI_PROT_EN_1_SET, 42 + MT8192_TOP_AXI_PROT_EN_1_CLR, 43 + MT8192_TOP_AXI_PROT_EN_1_STA1), 44 + }, 45 + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, 46 + }, 47 + [MT8192_POWER_DOMAIN_MFG0] = { 48 + .sta_mask = BIT(2), 49 + .ctl_offs = 0x0308, 50 + .sram_pdn_bits = GENMASK(8, 8), 51 + .sram_pdn_ack_bits = GENMASK(12, 12), 52 + }, 53 + [MT8192_POWER_DOMAIN_MFG1] = { 54 + .sta_mask = BIT(3), 55 + .ctl_offs = 0x030c, 56 + .sram_pdn_bits = GENMASK(8, 8), 57 + .sram_pdn_ack_bits = GENMASK(12, 12), 58 + .bp_infracfg = { 59 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_MFG1, 60 + MT8192_TOP_AXI_PROT_EN_1_SET, 61 + MT8192_TOP_AXI_PROT_EN_1_CLR, 62 + MT8192_TOP_AXI_PROT_EN_1_STA1), 63 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1, 64 + MT8192_TOP_AXI_PROT_EN_2_SET, 65 + MT8192_TOP_AXI_PROT_EN_2_CLR, 66 + MT8192_TOP_AXI_PROT_EN_2_STA1), 67 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MFG1, 68 + MT8192_TOP_AXI_PROT_EN_SET, 69 + MT8192_TOP_AXI_PROT_EN_CLR, 70 + MT8192_TOP_AXI_PROT_EN_STA1), 71 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND, 72 + MT8192_TOP_AXI_PROT_EN_2_SET, 73 + MT8192_TOP_AXI_PROT_EN_2_CLR, 74 + MT8192_TOP_AXI_PROT_EN_2_STA1), 75 + }, 76 + }, 77 + [MT8192_POWER_DOMAIN_MFG2] = { 78 + .sta_mask = BIT(4), 79 + .ctl_offs = 0x0310, 80 + .sram_pdn_bits = GENMASK(8, 8), 81 + .sram_pdn_ack_bits = GENMASK(12, 12), 82 + }, 83 + [MT8192_POWER_DOMAIN_MFG3] = { 84 + .sta_mask = BIT(5), 85 + .ctl_offs = 0x0314, 86 + .sram_pdn_bits = GENMASK(8, 8), 87 + .sram_pdn_ack_bits = GENMASK(12, 12), 88 + }, 89 + [MT8192_POWER_DOMAIN_MFG4] = { 90 + .sta_mask = BIT(6), 91 + .ctl_offs = 0x0318, 92 + .sram_pdn_bits = GENMASK(8, 8), 93 + .sram_pdn_ack_bits = GENMASK(12, 12), 94 + }, 95 + [MT8192_POWER_DOMAIN_MFG5] = { 96 + .sta_mask = BIT(7), 97 + .ctl_offs = 0x031c, 98 + .sram_pdn_bits = GENMASK(8, 8), 99 + .sram_pdn_ack_bits = GENMASK(12, 12), 100 + }, 101 + [MT8192_POWER_DOMAIN_MFG6] = { 102 + .sta_mask = BIT(8), 103 + .ctl_offs = 0x0320, 104 + .sram_pdn_bits = GENMASK(8, 8), 105 + .sram_pdn_ack_bits = GENMASK(12, 12), 106 + }, 107 + [MT8192_POWER_DOMAIN_DISP] = { 108 + .sta_mask = BIT(20), 109 + .ctl_offs = 0x0350, 110 + .sram_pdn_bits = GENMASK(8, 8), 111 + .sram_pdn_ack_bits = GENMASK(12, 12), 112 + .bp_infracfg = { 113 + BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_DISP, 114 + MT8192_TOP_AXI_PROT_EN_MM_SET, 115 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 116 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 117 + BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_2_DISP, 118 + MT8192_TOP_AXI_PROT_EN_MM_2_SET, 119 + MT8192_TOP_AXI_PROT_EN_MM_2_CLR, 120 + MT8192_TOP_AXI_PROT_EN_MM_2_STA1), 121 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_DISP, 122 + MT8192_TOP_AXI_PROT_EN_SET, 123 + MT8192_TOP_AXI_PROT_EN_CLR, 124 + MT8192_TOP_AXI_PROT_EN_STA1), 125 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND, 126 + MT8192_TOP_AXI_PROT_EN_MM_SET, 127 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 128 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 129 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND, 130 + MT8192_TOP_AXI_PROT_EN_MM_2_SET, 131 + MT8192_TOP_AXI_PROT_EN_MM_2_CLR, 132 + MT8192_TOP_AXI_PROT_EN_MM_2_STA1), 133 + }, 134 + }, 135 + [MT8192_POWER_DOMAIN_IPE] = { 136 + .sta_mask = BIT(14), 137 + .ctl_offs = 0x0338, 138 + .sram_pdn_bits = GENMASK(8, 8), 139 + .sram_pdn_ack_bits = GENMASK(12, 12), 140 + .bp_infracfg = { 141 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE, 142 + MT8192_TOP_AXI_PROT_EN_MM_SET, 143 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 144 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 145 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND, 146 + MT8192_TOP_AXI_PROT_EN_MM_SET, 147 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 148 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 149 + }, 150 + }, 151 + [MT8192_POWER_DOMAIN_ISP] = { 152 + .sta_mask = BIT(12), 153 + .ctl_offs = 0x0330, 154 + .sram_pdn_bits = GENMASK(8, 8), 155 + .sram_pdn_ack_bits = GENMASK(12, 12), 156 + .bp_infracfg = { 157 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP, 158 + MT8192_TOP_AXI_PROT_EN_MM_2_SET, 159 + MT8192_TOP_AXI_PROT_EN_MM_2_CLR, 160 + MT8192_TOP_AXI_PROT_EN_MM_2_STA1), 161 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND, 162 + MT8192_TOP_AXI_PROT_EN_MM_2_SET, 163 + MT8192_TOP_AXI_PROT_EN_MM_2_CLR, 164 + MT8192_TOP_AXI_PROT_EN_MM_2_STA1), 165 + }, 166 + }, 167 + [MT8192_POWER_DOMAIN_ISP2] = { 168 + .sta_mask = BIT(13), 169 + .ctl_offs = 0x0334, 170 + .sram_pdn_bits = GENMASK(8, 8), 171 + .sram_pdn_ack_bits = GENMASK(12, 12), 172 + .bp_infracfg = { 173 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2, 174 + MT8192_TOP_AXI_PROT_EN_MM_SET, 175 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 176 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 177 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND, 178 + MT8192_TOP_AXI_PROT_EN_MM_SET, 179 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 180 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 181 + }, 182 + }, 183 + [MT8192_POWER_DOMAIN_MDP] = { 184 + .sta_mask = BIT(19), 185 + .ctl_offs = 0x034c, 186 + .sram_pdn_bits = GENMASK(8, 8), 187 + .sram_pdn_ack_bits = GENMASK(12, 12), 188 + .bp_infracfg = { 189 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP, 190 + MT8192_TOP_AXI_PROT_EN_MM_2_SET, 191 + MT8192_TOP_AXI_PROT_EN_MM_2_CLR, 192 + MT8192_TOP_AXI_PROT_EN_MM_2_STA1), 193 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND, 194 + MT8192_TOP_AXI_PROT_EN_MM_2_SET, 195 + MT8192_TOP_AXI_PROT_EN_MM_2_CLR, 196 + MT8192_TOP_AXI_PROT_EN_MM_2_STA1), 197 + }, 198 + }, 199 + [MT8192_POWER_DOMAIN_VENC] = { 200 + .sta_mask = BIT(17), 201 + .ctl_offs = 0x0344, 202 + .sram_pdn_bits = GENMASK(8, 8), 203 + .sram_pdn_ack_bits = GENMASK(12, 12), 204 + .bp_infracfg = { 205 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC, 206 + MT8192_TOP_AXI_PROT_EN_MM_SET, 207 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 208 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 209 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND, 210 + MT8192_TOP_AXI_PROT_EN_MM_SET, 211 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 212 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 213 + }, 214 + }, 215 + [MT8192_POWER_DOMAIN_VDEC] = { 216 + .sta_mask = BIT(15), 217 + .ctl_offs = 0x033c, 218 + .sram_pdn_bits = GENMASK(8, 8), 219 + .sram_pdn_ack_bits = GENMASK(12, 12), 220 + .bp_infracfg = { 221 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC, 222 + MT8192_TOP_AXI_PROT_EN_MM_SET, 223 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 224 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 225 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND, 226 + MT8192_TOP_AXI_PROT_EN_MM_SET, 227 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 228 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 229 + }, 230 + }, 231 + [MT8192_POWER_DOMAIN_VDEC2] = { 232 + .sta_mask = BIT(16), 233 + .ctl_offs = 0x0340, 234 + .sram_pdn_bits = GENMASK(8, 8), 235 + .sram_pdn_ack_bits = GENMASK(12, 12), 236 + }, 237 + [MT8192_POWER_DOMAIN_CAM] = { 238 + .sta_mask = BIT(23), 239 + .ctl_offs = 0x035c, 240 + .sram_pdn_bits = GENMASK(8, 8), 241 + .sram_pdn_ack_bits = GENMASK(12, 12), 242 + .bp_infracfg = { 243 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_CAM, 244 + MT8192_TOP_AXI_PROT_EN_2_SET, 245 + MT8192_TOP_AXI_PROT_EN_2_CLR, 246 + MT8192_TOP_AXI_PROT_EN_2_STA1), 247 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM, 248 + MT8192_TOP_AXI_PROT_EN_MM_SET, 249 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 250 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 251 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CAM, 252 + MT8192_TOP_AXI_PROT_EN_1_SET, 253 + MT8192_TOP_AXI_PROT_EN_1_CLR, 254 + MT8192_TOP_AXI_PROT_EN_1_STA1), 255 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND, 256 + MT8192_TOP_AXI_PROT_EN_MM_SET, 257 + MT8192_TOP_AXI_PROT_EN_MM_CLR, 258 + MT8192_TOP_AXI_PROT_EN_MM_STA1), 259 + BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_VDNR_CAM, 260 + MT8192_TOP_AXI_PROT_EN_VDNR_SET, 261 + MT8192_TOP_AXI_PROT_EN_VDNR_CLR, 262 + MT8192_TOP_AXI_PROT_EN_VDNR_STA1), 263 + }, 264 + }, 265 + [MT8192_POWER_DOMAIN_CAM_RAWA] = { 266 + .sta_mask = BIT(24), 267 + .ctl_offs = 0x0360, 268 + .sram_pdn_bits = GENMASK(8, 8), 269 + .sram_pdn_ack_bits = GENMASK(12, 12), 270 + }, 271 + [MT8192_POWER_DOMAIN_CAM_RAWB] = { 272 + .sta_mask = BIT(25), 273 + .ctl_offs = 0x0364, 274 + .sram_pdn_bits = GENMASK(8, 8), 275 + .sram_pdn_ack_bits = GENMASK(12, 12), 276 + }, 277 + [MT8192_POWER_DOMAIN_CAM_RAWC] = { 278 + .sta_mask = BIT(26), 279 + .ctl_offs = 0x0368, 280 + .sram_pdn_bits = GENMASK(8, 8), 281 + .sram_pdn_ack_bits = GENMASK(12, 12), 282 + }, 283 + }; 284 + 285 + static const struct scpsys_soc_data mt8192_scpsys_data = { 286 + .domains_data = scpsys_domain_data_mt8192, 287 + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192), 288 + .pwr_sta_offs = 0x016c, 289 + .pwr_sta2nd_offs = 0x0170, 290 + }; 291 + 292 + #endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */
+5
drivers/soc/mediatek/mtk-pm-domains.c
··· 17 17 18 18 #include "mt8173-pm-domains.h" 19 19 #include "mt8183-pm-domains.h" 20 + #include "mt8192-pm-domains.h" 20 21 21 22 #define MTK_POLL_DELAY_US 10 22 23 #define MTK_POLL_TIMEOUT USEC_PER_SEC ··· 521 520 { 522 521 .compatible = "mediatek,mt8183-power-controller", 523 522 .data = &mt8183_scpsys_data, 523 + }, 524 + { 525 + .compatible = "mediatek,mt8192-power-controller", 526 + .data = &mt8192_scpsys_data, 524 527 }, 525 528 { } 526 529 };
+56
include/linux/soc/mediatek/infracfg.h
··· 2 2 #ifndef __SOC_MEDIATEK_INFRACFG_H 3 3 #define __SOC_MEDIATEK_INFRACFG_H 4 4 5 + #define MT8192_TOP_AXI_PROT_EN_STA1 0x228 6 + #define MT8192_TOP_AXI_PROT_EN_1_STA1 0x258 7 + #define MT8192_TOP_AXI_PROT_EN_SET 0x2a0 8 + #define MT8192_TOP_AXI_PROT_EN_CLR 0x2a4 9 + #define MT8192_TOP_AXI_PROT_EN_1_SET 0x2a8 10 + #define MT8192_TOP_AXI_PROT_EN_1_CLR 0x2ac 11 + #define MT8192_TOP_AXI_PROT_EN_MM_SET 0x2d4 12 + #define MT8192_TOP_AXI_PROT_EN_MM_CLR 0x2d8 13 + #define MT8192_TOP_AXI_PROT_EN_MM_STA1 0x2ec 14 + #define MT8192_TOP_AXI_PROT_EN_2_SET 0x714 15 + #define MT8192_TOP_AXI_PROT_EN_2_CLR 0x718 16 + #define MT8192_TOP_AXI_PROT_EN_2_STA1 0x724 17 + #define MT8192_TOP_AXI_PROT_EN_VDNR_SET 0xb84 18 + #define MT8192_TOP_AXI_PROT_EN_VDNR_CLR 0xb88 19 + #define MT8192_TOP_AXI_PROT_EN_VDNR_STA1 0xb90 20 + #define MT8192_TOP_AXI_PROT_EN_MM_2_SET 0xdcc 21 + #define MT8192_TOP_AXI_PROT_EN_MM_2_CLR 0xdd0 22 + #define MT8192_TOP_AXI_PROT_EN_MM_2_STA1 0xdd8 23 + 24 + #define MT8192_TOP_AXI_PROT_EN_DISP (BIT(6) | BIT(23)) 25 + #define MT8192_TOP_AXI_PROT_EN_CONN (BIT(13) | BIT(18)) 26 + #define MT8192_TOP_AXI_PROT_EN_CONN_2ND BIT(14) 27 + #define MT8192_TOP_AXI_PROT_EN_MFG1 GENMASK(22, 21) 28 + #define MT8192_TOP_AXI_PROT_EN_1_CONN BIT(10) 29 + #define MT8192_TOP_AXI_PROT_EN_1_MFG1 BIT(21) 30 + #define MT8192_TOP_AXI_PROT_EN_1_CAM BIT(22) 31 + #define MT8192_TOP_AXI_PROT_EN_2_CAM BIT(0) 32 + #define MT8192_TOP_AXI_PROT_EN_2_ADSP BIT(3) 33 + #define MT8192_TOP_AXI_PROT_EN_2_AUDIO BIT(4) 34 + #define MT8192_TOP_AXI_PROT_EN_2_MFG1 GENMASK(6, 5) 35 + #define MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND BIT(7) 36 + #define MT8192_TOP_AXI_PROT_EN_MM_CAM (BIT(0) | BIT(2)) 37 + #define MT8192_TOP_AXI_PROT_EN_MM_DISP (BIT(0) | BIT(2) | \ 38 + BIT(10) | BIT(12) | \ 39 + BIT(14) | BIT(16) | \ 40 + BIT(24) | BIT(26)) 41 + #define MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND (BIT(1) | BIT(3)) 42 + #define MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND (BIT(1) | BIT(3) | \ 43 + BIT(15) | BIT(17) | \ 44 + BIT(25) | BIT(27)) 45 + #define MT8192_TOP_AXI_PROT_EN_MM_ISP2 BIT(14) 46 + #define MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND BIT(15) 47 + #define MT8192_TOP_AXI_PROT_EN_MM_IPE BIT(16) 48 + #define MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND BIT(17) 49 + #define MT8192_TOP_AXI_PROT_EN_MM_VDEC BIT(24) 50 + #define MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND BIT(25) 51 + #define MT8192_TOP_AXI_PROT_EN_MM_VENC BIT(26) 52 + #define MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND BIT(27) 53 + #define MT8192_TOP_AXI_PROT_EN_MM_2_ISP BIT(8) 54 + #define MT8192_TOP_AXI_PROT_EN_MM_2_DISP (BIT(8) | BIT(12)) 55 + #define MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND BIT(9) 56 + #define MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND (BIT(9) | BIT(13)) 57 + #define MT8192_TOP_AXI_PROT_EN_MM_2_MDP BIT(12) 58 + #define MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND BIT(13) 59 + #define MT8192_TOP_AXI_PROT_EN_VDNR_CAM BIT(21) 60 + 5 61 #define MT8183_TOP_AXI_PROT_EN_STA1 0x228 6 62 #define MT8183_TOP_AXI_PROT_EN_STA1_1 0x258 7 63 #define MT8183_TOP_AXI_PROT_EN_SET 0x2a0