@@ -156,6 +156,7 @@ struct meson_spicc_device {
156156 void __iomem * base ;
157157 struct clk * core ;
158158 struct clk * pclk ;
159+ struct clk_divider pow2_div ;
159160 struct clk * clk ;
160161 struct spi_message * message ;
161162 struct spi_transfer * xfer ;
@@ -168,6 +169,8 @@ struct meson_spicc_device {
168169 unsigned long xfer_remain ;
169170};
170171
172+ #define pow2_clk_to_spicc (_div ) container_of(_div, struct meson_spicc_device, pow2_div)
173+
171174static void meson_spicc_oen_enable (struct meson_spicc_device * spicc )
172175{
173176 u32 conf ;
@@ -421,7 +424,7 @@ static int meson_spicc_prepare_message(struct spi_master *master,
421424{
422425 struct meson_spicc_device * spicc = spi_master_get_devdata (master );
423426 struct spi_device * spi = message -> spi ;
424- u32 conf = 0 ;
427+ u32 conf = readl_relaxed ( spicc -> base + SPICC_CONREG ) & SPICC_DATARATE_MASK ;
425428
426429 /* Store current message */
427430 spicc -> message = message ;
@@ -458,8 +461,6 @@ static int meson_spicc_prepare_message(struct spi_master *master,
458461 /* Select CS */
459462 conf |= FIELD_PREP (SPICC_CS_MASK , spi -> chip_select );
460463
461- /* Default Clock rate core/4 */
462-
463464 /* Default 8bit word */
464465 conf |= FIELD_PREP (SPICC_BITLENGTH_MASK , 8 - 1 );
465466
@@ -476,12 +477,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
476477static int meson_spicc_unprepare_transfer (struct spi_master * master )
477478{
478479 struct meson_spicc_device * spicc = spi_master_get_devdata (master );
480+ u32 conf = readl_relaxed (spicc -> base + SPICC_CONREG ) & SPICC_DATARATE_MASK ;
479481
480482 /* Disable all IRQs */
481483 writel (0 , spicc -> base + SPICC_INTREG );
482484
483485 device_reset_optional (& spicc -> pdev -> dev );
484486
487+ /* Set default configuration, keeping datarate field */
488+ writel_relaxed (conf , spicc -> base + SPICC_CONREG );
489+
485490 return 0 ;
486491}
487492
@@ -518,14 +523,60 @@ static void meson_spicc_cleanup(struct spi_device *spi)
518523 * Clk path for G12A series:
519524 * pclk -> pow2 fixed div -> pow2 div -> mux -> out
520525 * pclk -> enh fixed div -> enh div -> mux -> out
526+ *
527+ * The pow2 divider is tied to the controller HW state, and the
528+ * divider is only valid when the controller is initialized.
529+ *
530+ * A set of clock ops is added to make sure we don't read/set this
531+ * clock rate while the controller is in an unknown state.
521532 */
522533
523- static int meson_spicc_clk_init (struct meson_spicc_device * spicc )
534+ static unsigned long meson_spicc_pow2_recalc_rate (struct clk_hw * hw ,
535+ unsigned long parent_rate )
536+ {
537+ struct clk_divider * divider = to_clk_divider (hw );
538+ struct meson_spicc_device * spicc = pow2_clk_to_spicc (divider );
539+
540+ if (!spicc -> master -> cur_msg || !spicc -> master -> busy )
541+ return 0 ;
542+
543+ return clk_divider_ops .recalc_rate (hw , parent_rate );
544+ }
545+
546+ static int meson_spicc_pow2_determine_rate (struct clk_hw * hw ,
547+ struct clk_rate_request * req )
548+ {
549+ struct clk_divider * divider = to_clk_divider (hw );
550+ struct meson_spicc_device * spicc = pow2_clk_to_spicc (divider );
551+
552+ if (!spicc -> master -> cur_msg || !spicc -> master -> busy )
553+ return - EINVAL ;
554+
555+ return clk_divider_ops .determine_rate (hw , req );
556+ }
557+
558+ static int meson_spicc_pow2_set_rate (struct clk_hw * hw , unsigned long rate ,
559+ unsigned long parent_rate )
560+ {
561+ struct clk_divider * divider = to_clk_divider (hw );
562+ struct meson_spicc_device * spicc = pow2_clk_to_spicc (divider );
563+
564+ if (!spicc -> master -> cur_msg || !spicc -> master -> busy )
565+ return - EINVAL ;
566+
567+ return clk_divider_ops .set_rate (hw , rate , parent_rate );
568+ }
569+
570+ const struct clk_ops meson_spicc_pow2_clk_ops = {
571+ .recalc_rate = meson_spicc_pow2_recalc_rate ,
572+ .determine_rate = meson_spicc_pow2_determine_rate ,
573+ .set_rate = meson_spicc_pow2_set_rate ,
574+ };
575+
576+ static int meson_spicc_pow2_clk_init (struct meson_spicc_device * spicc )
524577{
525578 struct device * dev = & spicc -> pdev -> dev ;
526- struct clk_fixed_factor * pow2_fixed_div , * enh_fixed_div ;
527- struct clk_divider * pow2_div , * enh_div ;
528- struct clk_mux * mux ;
579+ struct clk_fixed_factor * pow2_fixed_div ;
529580 struct clk_init_data init ;
530581 struct clk * clk ;
531582 struct clk_parent_data parent_data [2 ];
@@ -560,31 +611,45 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
560611 if (WARN_ON (IS_ERR (clk )))
561612 return PTR_ERR (clk );
562613
563- pow2_div = devm_kzalloc (dev , sizeof (* pow2_div ), GFP_KERNEL );
564- if (!pow2_div )
565- return - ENOMEM ;
566-
567614 snprintf (name , sizeof (name ), "%s#pow2_div" , dev_name (dev ));
568615 init .name = name ;
569- init .ops = & clk_divider_ops ;
570- init .flags = CLK_SET_RATE_PARENT ;
616+ init .ops = & meson_spicc_pow2_clk_ops ;
617+ /*
618+ * Set NOCACHE here to make sure we read the actual HW value
619+ * since we reset the HW after each transfer.
620+ */
621+ init .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE ;
571622 parent_data [0 ].hw = & pow2_fixed_div -> hw ;
572623 init .num_parents = 1 ;
573624
574- pow2_div -> shift = 16 ,
575- pow2_div -> width = 3 ,
576- pow2_div -> flags = CLK_DIVIDER_POWER_OF_TWO ,
577- pow2_div -> reg = spicc -> base + SPICC_CONREG ;
578- pow2_div -> hw .init = & init ;
625+ spicc -> pow2_div . shift = 16 ,
626+ spicc -> pow2_div . width = 3 ,
627+ spicc -> pow2_div . flags = CLK_DIVIDER_POWER_OF_TWO ,
628+ spicc -> pow2_div . reg = spicc -> base + SPICC_CONREG ;
629+ spicc -> pow2_div . hw .init = & init ;
579630
580- clk = devm_clk_register (dev , & pow2_div -> hw );
581- if (WARN_ON (IS_ERR (clk )))
582- return PTR_ERR (clk );
631+ spicc -> clk = devm_clk_register (dev , & spicc -> pow2_div . hw );
632+ if (WARN_ON (IS_ERR (spicc -> clk )))
633+ return PTR_ERR (spicc -> clk );
583634
584- if (!spicc -> data -> has_enhance_clk_div ) {
585- spicc -> clk = clk ;
586- return 0 ;
587- }
635+ return 0 ;
636+ }
637+
638+ static int meson_spicc_enh_clk_init (struct meson_spicc_device * spicc )
639+ {
640+ struct device * dev = & spicc -> pdev -> dev ;
641+ struct clk_fixed_factor * enh_fixed_div ;
642+ struct clk_divider * enh_div ;
643+ struct clk_mux * mux ;
644+ struct clk_init_data init ;
645+ struct clk * clk ;
646+ struct clk_parent_data parent_data [2 ];
647+ char name [64 ];
648+
649+ memset (& init , 0 , sizeof (init ));
650+ memset (& parent_data , 0 , sizeof (parent_data ));
651+
652+ init .parent_data = parent_data ;
588653
589654 /* algorithm for enh div: rate = freq / 2 / (N + 1) */
590655
@@ -637,7 +702,7 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
637702 snprintf (name , sizeof (name ), "%s#sel" , dev_name (dev ));
638703 init .name = name ;
639704 init .ops = & clk_mux_ops ;
640- parent_data [0 ].hw = & pow2_div -> hw ;
705+ parent_data [0 ].hw = & spicc -> pow2_div . hw ;
641706 parent_data [1 ].hw = & enh_div -> hw ;
642707 init .num_parents = 2 ;
643708 init .flags = CLK_SET_RATE_PARENT ;
@@ -754,12 +819,20 @@ static int meson_spicc_probe(struct platform_device *pdev)
754819
755820 meson_spicc_oen_enable (spicc );
756821
757- ret = meson_spicc_clk_init (spicc );
822+ ret = meson_spicc_pow2_clk_init (spicc );
758823 if (ret ) {
759- dev_err (& pdev -> dev , "clock registration failed\n" );
824+ dev_err (& pdev -> dev , "pow2 clock registration failed\n" );
760825 goto out_clk ;
761826 }
762827
828+ if (spicc -> data -> has_enhance_clk_div ) {
829+ ret = meson_spicc_enh_clk_init (spicc );
830+ if (ret ) {
831+ dev_err (& pdev -> dev , "clock registration failed\n" );
832+ goto out_clk ;
833+ }
834+ }
835+
763836 ret = devm_spi_register_master (& pdev -> dev , master );
764837 if (ret ) {
765838 dev_err (& pdev -> dev , "spi master registration failed\n" );
0 commit comments