0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk-provider.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regmap.h>
0015
0016 #define NB_GPIO1_LATCH 0x8
0017 #define XTAL_MODE BIT(9)
0018
0019 static int armada_3700_xtal_clock_probe(struct platform_device *pdev)
0020 {
0021 struct device_node *np = pdev->dev.of_node;
0022 const char *xtal_name = "xtal";
0023 struct device_node *parent;
0024 struct regmap *regmap;
0025 struct clk_hw *xtal_hw;
0026 unsigned int rate;
0027 u32 reg;
0028 int ret;
0029
0030 xtal_hw = devm_kzalloc(&pdev->dev, sizeof(*xtal_hw), GFP_KERNEL);
0031 if (!xtal_hw)
0032 return -ENOMEM;
0033
0034 platform_set_drvdata(pdev, xtal_hw);
0035
0036 parent = np->parent;
0037 if (!parent) {
0038 dev_err(&pdev->dev, "no parent\n");
0039 return -ENODEV;
0040 }
0041
0042 regmap = syscon_node_to_regmap(parent);
0043 if (IS_ERR(regmap)) {
0044 dev_err(&pdev->dev, "cannot get regmap\n");
0045 return PTR_ERR(regmap);
0046 }
0047
0048 ret = regmap_read(regmap, NB_GPIO1_LATCH, ®);
0049 if (ret) {
0050 dev_err(&pdev->dev, "cannot read from regmap\n");
0051 return ret;
0052 }
0053
0054 if (reg & XTAL_MODE)
0055 rate = 40000000;
0056 else
0057 rate = 25000000;
0058
0059 of_property_read_string_index(np, "clock-output-names", 0, &xtal_name);
0060 xtal_hw = clk_hw_register_fixed_rate(NULL, xtal_name, NULL, 0, rate);
0061 if (IS_ERR(xtal_hw))
0062 return PTR_ERR(xtal_hw);
0063 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, xtal_hw);
0064
0065 return ret;
0066 }
0067
0068 static int armada_3700_xtal_clock_remove(struct platform_device *pdev)
0069 {
0070 of_clk_del_provider(pdev->dev.of_node);
0071
0072 return 0;
0073 }
0074
0075 static const struct of_device_id armada_3700_xtal_clock_of_match[] = {
0076 { .compatible = "marvell,armada-3700-xtal-clock", },
0077 { }
0078 };
0079
0080 static struct platform_driver armada_3700_xtal_clock_driver = {
0081 .probe = armada_3700_xtal_clock_probe,
0082 .remove = armada_3700_xtal_clock_remove,
0083 .driver = {
0084 .name = "marvell-armada-3700-xtal-clock",
0085 .of_match_table = armada_3700_xtal_clock_of_match,
0086 },
0087 };
0088
0089 builtin_platform_driver(armada_3700_xtal_clock_driver);