9999#define MESON_MX_SDIO_RESPONSE_CRC16_BITS (16 - 1)
100100#define MESON_MX_SDIO_MAX_SLOTS 3
101101
102+ struct meson_mx_mmc_host_clkc {
103+ struct clk_divider cfg_div ;
104+ struct clk_fixed_factor fixed_div2 ;
105+ };
106+
102107struct meson_mx_mmc_host {
103108 struct device * controller_dev ;
104109
105- struct clk * parent_clk ;
106- struct clk_divider cfg_div ;
107110 struct clk * cfg_div_clk ;
108- struct clk_fixed_factor fixed_factor ;
109- struct clk * fixed_factor_clk ;
110-
111111 struct regmap * regmap ;
112112 int irq ;
113113 spinlock_t irq_lock ;
@@ -548,8 +548,7 @@ static int meson_mx_mmc_add_host(struct meson_mx_mmc_host *host)
548548
549549 /* Get the min and max supported clock rates */
550550 mmc -> f_min = clk_round_rate (host -> cfg_div_clk , 1 );
551- mmc -> f_max = clk_round_rate (host -> cfg_div_clk ,
552- clk_get_rate (host -> parent_clk ));
551+ mmc -> f_max = clk_round_rate (host -> cfg_div_clk , ULONG_MAX );
553552
554553 mmc -> caps |= MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY ;
555554 mmc -> ops = & meson_mx_mmc_ops ;
@@ -565,54 +564,62 @@ static int meson_mx_mmc_add_host(struct meson_mx_mmc_host *host)
565564 return 0 ;
566565}
567566
568- static int meson_mx_mmc_register_clks (struct meson_mx_mmc_host * host ,
569- void __iomem * base )
567+ static struct clk * meson_mx_mmc_register_clk (struct device * dev ,
568+ void __iomem * base )
570569{
571- struct clk_init_data init ;
572- const char * clk_div_parent , * clk_fixed_factor_parent ;
573-
574- clk_fixed_factor_parent = __clk_get_name (host -> parent_clk );
575- init .name = devm_kasprintf (host -> controller_dev , GFP_KERNEL ,
576- "%s#fixed_factor" ,
577- dev_name (host -> controller_dev ));
578- if (!init .name )
579- return - ENOMEM ;
570+ const char * fixed_div2_name , * cfg_div_name ;
571+ struct meson_mx_mmc_host_clkc * host_clkc ;
572+ struct clk * clk ;
573+ int ret ;
580574
581- init .ops = & clk_fixed_factor_ops ;
582- init .flags = 0 ;
583- init .parent_names = & clk_fixed_factor_parent ;
584- init .num_parents = 1 ;
585- host -> fixed_factor .div = 2 ;
586- host -> fixed_factor .mult = 1 ;
587- host -> fixed_factor .hw .init = & init ;
588-
589- host -> fixed_factor_clk = devm_clk_register (host -> controller_dev ,
590- & host -> fixed_factor .hw );
591- if (WARN_ON (IS_ERR (host -> fixed_factor_clk )))
592- return PTR_ERR (host -> fixed_factor_clk );
593-
594- clk_div_parent = __clk_get_name (host -> fixed_factor_clk );
595- init .name = devm_kasprintf (host -> controller_dev , GFP_KERNEL ,
596- "%s#div" , dev_name (host -> controller_dev ));
597- if (!init .name )
598- return - ENOMEM ;
575+ /* use a dedicated memory allocation for the clock controller to
576+ * prevent use-after-free as meson_mx_mmc_host is free'd before
577+ * dev (controller dev, not mmc_host->dev) is free'd.
578+ */
579+ host_clkc = devm_kzalloc (dev , sizeof (* host_clkc ), GFP_KERNEL );
580+ if (!host_clkc )
581+ return ERR_PTR (- ENOMEM );
582+
583+ fixed_div2_name = devm_kasprintf (dev , GFP_KERNEL , "%s#fixed_div2" ,
584+ dev_name (dev ));
585+ if (!fixed_div2_name )
586+ return ERR_PTR (- ENOMEM );
587+
588+ host_clkc -> fixed_div2 .div = 2 ;
589+ host_clkc -> fixed_div2 .mult = 1 ;
590+ host_clkc -> fixed_div2 .hw .init = CLK_HW_INIT_FW_NAME (fixed_div2_name ,
591+ "clkin" ,
592+ & clk_fixed_factor_ops ,
593+ 0 );
594+ ret = devm_clk_hw_register (dev , & host_clkc -> fixed_div2 .hw );
595+ if (ret )
596+ return dev_err_ptr_probe (dev , ret ,
597+ "Failed to register %s clock\n" ,
598+ fixed_div2_name );
599+
600+ cfg_div_name = devm_kasprintf (dev , GFP_KERNEL , "%s#div" , dev_name (dev ));
601+ if (!cfg_div_name )
602+ return ERR_PTR (- ENOMEM );
603+
604+ host_clkc -> cfg_div .reg = base + MESON_MX_SDIO_CONF ;
605+ host_clkc -> cfg_div .shift = MESON_MX_SDIO_CONF_CMD_CLK_DIV_SHIFT ;
606+ host_clkc -> cfg_div .width = MESON_MX_SDIO_CONF_CMD_CLK_DIV_WIDTH ;
607+ host_clkc -> cfg_div .hw .init = CLK_HW_INIT_HW (cfg_div_name ,
608+ & host_clkc -> fixed_div2 .hw ,
609+ & clk_divider_ops ,
610+ CLK_DIVIDER_ALLOW_ZERO );
611+ ret = devm_clk_hw_register (dev , & host_clkc -> cfg_div .hw );
612+ if (ret )
613+ return dev_err_ptr_probe (dev , ret ,
614+ "Failed to register %s clock\n" ,
615+ cfg_div_name );
599616
600- init .ops = & clk_divider_ops ;
601- init .flags = CLK_SET_RATE_PARENT ;
602- init .parent_names = & clk_div_parent ;
603- init .num_parents = 1 ;
604- host -> cfg_div .reg = base + MESON_MX_SDIO_CONF ;
605- host -> cfg_div .shift = MESON_MX_SDIO_CONF_CMD_CLK_DIV_SHIFT ;
606- host -> cfg_div .width = MESON_MX_SDIO_CONF_CMD_CLK_DIV_WIDTH ;
607- host -> cfg_div .hw .init = & init ;
608- host -> cfg_div .flags = CLK_DIVIDER_ALLOW_ZERO ;
609-
610- host -> cfg_div_clk = devm_clk_register (host -> controller_dev ,
611- & host -> cfg_div .hw );
612- if (WARN_ON (IS_ERR (host -> cfg_div_clk )))
613- return PTR_ERR (host -> cfg_div_clk );
617+ clk = devm_clk_hw_get_clk (dev , & host_clkc -> cfg_div .hw , "cfg_div_clk" );
618+ if (IS_ERR (clk ))
619+ return dev_err_ptr_probe (dev , PTR_ERR (clk ),
620+ "Failed to get the cfg_div clock\n" );
614621
615- return 0 ;
622+ return clk ;
616623}
617624
618625static int meson_mx_mmc_probe (struct platform_device * pdev )
@@ -682,16 +689,12 @@ static int meson_mx_mmc_probe(struct platform_device *pdev)
682689 goto error_free_mmc ;
683690 }
684691
685- host -> parent_clk = devm_clk_get ( host -> controller_dev , "clkin" );
686- if (IS_ERR (host -> parent_clk )) {
687- ret = PTR_ERR (host -> parent_clk );
692+ host -> cfg_div_clk = meson_mx_mmc_register_clk ( & pdev -> dev , base );
693+ if (IS_ERR (host -> cfg_div_clk )) {
694+ ret = PTR_ERR (host -> cfg_div_clk );
688695 goto error_free_mmc ;
689696 }
690697
691- ret = meson_mx_mmc_register_clks (host , base );
692- if (ret )
693- goto error_free_mmc ;
694-
695698 ret = clk_prepare_enable (host -> cfg_div_clk );
696699 if (ret ) {
697700 dev_err (host -> controller_dev , "Failed to enable MMC clock\n" );
0 commit comments