1*9d13c7bbSTaniya Das // SPDX-License-Identifier: GPL-2.0-only 2*9d13c7bbSTaniya Das /* 3*9d13c7bbSTaniya Das * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4*9d13c7bbSTaniya Das */ 5*9d13c7bbSTaniya Das 6*9d13c7bbSTaniya Das #include <linux/clk-provider.h> 7*9d13c7bbSTaniya Das #include <linux/mod_devicetable.h> 8*9d13c7bbSTaniya Das #include <linux/module.h> 9*9d13c7bbSTaniya Das #include <linux/platform_device.h> 10*9d13c7bbSTaniya Das #include <linux/regmap.h> 11*9d13c7bbSTaniya Das 12*9d13c7bbSTaniya Das #include <dt-bindings/clock/qcom,nord-tcsrcc.h> 13*9d13c7bbSTaniya Das 14*9d13c7bbSTaniya Das #include "clk-alpha-pll.h" 15*9d13c7bbSTaniya Das #include "clk-branch.h" 16*9d13c7bbSTaniya Das #include "clk-pll.h" 17*9d13c7bbSTaniya Das #include "clk-rcg.h" 18*9d13c7bbSTaniya Das #include "clk-regmap.h" 19*9d13c7bbSTaniya Das #include "clk-regmap-divider.h" 20*9d13c7bbSTaniya Das #include "clk-regmap-mux.h" 21*9d13c7bbSTaniya Das #include "common.h" 22*9d13c7bbSTaniya Das #include "reset.h" 23*9d13c7bbSTaniya Das 24*9d13c7bbSTaniya Das enum { 25*9d13c7bbSTaniya Das DT_BI_TCXO_PAD, 26*9d13c7bbSTaniya Das }; 27*9d13c7bbSTaniya Das 28*9d13c7bbSTaniya Das static struct clk_branch tcsr_dp_rx_0_clkref_en = { 29*9d13c7bbSTaniya Das .halt_reg = 0xa008, 30*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 31*9d13c7bbSTaniya Das .clkr = { 32*9d13c7bbSTaniya Das .enable_reg = 0xa008, 33*9d13c7bbSTaniya Das .enable_mask = BIT(0), 34*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 35*9d13c7bbSTaniya Das .name = "tcsr_dp_rx_0_clkref_en", 36*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 37*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 38*9d13c7bbSTaniya Das }, 39*9d13c7bbSTaniya Das .num_parents = 1, 40*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 41*9d13c7bbSTaniya Das }, 42*9d13c7bbSTaniya Das }, 43*9d13c7bbSTaniya Das }; 44*9d13c7bbSTaniya Das 45*9d13c7bbSTaniya Das static struct clk_branch tcsr_dp_rx_1_clkref_en = { 46*9d13c7bbSTaniya Das .halt_reg = 0xb008, 47*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 48*9d13c7bbSTaniya Das .clkr = { 49*9d13c7bbSTaniya Das .enable_reg = 0xb008, 50*9d13c7bbSTaniya Das .enable_mask = BIT(0), 51*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 52*9d13c7bbSTaniya Das .name = "tcsr_dp_rx_1_clkref_en", 53*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 54*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 55*9d13c7bbSTaniya Das }, 56*9d13c7bbSTaniya Das .num_parents = 1, 57*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 58*9d13c7bbSTaniya Das }, 59*9d13c7bbSTaniya Das }, 60*9d13c7bbSTaniya Das }; 61*9d13c7bbSTaniya Das 62*9d13c7bbSTaniya Das static struct clk_branch tcsr_dp_tx_0_clkref_en = { 63*9d13c7bbSTaniya Das .halt_reg = 0xc008, 64*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 65*9d13c7bbSTaniya Das .clkr = { 66*9d13c7bbSTaniya Das .enable_reg = 0xc008, 67*9d13c7bbSTaniya Das .enable_mask = BIT(0), 68*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 69*9d13c7bbSTaniya Das .name = "tcsr_dp_tx_0_clkref_en", 70*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 71*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 72*9d13c7bbSTaniya Das }, 73*9d13c7bbSTaniya Das .num_parents = 1, 74*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 75*9d13c7bbSTaniya Das }, 76*9d13c7bbSTaniya Das }, 77*9d13c7bbSTaniya Das }; 78*9d13c7bbSTaniya Das 79*9d13c7bbSTaniya Das static struct clk_branch tcsr_dp_tx_1_clkref_en = { 80*9d13c7bbSTaniya Das .halt_reg = 0xd008, 81*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 82*9d13c7bbSTaniya Das .clkr = { 83*9d13c7bbSTaniya Das .enable_reg = 0xd008, 84*9d13c7bbSTaniya Das .enable_mask = BIT(0), 85*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 86*9d13c7bbSTaniya Das .name = "tcsr_dp_tx_1_clkref_en", 87*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 88*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 89*9d13c7bbSTaniya Das }, 90*9d13c7bbSTaniya Das .num_parents = 1, 91*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 92*9d13c7bbSTaniya Das }, 93*9d13c7bbSTaniya Das }, 94*9d13c7bbSTaniya Das }; 95*9d13c7bbSTaniya Das 96*9d13c7bbSTaniya Das static struct clk_branch tcsr_dp_tx_2_clkref_en = { 97*9d13c7bbSTaniya Das .halt_reg = 0xe008, 98*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 99*9d13c7bbSTaniya Das .clkr = { 100*9d13c7bbSTaniya Das .enable_reg = 0xe008, 101*9d13c7bbSTaniya Das .enable_mask = BIT(0), 102*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 103*9d13c7bbSTaniya Das .name = "tcsr_dp_tx_2_clkref_en", 104*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 105*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 106*9d13c7bbSTaniya Das }, 107*9d13c7bbSTaniya Das .num_parents = 1, 108*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 109*9d13c7bbSTaniya Das }, 110*9d13c7bbSTaniya Das }, 111*9d13c7bbSTaniya Das }; 112*9d13c7bbSTaniya Das 113*9d13c7bbSTaniya Das static struct clk_branch tcsr_dp_tx_3_clkref_en = { 114*9d13c7bbSTaniya Das .halt_reg = 0xf008, 115*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 116*9d13c7bbSTaniya Das .clkr = { 117*9d13c7bbSTaniya Das .enable_reg = 0xf008, 118*9d13c7bbSTaniya Das .enable_mask = BIT(0), 119*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 120*9d13c7bbSTaniya Das .name = "tcsr_dp_tx_3_clkref_en", 121*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 122*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 123*9d13c7bbSTaniya Das }, 124*9d13c7bbSTaniya Das .num_parents = 1, 125*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 126*9d13c7bbSTaniya Das }, 127*9d13c7bbSTaniya Das }, 128*9d13c7bbSTaniya Das }; 129*9d13c7bbSTaniya Das 130*9d13c7bbSTaniya Das static struct clk_branch tcsr_pcie_clkref_en = { 131*9d13c7bbSTaniya Das .halt_reg = 0x8, 132*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 133*9d13c7bbSTaniya Das .clkr = { 134*9d13c7bbSTaniya Das .enable_reg = 0x8, 135*9d13c7bbSTaniya Das .enable_mask = BIT(0), 136*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 137*9d13c7bbSTaniya Das .name = "tcsr_pcie_clkref_en", 138*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 139*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 140*9d13c7bbSTaniya Das }, 141*9d13c7bbSTaniya Das .num_parents = 1, 142*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 143*9d13c7bbSTaniya Das }, 144*9d13c7bbSTaniya Das }, 145*9d13c7bbSTaniya Das }; 146*9d13c7bbSTaniya Das 147*9d13c7bbSTaniya Das static struct clk_branch tcsr_ufs_clkref_en = { 148*9d13c7bbSTaniya Das .halt_reg = 0x3008, 149*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 150*9d13c7bbSTaniya Das .clkr = { 151*9d13c7bbSTaniya Das .enable_reg = 0x3008, 152*9d13c7bbSTaniya Das .enable_mask = BIT(0), 153*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 154*9d13c7bbSTaniya Das .name = "tcsr_ufs_clkref_en", 155*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 156*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 157*9d13c7bbSTaniya Das }, 158*9d13c7bbSTaniya Das .num_parents = 1, 159*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 160*9d13c7bbSTaniya Das }, 161*9d13c7bbSTaniya Das }, 162*9d13c7bbSTaniya Das }; 163*9d13c7bbSTaniya Das 164*9d13c7bbSTaniya Das static struct clk_branch tcsr_usb2_0_clkref_en = { 165*9d13c7bbSTaniya Das .halt_reg = 0x4008, 166*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 167*9d13c7bbSTaniya Das .clkr = { 168*9d13c7bbSTaniya Das .enable_reg = 0x4008, 169*9d13c7bbSTaniya Das .enable_mask = BIT(0), 170*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 171*9d13c7bbSTaniya Das .name = "tcsr_usb2_0_clkref_en", 172*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 173*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 174*9d13c7bbSTaniya Das }, 175*9d13c7bbSTaniya Das .num_parents = 1, 176*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 177*9d13c7bbSTaniya Das }, 178*9d13c7bbSTaniya Das }, 179*9d13c7bbSTaniya Das }; 180*9d13c7bbSTaniya Das 181*9d13c7bbSTaniya Das static struct clk_branch tcsr_usb2_1_clkref_en = { 182*9d13c7bbSTaniya Das .halt_reg = 0x5008, 183*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 184*9d13c7bbSTaniya Das .clkr = { 185*9d13c7bbSTaniya Das .enable_reg = 0x5008, 186*9d13c7bbSTaniya Das .enable_mask = BIT(0), 187*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 188*9d13c7bbSTaniya Das .name = "tcsr_usb2_1_clkref_en", 189*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 190*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 191*9d13c7bbSTaniya Das }, 192*9d13c7bbSTaniya Das .num_parents = 1, 193*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 194*9d13c7bbSTaniya Das }, 195*9d13c7bbSTaniya Das }, 196*9d13c7bbSTaniya Das }; 197*9d13c7bbSTaniya Das 198*9d13c7bbSTaniya Das static struct clk_branch tcsr_usb2_2_clkref_en = { 199*9d13c7bbSTaniya Das .halt_reg = 0x6008, 200*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 201*9d13c7bbSTaniya Das .clkr = { 202*9d13c7bbSTaniya Das .enable_reg = 0x6008, 203*9d13c7bbSTaniya Das .enable_mask = BIT(0), 204*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 205*9d13c7bbSTaniya Das .name = "tcsr_usb2_2_clkref_en", 206*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 207*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 208*9d13c7bbSTaniya Das }, 209*9d13c7bbSTaniya Das .num_parents = 1, 210*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 211*9d13c7bbSTaniya Das }, 212*9d13c7bbSTaniya Das }, 213*9d13c7bbSTaniya Das }; 214*9d13c7bbSTaniya Das 215*9d13c7bbSTaniya Das static struct clk_branch tcsr_usb3_0_clkref_en = { 216*9d13c7bbSTaniya Das .halt_reg = 0x8008, 217*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 218*9d13c7bbSTaniya Das .clkr = { 219*9d13c7bbSTaniya Das .enable_reg = 0x8008, 220*9d13c7bbSTaniya Das .enable_mask = BIT(0), 221*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 222*9d13c7bbSTaniya Das .name = "tcsr_usb3_0_clkref_en", 223*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 224*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 225*9d13c7bbSTaniya Das }, 226*9d13c7bbSTaniya Das .num_parents = 1, 227*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 228*9d13c7bbSTaniya Das }, 229*9d13c7bbSTaniya Das }, 230*9d13c7bbSTaniya Das }; 231*9d13c7bbSTaniya Das 232*9d13c7bbSTaniya Das static struct clk_branch tcsr_usb3_1_clkref_en = { 233*9d13c7bbSTaniya Das .halt_reg = 0x7008, 234*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 235*9d13c7bbSTaniya Das .clkr = { 236*9d13c7bbSTaniya Das .enable_reg = 0x7008, 237*9d13c7bbSTaniya Das .enable_mask = BIT(0), 238*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 239*9d13c7bbSTaniya Das .name = "tcsr_usb3_1_clkref_en", 240*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 241*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 242*9d13c7bbSTaniya Das }, 243*9d13c7bbSTaniya Das .num_parents = 1, 244*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 245*9d13c7bbSTaniya Das }, 246*9d13c7bbSTaniya Das }, 247*9d13c7bbSTaniya Das }; 248*9d13c7bbSTaniya Das 249*9d13c7bbSTaniya Das static struct clk_branch tcsr_ux_sgmii_0_clkref_en = { 250*9d13c7bbSTaniya Das .halt_reg = 0x1008, 251*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 252*9d13c7bbSTaniya Das .clkr = { 253*9d13c7bbSTaniya Das .enable_reg = 0x1008, 254*9d13c7bbSTaniya Das .enable_mask = BIT(0), 255*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 256*9d13c7bbSTaniya Das .name = "tcsr_ux_sgmii_0_clkref_en", 257*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 258*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 259*9d13c7bbSTaniya Das }, 260*9d13c7bbSTaniya Das .num_parents = 1, 261*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 262*9d13c7bbSTaniya Das }, 263*9d13c7bbSTaniya Das }, 264*9d13c7bbSTaniya Das }; 265*9d13c7bbSTaniya Das 266*9d13c7bbSTaniya Das static struct clk_branch tcsr_ux_sgmii_1_clkref_en = { 267*9d13c7bbSTaniya Das .halt_reg = 0x2008, 268*9d13c7bbSTaniya Das .halt_check = BRANCH_HALT_DELAY, 269*9d13c7bbSTaniya Das .clkr = { 270*9d13c7bbSTaniya Das .enable_reg = 0x2008, 271*9d13c7bbSTaniya Das .enable_mask = BIT(0), 272*9d13c7bbSTaniya Das .hw.init = &(const struct clk_init_data) { 273*9d13c7bbSTaniya Das .name = "tcsr_ux_sgmii_1_clkref_en", 274*9d13c7bbSTaniya Das .parent_data = &(const struct clk_parent_data){ 275*9d13c7bbSTaniya Das .index = DT_BI_TCXO_PAD, 276*9d13c7bbSTaniya Das }, 277*9d13c7bbSTaniya Das .num_parents = 1, 278*9d13c7bbSTaniya Das .ops = &clk_branch2_ops, 279*9d13c7bbSTaniya Das }, 280*9d13c7bbSTaniya Das }, 281*9d13c7bbSTaniya Das }; 282*9d13c7bbSTaniya Das 283*9d13c7bbSTaniya Das static struct clk_regmap *tcsr_cc_nord_clocks[] = { 284*9d13c7bbSTaniya Das [TCSR_DP_RX_0_CLKREF_EN] = &tcsr_dp_rx_0_clkref_en.clkr, 285*9d13c7bbSTaniya Das [TCSR_DP_RX_1_CLKREF_EN] = &tcsr_dp_rx_1_clkref_en.clkr, 286*9d13c7bbSTaniya Das [TCSR_DP_TX_0_CLKREF_EN] = &tcsr_dp_tx_0_clkref_en.clkr, 287*9d13c7bbSTaniya Das [TCSR_DP_TX_1_CLKREF_EN] = &tcsr_dp_tx_1_clkref_en.clkr, 288*9d13c7bbSTaniya Das [TCSR_DP_TX_2_CLKREF_EN] = &tcsr_dp_tx_2_clkref_en.clkr, 289*9d13c7bbSTaniya Das [TCSR_DP_TX_3_CLKREF_EN] = &tcsr_dp_tx_3_clkref_en.clkr, 290*9d13c7bbSTaniya Das [TCSR_PCIE_CLKREF_EN] = &tcsr_pcie_clkref_en.clkr, 291*9d13c7bbSTaniya Das [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 292*9d13c7bbSTaniya Das [TCSR_USB2_0_CLKREF_EN] = &tcsr_usb2_0_clkref_en.clkr, 293*9d13c7bbSTaniya Das [TCSR_USB2_1_CLKREF_EN] = &tcsr_usb2_1_clkref_en.clkr, 294*9d13c7bbSTaniya Das [TCSR_USB2_2_CLKREF_EN] = &tcsr_usb2_2_clkref_en.clkr, 295*9d13c7bbSTaniya Das [TCSR_USB3_0_CLKREF_EN] = &tcsr_usb3_0_clkref_en.clkr, 296*9d13c7bbSTaniya Das [TCSR_USB3_1_CLKREF_EN] = &tcsr_usb3_1_clkref_en.clkr, 297*9d13c7bbSTaniya Das [TCSR_UX_SGMII_0_CLKREF_EN] = &tcsr_ux_sgmii_0_clkref_en.clkr, 298*9d13c7bbSTaniya Das [TCSR_UX_SGMII_1_CLKREF_EN] = &tcsr_ux_sgmii_1_clkref_en.clkr, 299*9d13c7bbSTaniya Das }; 300*9d13c7bbSTaniya Das 301*9d13c7bbSTaniya Das static const struct regmap_config tcsr_cc_nord_regmap_config = { 302*9d13c7bbSTaniya Das .reg_bits = 32, 303*9d13c7bbSTaniya Das .reg_stride = 4, 304*9d13c7bbSTaniya Das .val_bits = 32, 305*9d13c7bbSTaniya Das .max_register = 0xf008, 306*9d13c7bbSTaniya Das .fast_io = true, 307*9d13c7bbSTaniya Das }; 308*9d13c7bbSTaniya Das 309*9d13c7bbSTaniya Das static const struct qcom_cc_desc tcsr_cc_nord_desc = { 310*9d13c7bbSTaniya Das .config = &tcsr_cc_nord_regmap_config, 311*9d13c7bbSTaniya Das .clks = tcsr_cc_nord_clocks, 312*9d13c7bbSTaniya Das .num_clks = ARRAY_SIZE(tcsr_cc_nord_clocks), 313*9d13c7bbSTaniya Das }; 314*9d13c7bbSTaniya Das 315*9d13c7bbSTaniya Das static const struct of_device_id tcsr_cc_nord_match_table[] = { 316*9d13c7bbSTaniya Das { .compatible = "qcom,nord-tcsrcc" }, 317*9d13c7bbSTaniya Das { } 318*9d13c7bbSTaniya Das }; 319*9d13c7bbSTaniya Das MODULE_DEVICE_TABLE(of, tcsr_cc_nord_match_table); 320*9d13c7bbSTaniya Das 321*9d13c7bbSTaniya Das static int tcsr_cc_nord_probe(struct platform_device *pdev) 322*9d13c7bbSTaniya Das { 323*9d13c7bbSTaniya Das return qcom_cc_probe(pdev, &tcsr_cc_nord_desc); 324*9d13c7bbSTaniya Das } 325*9d13c7bbSTaniya Das 326*9d13c7bbSTaniya Das static struct platform_driver tcsr_cc_nord_driver = { 327*9d13c7bbSTaniya Das .probe = tcsr_cc_nord_probe, 328*9d13c7bbSTaniya Das .driver = { 329*9d13c7bbSTaniya Das .name = "tcsrcc-nord", 330*9d13c7bbSTaniya Das .of_match_table = tcsr_cc_nord_match_table, 331*9d13c7bbSTaniya Das }, 332*9d13c7bbSTaniya Das }; 333*9d13c7bbSTaniya Das 334*9d13c7bbSTaniya Das module_platform_driver(tcsr_cc_nord_driver); 335*9d13c7bbSTaniya Das 336*9d13c7bbSTaniya Das MODULE_DESCRIPTION("QTI TCSRCC NORD Driver"); 337*9d13c7bbSTaniya Das MODULE_LICENSE("GPL"); 338