MLK-21987-1 soc: imx: Add speed grading fuse check for i.MX8MN
authorAnson Huang <Anson.Huang@nxp.com>
Mon, 10 Jun 2019 01:56:16 +0000 (09:56 +0800)
committerAbel Vesa <abel.vesa@nxp.com>
Thu, 27 Jun 2019 10:52:25 +0000 (13:52 +0300)
Add speed grading fuse check to constrain CPU OPP according
to market segment and speed grading fuse map,

Market_Segment[1:0]:
'00' - Consumer 0C to 95C
'01' - Ext. Consumer -20C to 105C
'10' - Industrial -40C to 105C
'11' - Automotive -40C to 125C

SPEED_GRADING[5:0]:
SPEED_GRADE[5:4]    SPEED_GRADE[3:0]    MHz
      xx                0000            2300
      xx                0001            2200
      xx                0010            2100
      xx                0011            2000
      xx                0100            1900
      xx                0101            1800
      xx                0110            1700
      xx                0111            1600
      xx                1000            1500
      xx                1001            1400
      xx                1010            1300
      xx                1011            1200
      xx                1100            1100
      xx                1101            1000
      xx                1110             900
      xx                1111             800

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Reviewed-by: Bai Ping <ping.bai@nxp.com>
drivers/soc/imx/soc-imx8.c

index 03363c9..8368b44 100644 (file)
@@ -357,6 +357,10 @@ device_initcall(imx8_soc_init);
 #define OCOTP_CFG3                     0x440
 #define OCOTP_CFG3_SPEED_GRADING_SHIFT 8
 #define OCOTP_CFG3_SPEED_GRADING_MASK  (0x7 << 8)
+#define OCOTP_CFG3_SPEED_GRADING_IMX8MN_MASK   (0x3F << 8)
+#define OCOTP_CFG3_SPEED_IMX8MN_1P5GHZ 0x8
+#define OCOTP_CFG3_SPEED_IMX8MN_1P4GHZ 0x9
+#define OCOTP_CFG3_SPEED_IMX8MN_1P2GHZ 0xb
 #define OCOTP_CFG3_SPEED_2GHZ          4
 #define OCOTP_CFG3_SPEED_1P8GHZ                3
 #define OCOTP_CFG3_SPEED_1P6GHZ                2
@@ -485,6 +489,57 @@ put_node:
        of_node_put(np);
 }
 
+static void __init imx8mn_opp_check_speed_grading(struct device *cpu_dev)
+{
+       struct device_node *np;
+       void __iomem *base;
+       u32 val, market;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
+       if (!np) {
+               pr_warn("failed to find ocotp node\n");
+               return;
+       }
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_warn("failed to map ocotp\n");
+               goto put_node;
+       }
+       val = readl_relaxed(base + OCOTP_CFG3);
+       /* market segment bit[7:6] */
+       market = (val & OCOTP_CFG3_MKT_SEGMENT_MASK)
+               >> OCOTP_CFG3_MKT_SEGMENT_SHIFT;
+       /* speed grading bit[13:8] */
+       val = (val & OCOTP_CFG3_SPEED_GRADING_IMX8MN_MASK)
+               >> OCOTP_CFG3_SPEED_GRADING_SHIFT;
+
+       switch (market) {
+       case OCOTP_CFG3_CONSUMER:
+               if (val > OCOTP_CFG3_SPEED_IMX8MN_1P5GHZ)
+                       if (dev_pm_opp_disable(cpu_dev, 1500000000))
+                               pr_warn("failed to disable 1.5GHz OPP!\n");
+               if (val > OCOTP_CFG3_SPEED_IMX8MN_1P4GHZ)
+                       if (dev_pm_opp_disable(cpu_dev, 1400000000))
+                               pr_warn("failed to disable 1.4GHz OPP!\n");
+               break;
+       case OCOTP_CFG3_INDUSTRIAL:
+               if (dev_pm_opp_disable(cpu_dev, 1500000000))
+                       pr_warn("failed to disable 1.5GHz OPP!\n");
+               if (val > OCOTP_CFG3_SPEED_IMX8MN_1P4GHZ)
+                       if (dev_pm_opp_disable(cpu_dev, 1400000000))
+                               pr_warn("failed to disable 1.4GHz OPP!\n");
+               break;
+       default:
+               break;
+       }
+
+       iounmap(base);
+
+put_node:
+       of_node_put(np);
+}
+
 static void __init imx8mq_opp_init(void)
 {
        struct device_node *np;
@@ -509,6 +564,8 @@ static void __init imx8mq_opp_init(void)
                imx8mq_opp_check_speed_grading(cpu_dev);
        else if (of_machine_is_compatible("fsl,imx8mm"))
                imx8mm_opp_check_speed_grading(cpu_dev);
+       else if (of_machine_is_compatible("fsl,imx8mn"))
+               imx8mn_opp_check_speed_grading(cpu_dev);
 
 put_node:
        of_node_put(np);