mirror of https://github.com/OpenIPC/firmware.git
125 lines
3.1 KiB
Diff
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");
|