]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00252418 imx6: add fuse check for available devices
authorDong Aisheng <b29396@freescale.com>
Wed, 27 Feb 2013 08:50:30 +0000 (16:50 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:55 +0000 (08:35 +0200)
Since device availability may be different on the same SoC,
so we add fuse check for the supported device before we really
adding the device to the kernel.
This may avoid kernel crash once the CPU at the slot are changed to
a different one which with different device available but the kernel is
the same one.

Reviewed-by: Jason Liu <r64343@freescale.com>
Acked-by: Jason Liu <r64343@freescale.com>
Signed-off-by: Dong Aisheng <b29396@freescale.com>
14 files changed:
arch/arm/plat-mxc/Makefile
arch/arm/plat-mxc/devices/platform-ahci-imx.c
arch/arm/plat-mxc/devices/platform-fec.c
arch/arm/plat-mxc/devices/platform-imx-epdc-fb.c
arch/arm/plat-mxc/devices/platform-imx-hdmi-soc-dai.c
arch/arm/plat-mxc/devices/platform-imx-hdmi-soc.c
arch/arm/plat-mxc/devices/platform-imx-pcie.c
arch/arm/plat-mxc/devices/platform-imx-pxp.c
arch/arm/plat-mxc/devices/platform-imx_vpu.c
arch/arm/plat-mxc/devices/platform-mxc-hdmi-core.c
arch/arm/plat-mxc/devices/platform-mxc_hdmi.c
arch/arm/plat-mxc/devices/platform-mxc_mlb.c
arch/arm/plat-mxc/fuse.c [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/mxc.h

index 6ff1c907210495ccaa2f6b1fa0e1d2a722d0c95a..1aa1780231d08ff96aea5e26e9093cc2631d0d99 100755 (executable)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o usb_common.o usb_wakeup.o
+obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o usb_common.o usb_wakeup.o fuse.o
 
 # MX51 uses the TZIC interrupt controller, older platforms use AVIC
 obj-$(CONFIG_MXC_TZIC) += tzic.o
index 30bfeaaac3d62aa5b1935cbf99cb08d9c056ecdf..90d994c27f9bfed084c8c06777236f7dc6440600 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -54,6 +54,9 @@ struct platform_device *__init imx_add_ahci(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_SATA))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device_dmamask("ahci", 0 /* -1? */,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata),  DMA_BIT_MASK(32));
index 20422cf6e76f13306694447c7e6984abb6638d14..0a03ea9b92b2eea5288f3e5d97ba4124d6493a73 100644 (file)
@@ -6,7 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  *
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  */
 #include <linux/dma-mapping.h>
 #include <asm/sizes.h>
@@ -74,6 +74,9 @@ struct platform_device *__init imx_add_fec(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_ENET))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device_dmamask(data->devid, 0,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
index 404a264e7ddc64766150b304d68b33a66047246c..459e6cc3ea0c3e04c169af6becfbd7c116ff4d96 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -55,6 +55,9 @@ struct platform_device *__init imx_add_imx_epdc(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_EPDC))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device_dmamask("imx_epdc_fb", -1,
                res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index 813f954517bb0009a90cb94a44e794246e54bb3a..26f4ae71edf1b51af75137fa1489da6f75af4b7f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  */
 
 /*
@@ -42,6 +42,9 @@ struct platform_device *__init imx_add_hdmi_soc_dai(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_HDMI))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device("imx-hdmi-soc-dai", 0,
                                res, ARRAY_SIZE(res), NULL, 0);
 }
index 33c8a685e8a4c7bfa90eec82dfbb3aabda6f8af7..7be6756c1ac8d75189101ccff30eab2d21481f84 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
 #include <mach/devices-common.h>
 
 struct platform_device *__init imx_add_hdmi_soc(void)
-{      return imx_add_platform_device("mxc_hdmi_soc", 0,
+{
+
+       if (!fuse_dev_is_available(MXC_DEV_HDMI))
+               return ERR_PTR(-ENODEV);
+
+       return imx_add_platform_device("mxc_hdmi_soc", 0,
                                       NULL, 0, NULL, 0);
 }
 
index cf36093651295bef80c893ec928d356a94ba10ca..7e0d630f92e28036275c9cfa32052176d647f2d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -55,6 +55,9 @@ struct platform_device *__init imx_add_pcie(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_PCIE))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device("imx-pcie", -1,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata));
index 418489e1c4ea5190dfa3d509b687c1253ea523ce..fed58d09306d34f9f018f75392bc0e31c6038103 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -54,18 +54,27 @@ struct platform_device *__init imx_add_imx_pxp(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_PXP))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device_dmamask("imx-pxp", -1,
                res, ARRAY_SIZE(res), NULL, 0, DMA_BIT_MASK(32));
 }
 
 struct platform_device *__init imx_add_imx_pxp_client()
 {
-    return imx_add_platform_device("imx-pxp-client", -1,
+       if (!fuse_dev_is_available(MXC_DEV_PXP))
+               return ERR_PTR(-ENODEV);
+
+       return imx_add_platform_device("imx-pxp-client", -1,
                NULL, 0, NULL, 0);
 }
 
 struct platform_device *__init imx_add_imx_pxp_v4l2()
 {
-    return imx_add_platform_device_dmamask("pxp-v4l2", -1,
+       if (!fuse_dev_is_available(MXC_DEV_PXP))
+               return ERR_PTR(-ENODEV);
+
+       return imx_add_platform_device_dmamask("pxp-v4l2", -1,
                NULL, 0, NULL, 0, DMA_BIT_MASK(32));
 }
index 83faed6e7b6a54f654adaf4681f3db7a8bd174e3..9e00b2fd22aa5aeb465a0c647b03237ad952363f 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  * Jason Chen <jason.chen@freescale.com>
  *
  * This program is free software; you can redistribute it and/or modify it under
@@ -167,15 +167,9 @@ struct platform_device *__init imx_add_vpu(
        pdata.iram_enable = data->iram_enable;
        pdata.iram_size = data->iram_size;
 
-#ifdef CONFIG_SOC_IMX6Q
-       if (cpu_is_mx6dl() || cpu_is_mx6q()) {
-               #define HW_OCOTP_CFGn(n) (0x00000410 + (n) * 0x10)
-               unsigned int vpu_disable;
-               vpu_disable = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_CFGn(3));
-               if (vpu_disable & 0x00008000)
-                       return ERR_PTR(-ENODEV);
-       }
-#endif
+       if (!fuse_dev_is_available(MXC_DEV_VPU))
+               return ERR_PTR(-ENODEV);
+
        if (cpu_is_mx6dl())
                pdata.iram_enable = false;
 
index e0c1906166a2170f6118bd8c541d42233ab49a83..2c9a32a9b56888c609f59f49d6b57c133804947b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -45,6 +45,9 @@ struct platform_device *__init imx_add_mxc_hdmi_core(
                },
        };
 
+       if (!fuse_dev_is_available(MXC_DEV_HDMI))
+               return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device_dmamask("mxc_hdmi_core", -1,
                res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index d4952620e223f837a07330fad8cd4fca5499ee70..cdbdae4999db2aeba6de84bec89c9606b1d9de90 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -43,6 +43,10 @@ struct platform_device *__init imx_add_mxc_hdmi(
                        .flags = IORESOURCE_IRQ,
                },
        };
+
+       if (!fuse_dev_is_available(MXC_DEV_HDMI))
+               return ERR_PTR(-ENODEV);
+
        imx_add_platform_device("mxc_hdmi_cec", 0,
                                       res, ARRAY_SIZE(res), NULL, 0);
        return imx_add_platform_device_dmamask("mxc_hdmi", -1,
index 661595fd5f383dab1616ef572db0c69f5370c60a..8925f3ee069056981e4cd27ccea093b9751554e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -44,8 +44,6 @@ struct platform_device *__init imx_add_mlb(
 struct platform_device *__init imx_add_mlb(
                const struct mxc_mlb_platform_data *pdata)
 {
-#define HW_OCOTP_CFGn(n)        (0x00000410 + (n) * 0x10)
-       unsigned int mlb_disable = 0;
        struct resource res[] = {
                {
                        .start = MLB_BASE_ADDR,
@@ -69,9 +67,9 @@ struct platform_device *__init imx_add_mlb(
                },
        };
 
-       mlb_disable = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_CFGn(2));
-       if (mlb_disable & 0x04000000)
+       if (!fuse_dev_is_available(MXC_DEV_MLB))
                return ERR_PTR(-ENODEV);
+
        return imx_add_platform_device("mxc_mlb150", 0,
                        res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/fuse.c b/arch/arm/plat-mxc/fuse.c
new file mode 100644 (file)
index 0000000..1238e76
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <mach/hardware.h>
+
+#define HW_OCOTP_CFGn(n)       (0x00000410 + (n) * 0x10)
+
+/* Note: the names oder is the same as device enum order defined in mxc.h */
+static char *names[] = {
+       "pxp", "ovg", "dsi_csi2", "enet", "mlb",
+       "epdc", "hdmi", "pcie", "sata", "dtcp",
+       "2d", "3d", "vpu", "divx3", "rv",
+       "sorensen",
+};
+
+int fuse_dev_is_available(enum mxc_dev_type dev)
+{
+       u32 uninitialized_var(reg);
+       u32 uninitialized_var(mask);
+       int ret;
+
+       if (!cpu_is_mx6())
+               return 1;
+
+       /* mx6sl is still not supported */
+       if (cpu_is_mx6sl())
+               return 1;
+
+       switch (dev) {
+       case MXC_DEV_PXP:
+               if (cpu_is_mx6q())
+                       return 0;
+
+               if (cpu_is_mx6dl()) {
+                       reg = HW_OCOTP_CFGn(2);
+                       mask = 0x80000000;
+               }
+               break;
+       case MXC_DEV_OVG:
+               if (cpu_is_mx6dl())
+                       return 0;
+
+               if (cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(2);
+                       mask = 0x40000000;
+               }
+               break;
+       case MXC_DEV_DSI_CSI2:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(2);
+                       mask = 0x10000000;
+               }
+               break;
+       case MXC_DEV_ENET:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(2);
+                       mask = 0x08000000;
+               }
+               break;
+       case MXC_DEV_MLB:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(2);
+                       mask = 0x04000000;
+               }
+               break;
+       case MXC_DEV_EPDC:
+               if (cpu_is_mx6q())
+                       return 0;
+
+               if (cpu_is_mx6dl()) {
+                       reg = HW_OCOTP_CFGn(2);
+                       mask = 0x02000000;
+               }
+               break;
+       case MXC_DEV_HDMI:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000080;
+               }
+               break;
+       case MXC_DEV_PCIE:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000040;
+               }
+               break;
+       case MXC_DEV_SATA:
+               if (cpu_is_mx6dl())
+                       return 0;
+
+               if (cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000020;
+               }
+               break;
+       case MXC_DEV_DTCP:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000010;
+               }
+               break;
+       case MXC_DEV_2D:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000008;
+               }
+               break;
+       case MXC_DEV_3D:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000004;
+               }
+               break;
+       case MXC_DEV_VPU:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00008000;
+               }
+               break;
+       case MXC_DEV_DIVX3:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000400;
+               }
+               break;
+       case MXC_DEV_RV:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000200;
+               }
+               break;
+       case MXC_DEV_SORENSEN:
+               if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+                       reg = HW_OCOTP_CFGn(3);
+                       mask = 0x00000100;
+               }
+               break;
+       default:
+               /* we treat the unkown device is avaiable by default */
+               return 1;
+       }
+
+       ret = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + reg) & mask;
+       pr_debug("fuse_check: %s is %s\n", names[dev], ret ?
+                                       "unavailable" : "available");
+
+       return !ret;
+}
index 4260d4a25c2c336f7ce486272efffe99a5dc16cd..75b99affc39bd365ae9028c78862817106936b97 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2007, 2011-2012 Freescale Semiconductor, Inc.
+ * Copyright 2004-2007, 2011-2013 Freescale Semiconductor, Inc.
  * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
  *
  * This program is free software; you can redistribute it and/or
@@ -275,6 +275,28 @@ int tzic_enable_wake(int is_idle);
 
 extern void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
 extern int tzic_enable_wake(int is_idle);
+
+/* available disableable devices in fuse */
+enum mxc_dev_type {
+       MXC_DEV_PXP,
+       MXC_DEV_OVG,
+       MXC_DEV_DSI_CSI2,
+       MXC_DEV_ENET,
+       MXC_DEV_MLB,
+       MXC_DEV_EPDC,
+       MXC_DEV_HDMI,
+       MXC_DEV_PCIE,
+       MXC_DEV_SATA,
+       MXC_DEV_DTCP,
+       MXC_DEV_2D,
+       MXC_DEV_3D,
+       MXC_DEV_VPU,
+       MXC_DEV_DIVX3,
+       MXC_DEV_RV,
+       MXC_DEV_SORENSEN,
+};
+extern int fuse_dev_is_available(enum mxc_dev_type dev);
+
 #endif
 
 #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2)