嵌入式爱好者

嵌入式爱好者 门户 知识库 查看内容

AM62xx添加GPMC NOR FLASH应用

2022-7-31 21:09| 发布者: 这是啥啊| 查看: 309| 评论: 0

类目:  >  知识库     文档编号: 714

AM62xx开发板将GPMC总线引出到P34引脚。添加GPMC NOR FLASH应用方法如下
  • 设备树修改
diff --git a/arch/arm64/boot/dts/ti/OK6254-C.dts b/arch/arm64/boot/dts/ti/OK6254-C.dts
index 5d4923bff..ad5228be3 100644
--- a/arch/arm64/boot/dts/ti/OK6254-C.dts
+++ b/arch/arm64/boot/dts/ti/OK6254-C.dts
@@ -525,6 +525,32 @@
             AM62X_IOPAD(0x128, PIN_OUTPUT, 7) /* (B23) CSI_PWDN.GPIO0_72 */
         >;
     };
+
+    gpmc0_pins_default: gpmc0-pins-default {
+        pinctrl-single,pins = <
+            AM62X_IOPAD(0x078, PIN_INPUT, 0) /* (U24) GPMC0_AD15.GPMC0_AD15 */   
+            AM62X_IOPAD(0x074, PIN_INPUT, 0) /* (U25) GPMC0_AD14.GPMC0_AD14 */
+            AM62X_IOPAD(0x070, PIN_INPUT, 0) /* (T24) GPMC0_AD13.GPMC0_AD13 */
+            AM62X_IOPAD(0x06C, PIN_INPUT, 0) /* (T22) GPMC0_AD12.GPMC0_AD12 */
+            AM62X_IOPAD(0x068, PIN_INPUT, 0) /* (R21) GPMC0_AD11.GPMC0_AD11 */
+            AM62X_IOPAD(0x064, PIN_INPUT, 0) /* (T25) GPMC0_AD10.GPMC0_AD10 */
+            AM62X_IOPAD(0x060, PIN_INPUT, 0) /* (R25) GPMC0_AD9.GPMC0_AD9 */
+            AM62X_IOPAD(0x05C, PIN_INPUT, 0) /* (R24) GPMC0_AD8.GPMC0_AD8 */
+            AM62X_IOPAD(0x058, PIN_INPUT, 0) /* (R23) GPMC0_AD7.GPMC0_AD7 */
+            AM62X_IOPAD(0x054, PIN_INPUT, 0) /* (P21) GPMC0_AD6.GPMC0_AD6 */
+            AM62X_IOPAD(0x050, PIN_INPUT, 0) /* (P22) GPMC0_AD5.GPMC0_AD5 */
+            AM62X_IOPAD(0x04C, PIN_INPUT, 0) /* (P24) GPMC0_AD4.GPMC0_AD4 */
+            AM62X_IOPAD(0x048, PIN_INPUT, 0) /* (N25) GPMC0_AD3.GPMC0_AD3 */
+            AM62X_IOPAD(0x044, PIN_INPUT, 0) /* (N24) GPMC0_AD2.GPMC0_AD2 */
+            AM62X_IOPAD(0x040, PIN_INPUT, 0) /* (N23) GPMC0_AD1.GPMC0_AD1 */
+            AM62X_IOPAD(0x03C, PIN_INPUT, 0) /* (M25) GPMC0_AD0.GPMC0_AD0 */
+            AM62X_IOPAD(0x084, PIN_OUTPUT, 0) /* (L23) GPMC0_ADVn_ALE.GPMC0_ADVn_ALE */
+            AM62X_IOPAD(0x088, PIN_OUTPUT, 0) /* (L24) GPMC0_OEn_REn.GPMC0_OEn_REn */
+            AM62X_IOPAD(0x08C, PIN_OUTPUT, 0) /* (L25) GPMC0_WEn.GPMC0_WEn */
+            AM62X_IOPAD(0x098, PIN_INPUT_PULLUP, 0) /* (U23) GPMC0_WAIT0.GPMC0_WAIT0 */
+            AM62X_IOPAD(0x0A8, PIN_OUTPUT, 0)    /* (M21) GPMC0_CSn0.GPMC0_CSn0 */
+        >;
+    };
};

&mcu_pmx0 {
@@ -937,3 +963,52 @@
     ti,system-suspend-controller;
        ti,ctx-memory-region = <&lpm_ctx_ddr>;
};
+
+&gpmc0 {
+    pinctrl-names = "default";
+    pinctrl-0 = <&gpmc0_pins_default>;
+    ranges = <0 0 0x00 0x50000000 0x02000000>;
+
+    nor@0,0 {
+            compatible = "fl,gpmc-nor";
+
+            reg = <0 0x0 0x02000000>;
+            linux,mtd-name = "cfi_probe";
+            probe-type = "CFI"; /* CFI or JEDEC */
+            //big-endian;
+
+            bank-width = <2>;
+            gpmc,mux-add-data = <2>;
+            gpmc,burst-length = <16>; //16words
+            gpmc,burst-read;
+            gpmc,burst-write;
+            gpmc,page-burst-access-ns = <0>;
+
+            gpmc,sync-clk-ps = <0>;
+            gpmc,cs-on-ns = <7>;
+            gpmc,cs-rd-off-ns = <120>;
+            gpmc,cs-wr-off-ns = <120>;
+            
+            gpmc,adv-on-ns = <7>;
+            gpmc,adv-rd-off-ns = <15>;
+            gpmc,adv-wr-off-ns = <15>;
+
+            gpmc,we-on-ns = <30>;
+            gpmc,we-off-ns = <93>;
+
+            gpmc,oe-on-ns = <28>;
+            gpmc,oe-off-ns = <120>;
+
+            gpmc,access-ns = <120>;
+
+            gpmc,rd-cycle-ns = <120>;
+            gpmc,wr-cycle-ns = <120>;
+
+            gpmc,bus-turnaround-ns = <0>;
+            gpmc,cycle2cycle-delay-ns = <0>;
+            gpmc,clk-activation-ns = <0>;
+            gpmc,wr-access-ns = <112>;
+
+            gpmc,wr-data-mux-bus-ns = <52>;
+    };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index e23350dce..cbc9bb54b 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -981,4 +981,32 @@
         reg-names = "esm";
         forlinx,esm-pins = <5>;
     };
+
+    gpmc0: memory-controller@3b000000 {
+        compatible = "ti,am64-gpmc";
+        power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>;
+        clocks = <&k3_clks 80 0>;
+        clock-names = "fck";
+        reg = <0x00 0x03b000000 0x00 0x400>,
+              <0x00 0x050000000 0x00 0x08000000>;
+        reg-names = "cfg", "data";
+        interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+        gpmc,num-cs = <3>;
+        gpmc,num-waitpins = <2>;
+        #address-cells = <2>;
+        #size-cells = <1>;
+        interrupt-controller;
+        #interrupt-cells = <2>;
+        gpio-controller;
+        #gpio-cells = <2>;
+    };
+
+    elm0: ecc@25010000 {
+        compatible = "ti,am3352-elm";
+        reg = <0x00 0x25010000 0x00 0x2000>;
+        interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+        power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>;
+        clocks = <&k3_clks 54 0>;
+        clock-names = "fck";
+    };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi
index 71665fa1f..d1f11ffd7 100644
--- a/arch/arm64/boot/dts/ti/k3-am62.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi
@@ -79,6 +79,8 @@
              <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01d20000>, /* Second peripheral window */
              <0x00 0x20000000 0x00 0x20000000 0x00 0x0a008000>, /* Third peripheral window */
              <0x00 0x30200000 0x00 0x30200000 0x00 0x00010000>, /* DSS */
+             <0x00 0x3b000000 0x00 0x3b000000 0x00 0x00000400>, /* GPMC0_CFG */
+             <0x00 0x50000000 0x00 0x50000000 0x00 0x08000000>, /* GPMC0_DATA */
              <0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* sa3 sproxy data */
              <0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */
              <0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* sa3 sproxy config */


2.驱动修改及添加
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index d9bf1c2ac..874298ffb 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -165,7 +165,7 @@
#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
#define GPMC_CONFIG7_CSVALID        (1 << 6)

-#define GPMC_CONFIG7_BASEADDRESS_MASK    0x3f
+#define GPMC_CONFIG7_BASEADDRESS_MASK    0x5f
#define GPMC_CONFIG7_CSVALID_MASK    BIT(6)
#define GPMC_CONFIG7_MASKADDRESS_OFFSET    8
#define GPMC_CONFIG7_MASKADDRESS_MASK    (0xf << GPMC_CONFIG7_MASKADDRESS_OFFSET)


diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 96a27e064..d2137cb72 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -432,6 +432,15 @@ static void fixup_s29ns512p_sectors(struct mtd_info *mtd)
         mtd->name);
}

+
+static void fixup_s29gl**s_sectors(struct mtd_info *mtd)
+{
+    struct map_info *map = mtd->priv;
+    struct cfi_private *cfi = map->fldrv_priv;
+    cfi->cfiq->DevSize = 26;
+    cfi->cfiq->EraseRegionInfo[0] = 0x020001ff;
+}
+
/* Used to fix CFI-Tables of chips without Extended Query Tables */
static struct cfi_fixup cfi_nopri_fixup_table[] = {
     { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */
@@ -463,6 +472,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
     { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors },
     { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors },
     { CFI_MFR_AMD, 0x3f00, fixup_s29ns512p_sectors },
+    { CFI_MFR_AMD, 0x2201, fixup_s29gl**s_sectors },
     { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */
     { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */
     { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */
diff --git a/drivers/mtd/gpmc_nor.c b/drivers/mtd/gpmc_nor.c
new file mode 100755
index 000000000..0e3d70e77
--- /dev/null
+++ b/drivers/mtd/gpmc_nor.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Normal mappings of chips in omap-nor memory
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/cfi.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/of.h>
+#include <linux/omap-gpmc.h>
+
+struct gpmc_nor_mtd {
+    struct mtd_info *mtd;
+    struct map_info *map;
+    struct resource *res;
+    const char        *probe_type;
+
+    /* gpmc */
+    int                gpmc_cs;
+};
+
+
+#define DRIVER_NAME "gpmc-nor"
+
+static struct mtd_partition board_nor_parts[] = {
+    [0] = {
+        .name = DRIVER_NAME,
+        .offset = 0,
+        .size = MTDPART_SIZ_FULL,
+    },
+};
+
+static const char *gpmc_nor_select_probe_type(struct platform_device *dev)
+{
+    struct device_node *dp = dev->dev.of_node;
+    const char *probe_type;
+
+    of_property_read_string(dp, "probe-type", &probe_type);
+    if (!probe_type)
+        return NULL;
+
+    if (!strcmp(probe_type, "CFI")) {
+        probe_type = "cfi_probe";
+    } else if (!strcmp(probe_type, "JEDEC")) {
+        probe_type = "jedec_probe";
+    } else if (!strcmp(probe_type, "ROM")) {
+        probe_type = "map_rom";
+    } else {
+        dev_warn(&dev->dev,
+             "obsolete_probe: don't know probe type '%s', mapping as cfi\n",
+             probe_type);
+        probe_type = "cfi_probe";
+    }
+
+    return probe_type;
+}
+
+static int gpmc_nor_parse_dt(struct platform_device *dev)
+{
+    struct gpmc_nor_mtd *gpmc_nor_mtd = platform_get_drvdata(dev);
+    struct device_node *dp = dev->dev.of_node;
+    int err;
+    u32 bankwidth;
+    u32 cs;
+    int swap = CFI_LITTLE_ENDIAN;
+
+    if (!dp)
+        return -EINVAL;
+
+    gpmc_nor_mtd->probe_type = gpmc_nor_select_probe_type(dev);
+
+    err = of_property_read_u32(dp, "reg", &cs);
+    if (err) {
+        dev_err(&dev->dev, "reg not found in DT\n");
+        return -EINVAL;
+    }
+    gpmc_nor_mtd->gpmc_cs = cs;
+
+    err = of_property_read_u32(dp, "bank-width", &bankwidth);
+    if (err) {
+        dev_err(&dev->dev, "Can't get bank width from device tree\n");
+        return err;
+    }
+
+    if (of_property_read_bool(dp, "big-endian"))
+        swap = CFI_BIG_ENDIAN;
+    else if (of_property_read_bool(dp, "little-endian"))
+        swap = CFI_LITTLE_ENDIAN;
+
+    gpmc_nor_mtd->map->name = gpmc_nor_mtd->probe_type;
+    gpmc_nor_mtd->map->bankwidth = bankwidth;
+    gpmc_nor_mtd->map->swap = swap;
+    gpmc_nor_mtd->map->device_node = dp;
+
+    /*
+     * On some platforms (e.g. MPC5200) a direct 1:1 mapping
+     * may cause problems with JFFS2 usage, as the local bus (LPB)
+     * doesn't support unaligned accesses as implemented in the
+     * JFFS2 code via memcpy(). By setting NO_XIP, the
+     * flash will not be exposed directly to the MTD users
+     * (e.g. JFFS2) any more.
+     */
+    if (of_property_read_bool(dp, "no-unaligned-direct-access"))
+        gpmc_nor_mtd->map->phys = NO_XIP;
+    else
+        gpmc_nor_mtd->map->phys = 0;
+    return 0;
+}
+
+static int gpmc_nor_remove(struct platform_device *pdev)
+{
+    struct gpmc_nor_mtd *gpmc_nor_mtd = platform_get_drvdata(pdev);
+
+    if (gpmc_nor_mtd && gpmc_nor_mtd->mtd) {
+        mtd_device_unregister(gpmc_nor_mtd->mtd);
+        map_destroy(gpmc_nor_mtd->mtd);
+    }
+
+    return 0;
+}
+
+static int gpmc_nor_probe(struct platform_device *pdev)
+{
+    struct gpmc_nor_mtd *gpmc_nor_mtd;
+    int err;
+
+    if (! pdev->dev.of_node) {
+        dev_err(&pdev->dev, "failed to find of node\n");
+        return -ENOMEM;
+    }
+
+    gpmc_nor_mtd = devm_kzalloc(&pdev->dev, sizeof(struct gpmc_nor_mtd), GFP_KERNEL);
+    if (!gpmc_nor_mtd)
+        return -ENOMEM;
+
+    platform_set_drvdata(pdev, gpmc_nor_mtd);
+
+    gpmc_nor_mtd->map = devm_kzalloc(&pdev->dev, sizeof(struct map_info), GFP_KERNEL);
+    if (!gpmc_nor_mtd->map)
+        return -ENOMEM;
+
+    err = gpmc_nor_parse_dt(pdev);
+    if (err) {
+        dev_err(&pdev->dev, "failed to parse dt\n");
+        return -ENOMEM;
+    }
+
+    gpmc_nor_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+    if (!gpmc_nor_mtd->res) {
+        dev_err(&pdev->dev, "failed to get memory resource\n");
+        return -ENOENT;
+    }
+
+    gpmc_nor_mtd->map->phys = gpmc_nor_mtd->res->start;
+    gpmc_nor_mtd->map->size = resource_size(gpmc_nor_mtd->res);
+    gpmc_nor_mtd->map->virt = devm_ioremap_resource(&pdev->dev, gpmc_nor_mtd->res);
+    if (IS_ERR(gpmc_nor_mtd->map->virt))
+        return PTR_ERR(gpmc_nor_mtd->map->virt);
+
+    printk("gpmc map phys:%x virt:%x size:%x\n", gpmc_nor_mtd->map->phys, gpmc_nor_mtd->map->virt,
+                gpmc_nor_mtd->map->size);
+    **_map_init(gpmc_nor_mtd->map);
+   
+    gpmc_cs_write_reg(0, 0x00,(2 << 23)|(0 << 22)|(0 << 21)|(0 << 18)|(1 << 12)|(2 << 8));
+    gpmc_nor_mtd->mtd = do_map_probe(gpmc_nor_mtd->probe_type, gpmc_nor_mtd->map);
+    if (!gpmc_nor_mtd->mtd) {
+        dev_err(&pdev->dev, "probing failed\n");
+        return -ENXIO;
+    }
+
+    gpmc_nor_mtd->mtd->dev.parent = &pdev->dev;
+
+    mtd_set_of_node(gpmc_nor_mtd->mtd, pdev->dev.of_node);
+
+    err = mtd_device_register(gpmc_nor_mtd->mtd, board_nor_parts, 1);
+    if (err) {
+        dev_err(&pdev->dev, "failed to add partitions\n");
+        goto err_destroy;
+    }
+
+    return 0;
+
+err_destroy:
+    gpmc_nor_remove(pdev);
+    return err;
+}
+
+static const struct of_device_id gpmc_nor_ids[] = {
+    { .compatible = "fl,gpmc-nor" },
+    {},
+};
+MODULE_DEVICE_TABLE(of, gpmc_nor_ids);
+
+static struct platform_driver gpmc_nor_driver = {
+    .probe = gpmc_nor_probe,
+    .remove = gpmc_nor_remove,
+    .driver = {
+        .name = DRIVER_NAME,
+        .of_match_table = gpmc_nor_ids,
+    },
+};
+
+module_platform_driver(gpmc_nor_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("ZZY <zzy@forlinx>");
+MODULE_DESCRIPTION("FL gpmc NOR");
+

3.makefile添加编译
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 593d0593a..92bc1c1b3 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -31,3 +31,4 @@ obj-y        += chips/ lpddr/ maps/ devices/ nand/ tests/
obj-$(CONFIG_MTD_SPI_NOR)    += spi-nor/
obj-$(CONFIG_MTD_UBI)        += ubi/
obj-$(CONFIG_MTD_HYPERBUS)    += hyperbus/
+obj-y                        += gpmc_nor.o

已解决

未解决

只是看看

最新评论

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2025-4-12 17:11

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

返回顶部