Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * ARM PL353 SMC driver
0004  *
0005  * Copyright (C) 2012 - 2018 Xilinx, Inc
0006  * Author: Punnaiah Choudary Kalluri <punnaiah@xilinx.com>
0007  * Author: Naga Sureshkumar Relli <nagasure@xilinx.com>
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/amba/bus.h>
0016 
0017 /**
0018  * struct pl353_smc_data - Private smc driver structure
0019  * @memclk:     Pointer to the peripheral clock
0020  * @aclk:       Pointer to the AXI peripheral clock
0021  */
0022 struct pl353_smc_data {
0023     struct clk      *memclk;
0024     struct clk      *aclk;
0025 };
0026 
0027 static int __maybe_unused pl353_smc_suspend(struct device *dev)
0028 {
0029     struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
0030 
0031     clk_disable(pl353_smc->memclk);
0032     clk_disable(pl353_smc->aclk);
0033 
0034     return 0;
0035 }
0036 
0037 static int __maybe_unused pl353_smc_resume(struct device *dev)
0038 {
0039     struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
0040     int ret;
0041 
0042     ret = clk_enable(pl353_smc->aclk);
0043     if (ret) {
0044         dev_err(dev, "Cannot enable axi domain clock.\n");
0045         return ret;
0046     }
0047 
0048     ret = clk_enable(pl353_smc->memclk);
0049     if (ret) {
0050         dev_err(dev, "Cannot enable memory clock.\n");
0051         clk_disable(pl353_smc->aclk);
0052         return ret;
0053     }
0054 
0055     return ret;
0056 }
0057 
0058 static SIMPLE_DEV_PM_OPS(pl353_smc_dev_pm_ops, pl353_smc_suspend,
0059              pl353_smc_resume);
0060 
0061 static const struct of_device_id pl353_smc_supported_children[] = {
0062     {
0063         .compatible = "cfi-flash"
0064     },
0065     {
0066         .compatible = "arm,pl353-nand-r2p1",
0067     },
0068     {}
0069 };
0070 
0071 static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id)
0072 {
0073     struct device_node *of_node = adev->dev.of_node;
0074     const struct of_device_id *match = NULL;
0075     struct pl353_smc_data *pl353_smc;
0076     struct device_node *child;
0077     int err;
0078 
0079     pl353_smc = devm_kzalloc(&adev->dev, sizeof(*pl353_smc), GFP_KERNEL);
0080     if (!pl353_smc)
0081         return -ENOMEM;
0082 
0083     pl353_smc->aclk = devm_clk_get(&adev->dev, "apb_pclk");
0084     if (IS_ERR(pl353_smc->aclk)) {
0085         dev_err(&adev->dev, "aclk clock not found.\n");
0086         return PTR_ERR(pl353_smc->aclk);
0087     }
0088 
0089     pl353_smc->memclk = devm_clk_get(&adev->dev, "memclk");
0090     if (IS_ERR(pl353_smc->memclk)) {
0091         dev_err(&adev->dev, "memclk clock not found.\n");
0092         return PTR_ERR(pl353_smc->memclk);
0093     }
0094 
0095     err = clk_prepare_enable(pl353_smc->aclk);
0096     if (err) {
0097         dev_err(&adev->dev, "Unable to enable AXI clock.\n");
0098         return err;
0099     }
0100 
0101     err = clk_prepare_enable(pl353_smc->memclk);
0102     if (err) {
0103         dev_err(&adev->dev, "Unable to enable memory clock.\n");
0104         goto disable_axi_clk;
0105     }
0106 
0107     amba_set_drvdata(adev, pl353_smc);
0108 
0109     /* Find compatible children. Only a single child is supported */
0110     for_each_available_child_of_node(of_node, child) {
0111         match = of_match_node(pl353_smc_supported_children, child);
0112         if (!match) {
0113             dev_warn(&adev->dev, "unsupported child node\n");
0114             continue;
0115         }
0116         break;
0117     }
0118     if (!match) {
0119         err = -ENODEV;
0120         dev_err(&adev->dev, "no matching children\n");
0121         goto disable_mem_clk;
0122     }
0123 
0124     of_platform_device_create(child, NULL, &adev->dev);
0125 
0126     return 0;
0127 
0128 disable_mem_clk:
0129     clk_disable_unprepare(pl353_smc->memclk);
0130 disable_axi_clk:
0131     clk_disable_unprepare(pl353_smc->aclk);
0132 
0133     return err;
0134 }
0135 
0136 static void pl353_smc_remove(struct amba_device *adev)
0137 {
0138     struct pl353_smc_data *pl353_smc = amba_get_drvdata(adev);
0139 
0140     clk_disable_unprepare(pl353_smc->memclk);
0141     clk_disable_unprepare(pl353_smc->aclk);
0142 }
0143 
0144 static const struct amba_id pl353_ids[] = {
0145     {
0146         .id = 0x00041353,
0147         .mask = 0x000fffff,
0148     },
0149     { 0, 0 },
0150 };
0151 MODULE_DEVICE_TABLE(amba, pl353_ids);
0152 
0153 static struct amba_driver pl353_smc_driver = {
0154     .drv = {
0155         .owner = THIS_MODULE,
0156         .name = "pl353-smc",
0157         .pm = &pl353_smc_dev_pm_ops,
0158     },
0159     .id_table = pl353_ids,
0160     .probe = pl353_smc_probe,
0161     .remove = pl353_smc_remove,
0162 };
0163 
0164 module_amba_driver(pl353_smc_driver);
0165 
0166 MODULE_AUTHOR("Xilinx, Inc.");
0167 MODULE_DESCRIPTION("ARM PL353 SMC Driver");
0168 MODULE_LICENSE("GPL");