6
6
* Author: Lars-Peter Clausen <[email protected] >
7
7
*/
8
8
9
+ #include <linux/adi-axi-common.h>
10
+ #include <linux/bits.h>
9
11
#include <linux/platform_device.h>
10
12
#include <linux/clk.h>
11
13
#include <linux/clk-provider.h>
29
31
30
32
#define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16)
31
33
34
+ #define ADI_CLKGEN_REG_FPGA_VOLTAGE 0x0140
35
+ #define ADI_CLKGEN_INFO_FPGA_VOLTAGE (val ) ((val) & GENMASK(15, 0))
36
+
32
37
#define MMCM_REG_CLKOUT5_2 0x07
33
38
#define MMCM_REG_CLKOUT0_1 0x08
34
39
#define MMCM_REG_CLKOUT0_2 0x09
@@ -497,6 +502,54 @@ static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw)
497
502
return parent ;
498
503
}
499
504
505
+ static int axi_clkgen_setup_limits (struct axi_clkgen * axi_clkgen ,
506
+ struct device * dev )
507
+ {
508
+ unsigned int tech , family , speed_grade , reg_value ;
509
+
510
+ axi_clkgen_read (axi_clkgen , ADI_AXI_REG_FPGA_INFO , & reg_value );
511
+ tech = ADI_AXI_INFO_FPGA_TECH (reg_value );
512
+ family = ADI_AXI_INFO_FPGA_FAMILY (reg_value );
513
+ speed_grade = ADI_AXI_INFO_FPGA_SPEED_GRADE (reg_value );
514
+
515
+ axi_clkgen -> limits .fpfd_min = 10000 ;
516
+ axi_clkgen -> limits .fvco_min = 600000 ;
517
+
518
+ switch (speed_grade ) {
519
+ case ADI_AXI_FPGA_SPEED_1 ... ADI_AXI_FPGA_SPEED_1LV :
520
+ axi_clkgen -> limits .fvco_max = 1200000 ;
521
+ axi_clkgen -> limits .fpfd_max = 450000 ;
522
+ break ;
523
+ case ADI_AXI_FPGA_SPEED_2 ... ADI_AXI_FPGA_SPEED_2LV :
524
+ axi_clkgen -> limits .fvco_max = 1440000 ;
525
+ axi_clkgen -> limits .fpfd_max = 500000 ;
526
+ if (family == ADI_AXI_FPGA_FAMILY_KINTEX || family == ADI_AXI_FPGA_FAMILY_ARTIX ) {
527
+ axi_clkgen_read (axi_clkgen , ADI_CLKGEN_REG_FPGA_VOLTAGE ,
528
+ & reg_value );
529
+ if (ADI_CLKGEN_INFO_FPGA_VOLTAGE (reg_value ) < 950 ) {
530
+ axi_clkgen -> limits .fvco_max = 1200000 ;
531
+ axi_clkgen -> limits .fpfd_max = 450000 ;
532
+ }
533
+ }
534
+ break ;
535
+ case ADI_AXI_FPGA_SPEED_3 :
536
+ axi_clkgen -> limits .fvco_max = 1600000 ;
537
+ axi_clkgen -> limits .fpfd_max = 550000 ;
538
+ break ;
539
+ default :
540
+ return dev_err_probe (dev , - ENODEV , "Unknown speed grade %d\n" ,
541
+ speed_grade );
542
+ };
543
+
544
+ /* Overwrite vco limits for ultrascale+ */
545
+ if (tech == ADI_AXI_FPGA_TECH_ULTRASCALE_PLUS ) {
546
+ axi_clkgen -> limits .fvco_max = 1600000 ;
547
+ axi_clkgen -> limits .fvco_min = 800000 ;
548
+ }
549
+
550
+ return 0 ;
551
+ }
552
+
500
553
static const struct clk_ops axi_clkgen_ops = {
501
554
.recalc_rate = axi_clkgen_recalc_rate ,
502
555
.determine_rate = axi_clkgen_determine_rate ,
@@ -511,6 +564,7 @@ static int axi_clkgen_probe(struct platform_device *pdev)
511
564
{
512
565
const struct axi_clkgen_limits * dflt_limits ;
513
566
struct axi_clkgen * axi_clkgen ;
567
+ unsigned int pcore_version ;
514
568
struct clk_init_data init ;
515
569
const char * parent_names [2 ];
516
570
const char * clk_name ;
@@ -556,7 +610,16 @@ static int axi_clkgen_probe(struct platform_device *pdev)
556
610
return - EINVAL ;
557
611
}
558
612
559
- memcpy (& axi_clkgen -> limits , dflt_limits , sizeof (axi_clkgen -> limits ));
613
+ axi_clkgen_read (axi_clkgen , ADI_AXI_REG_VERSION , & pcore_version );
614
+
615
+ if (ADI_AXI_PCORE_VER_MAJOR (pcore_version ) > 0x04 ) {
616
+ ret = axi_clkgen_setup_limits (axi_clkgen , & pdev -> dev );
617
+ if (ret )
618
+ return ret ;
619
+ } else {
620
+ memcpy (& axi_clkgen -> limits , dflt_limits ,
621
+ sizeof (axi_clkgen -> limits ));
622
+ }
560
623
561
624
clk_name = pdev -> dev .of_node -> name ;
562
625
of_property_read_string (pdev -> dev .of_node , "clock-output-names" ,
0 commit comments