firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_drivers-mfd-goke_fmc.c.p...

125 lines
3.1 KiB
Diff

--- linux-4.9.37/drivers/mfd/goke_fmc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mfd/goke_fmc.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/goke_fmc.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+unsigned char fmc_cs_user[FMC_MAX_CHIP_NUM];
+
+DEFINE_MUTEX(fmc_switch_mutex);
+EXPORT_SYMBOL_GPL(fmc_switch_mutex);
+
+/* ------------------------------------------------------------------------ */
+static const struct mfd_cell bsp_fmc_devs[] = {
+ {
+ .name = "bsp_spi_nor",
+ .of_compatible = "goke,fmc-spi-nor",
+ },
+ {
+ .name = "bsp_spi_nand",
+ .of_compatible = "goke,fmc-spi-nand",
+ },
+};
+
+static int bsp_fmc_probe(struct platform_device *pdev)
+{
+ struct bsp_fmc *fmc;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ fmc = devm_kzalloc(dev, sizeof(*fmc), GFP_KERNEL);
+ if (!fmc) {
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
+ fmc->regbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc->regbase)) {
+ return PTR_ERR(fmc->regbase);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory");
+ fmc->iobase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc->iobase)) {
+ return PTR_ERR(fmc->iobase);
+ }
+
+ fmc->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(fmc->clk)) {
+ return PTR_ERR(fmc->clk);
+ }
+
+ if (of_property_read_u32(dev->of_node, "max-dma-size", &fmc->dma_len)) {
+ dev_err(dev, "Please set the suitable max-dma-size value !!!\n");
+ return -ENOMEM;
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_warn(dev, "Unable to set dma mask\n");
+ return ret;
+ }
+
+ fmc->buffer = dmam_alloc_coherent(dev, fmc->dma_len,
+ &fmc->dma_buffer, GFP_KERNEL);
+ if (IS_ERR(fmc->buffer)) {
+ return PTR_ERR(fmc->buffer);
+ }
+
+ mutex_init(&fmc->lock);
+
+ platform_set_drvdata(pdev, fmc);
+
+ ret = mfd_add_devices(dev, 0, bsp_fmc_devs,
+ ARRAY_SIZE(bsp_fmc_devs), NULL, 0, NULL);
+ if (ret) {
+ dev_err(dev, "add mfd devices failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bsp_fmc_remove(struct platform_device *pdev)
+{
+ struct bsp_fmc *fmc = platform_get_drvdata(pdev);
+
+ dmam_free_coherent(&pdev->dev, fmc->dma_len,
+ fmc->buffer, fmc->dma_buffer);
+ mfd_remove_devices(&pdev->dev);
+ mutex_destroy(&fmc->lock);
+
+ return 0;
+}
+
+static const struct of_device_id bsp_fmc_of_match_tbl[] = {
+ { .compatible = "goke,fmc"},
+ { }
+};
+MODULE_DEVICE_TABLE(of, bsp_fmc_of_match_tbl);
+
+static struct platform_driver bsp_fmc_driver = {
+ .driver = {
+ .name = "fmc",
+ .of_match_table = bsp_fmc_of_match_tbl,
+ },
+ .probe = bsp_fmc_probe,
+ .remove = bsp_fmc_remove,
+};
+module_platform_driver(bsp_fmc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Goke Flash Memory Controller Driver");