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

clk: meson: gxbb: Add sd_emmc clk0 clocks

Input source 0 of the mmc controllers is not directly xtal, as currently
described in DT. Each controller is fed by a composite clock (the usual
mux, divider and gate). The muxes inputs are the xtal (default) and the
fclk_div clocks. These parents, along with the divider, should be able to
provide the necessary rates for mmc and nand operation.

The input muxes should also be able to take mpll2, mpll3 and gp0_pll but
these are precious clocks, needed for other usage. It is better if the
mmc does not use these them. For this reason, mpll2, mpll3 and gp0_pll is
not listed among the possible parents.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

authored by

Jerome Brunet and committed by
Neil Armstrong
914e6e80 7605aa5b

+177
+177
drivers/clk/meson/gxbb.c
··· 976 976 }, 977 977 }; 978 978 979 + static const char * const gxbb_sd_emmc_clk0_parent_names[] = { 980 + "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", 981 + 982 + /* 983 + * Following these parent clocks, we should also have had mpll2, mpll3 984 + * and gp0_pll but these clocks are too precious to be used here. All 985 + * the necessary rates for MMC and NAND operation can be acheived using 986 + * xtal or fclk_div clocks 987 + */ 988 + }; 989 + 990 + /* SDIO clock */ 991 + static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { 992 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 993 + .mask = 0x7, 994 + .shift = 9, 995 + .lock = &clk_lock, 996 + .hw.init = &(struct clk_init_data) { 997 + .name = "sd_emmc_a_clk0_sel", 998 + .ops = &clk_mux_ops, 999 + .parent_names = gxbb_sd_emmc_clk0_parent_names, 1000 + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1001 + .flags = CLK_SET_RATE_PARENT, 1002 + }, 1003 + }; 1004 + 1005 + static struct clk_divider gxbb_sd_emmc_a_clk0_div = { 1006 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1007 + .shift = 0, 1008 + .width = 7, 1009 + .lock = &clk_lock, 1010 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 1011 + .hw.init = &(struct clk_init_data) { 1012 + .name = "sd_emmc_a_clk0_div", 1013 + .ops = &clk_divider_ops, 1014 + .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, 1015 + .num_parents = 1, 1016 + .flags = CLK_SET_RATE_PARENT, 1017 + }, 1018 + }; 1019 + 1020 + static struct clk_gate gxbb_sd_emmc_a_clk0 = { 1021 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1022 + .bit_idx = 7, 1023 + .lock = &clk_lock, 1024 + .hw.init = &(struct clk_init_data){ 1025 + .name = "sd_emmc_a_clk0", 1026 + .ops = &clk_gate_ops, 1027 + .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, 1028 + .num_parents = 1, 1029 + 1030 + /* 1031 + * FIXME: 1032 + * We need CLK_IGNORE_UNUSED because mmc DT node point to xtal 1033 + * instead of this clock. CCF would gate this on boot, killing 1034 + * the mmc controller. Please remove this flag once DT properly 1035 + * point to this clock instead of xtal 1036 + * 1037 + * Same goes for emmc B and C clocks 1038 + */ 1039 + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1040 + }, 1041 + }; 1042 + 1043 + /* SDcard clock */ 1044 + static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { 1045 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1046 + .mask = 0x7, 1047 + .shift = 25, 1048 + .lock = &clk_lock, 1049 + .hw.init = &(struct clk_init_data) { 1050 + .name = "sd_emmc_b_clk0_sel", 1051 + .ops = &clk_mux_ops, 1052 + .parent_names = gxbb_sd_emmc_clk0_parent_names, 1053 + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1054 + .flags = CLK_SET_RATE_PARENT, 1055 + }, 1056 + }; 1057 + 1058 + static struct clk_divider gxbb_sd_emmc_b_clk0_div = { 1059 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1060 + .shift = 16, 1061 + .width = 7, 1062 + .lock = &clk_lock, 1063 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 1064 + .hw.init = &(struct clk_init_data) { 1065 + .name = "sd_emmc_b_clk0_div", 1066 + .ops = &clk_divider_ops, 1067 + .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, 1068 + .num_parents = 1, 1069 + .flags = CLK_SET_RATE_PARENT, 1070 + }, 1071 + }; 1072 + 1073 + static struct clk_gate gxbb_sd_emmc_b_clk0 = { 1074 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1075 + .bit_idx = 23, 1076 + .lock = &clk_lock, 1077 + .hw.init = &(struct clk_init_data){ 1078 + .name = "sd_emmc_b_clk0", 1079 + .ops = &clk_gate_ops, 1080 + .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, 1081 + .num_parents = 1, 1082 + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1083 + }, 1084 + }; 1085 + 1086 + /* EMMC/NAND clock */ 1087 + static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { 1088 + .reg = (void *)HHI_NAND_CLK_CNTL, 1089 + .mask = 0x7, 1090 + .shift = 9, 1091 + .lock = &clk_lock, 1092 + .hw.init = &(struct clk_init_data) { 1093 + .name = "sd_emmc_c_clk0_sel", 1094 + .ops = &clk_mux_ops, 1095 + .parent_names = gxbb_sd_emmc_clk0_parent_names, 1096 + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1097 + .flags = CLK_SET_RATE_PARENT, 1098 + }, 1099 + }; 1100 + 1101 + static struct clk_divider gxbb_sd_emmc_c_clk0_div = { 1102 + .reg = (void *)HHI_NAND_CLK_CNTL, 1103 + .shift = 0, 1104 + .width = 7, 1105 + .lock = &clk_lock, 1106 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 1107 + .hw.init = &(struct clk_init_data) { 1108 + .name = "sd_emmc_c_clk0_div", 1109 + .ops = &clk_divider_ops, 1110 + .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, 1111 + .num_parents = 1, 1112 + .flags = CLK_SET_RATE_PARENT, 1113 + }, 1114 + }; 1115 + 1116 + static struct clk_gate gxbb_sd_emmc_c_clk0 = { 1117 + .reg = (void *)HHI_NAND_CLK_CNTL, 1118 + .bit_idx = 7, 1119 + .lock = &clk_lock, 1120 + .hw.init = &(struct clk_init_data){ 1121 + .name = "sd_emmc_c_clk0", 1122 + .ops = &clk_gate_ops, 1123 + .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, 1124 + .num_parents = 1, 1125 + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1126 + }, 1127 + }; 1128 + 979 1129 /* Everything Else (EE) domain gates */ 980 1130 static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); 981 1131 static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); ··· 1335 1185 [CLKID_32K_CLK] = &gxbb_32k_clk.hw, 1336 1186 [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, 1337 1187 [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, 1188 + [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, 1189 + [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, 1190 + [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, 1191 + [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, 1192 + [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, 1193 + [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, 1194 + [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, 1195 + [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, 1196 + [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, 1338 1197 [NR_CLKS] = NULL, 1339 1198 }, 1340 1199 .num = NR_CLKS, ··· 1467 1308 [CLKID_32K_CLK] = &gxbb_32k_clk.hw, 1468 1309 [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, 1469 1310 [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, 1311 + [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, 1312 + [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, 1313 + [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, 1314 + [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, 1315 + [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, 1316 + [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, 1317 + [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, 1318 + [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, 1319 + [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, 1470 1320 [NR_CLKS] = NULL, 1471 1321 }, 1472 1322 .num = NR_CLKS, ··· 1592 1424 &gxbb_cts_amclk, 1593 1425 &gxbb_cts_mclk_i958, 1594 1426 &gxbb_32k_clk, 1427 + &gxbb_sd_emmc_a_clk0, 1428 + &gxbb_sd_emmc_b_clk0, 1429 + &gxbb_sd_emmc_c_clk0, 1595 1430 }; 1596 1431 1597 1432 static struct clk_mux *const gxbb_clk_muxes[] = { ··· 1607 1436 &gxbb_cts_mclk_i958_sel, 1608 1437 &gxbb_cts_i958, 1609 1438 &gxbb_32k_clk_sel, 1439 + &gxbb_sd_emmc_a_clk0_sel, 1440 + &gxbb_sd_emmc_b_clk0_sel, 1441 + &gxbb_sd_emmc_c_clk0_sel, 1610 1442 }; 1611 1443 1612 1444 static struct clk_divider *const gxbb_clk_dividers[] = { ··· 1619 1445 &gxbb_mali_1_div, 1620 1446 &gxbb_cts_mclk_i958_div, 1621 1447 &gxbb_32k_clk_div, 1448 + &gxbb_sd_emmc_a_clk0_div, 1449 + &gxbb_sd_emmc_b_clk0_div, 1450 + &gxbb_sd_emmc_c_clk0_div, 1622 1451 }; 1623 1452 1624 1453 static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {