aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/soc/qcom/qcom_gsbi.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c
index 447458e696a9..7e1f120f2b32 100644
--- a/drivers/soc/qcom/qcom_gsbi.c
+++ b/drivers/soc/qcom/qcom_gsbi.c
@@ -22,44 +22,63 @@
22#define GSBI_CTRL_REG 0x0000 22#define GSBI_CTRL_REG 0x0000
23#define GSBI_PROTOCOL_SHIFT 4 23#define GSBI_PROTOCOL_SHIFT 4
24 24
25struct gsbi_info {
26 struct clk *hclk;
27 u32 mode;
28 u32 crci;
29};
30
25static int gsbi_probe(struct platform_device *pdev) 31static int gsbi_probe(struct platform_device *pdev)
26{ 32{
27 struct device_node *node = pdev->dev.of_node; 33 struct device_node *node = pdev->dev.of_node;
28 struct resource *res; 34 struct resource *res;
29 void __iomem *base; 35 void __iomem *base;
30 struct clk *hclk; 36 struct gsbi_info *gsbi;
31 u32 mode, crci = 0; 37
38 gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
39
40 if (!gsbi)
41 return -ENOMEM;
32 42
33 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 43 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
34 base = devm_ioremap_resource(&pdev->dev, res); 44 base = devm_ioremap_resource(&pdev->dev, res);
35 if (IS_ERR(base)) 45 if (IS_ERR(base))
36 return PTR_ERR(base); 46 return PTR_ERR(base);
37 47
38 if (of_property_read_u32(node, "qcom,mode", &mode)) { 48 if (of_property_read_u32(node, "qcom,mode", &gsbi->mode)) {
39 dev_err(&pdev->dev, "missing mode configuration\n"); 49 dev_err(&pdev->dev, "missing mode configuration\n");
40 return -EINVAL; 50 return -EINVAL;
41 } 51 }
42 52
43 /* not required, so default to 0 if not present */ 53 /* not required, so default to 0 if not present */
44 of_property_read_u32(node, "qcom,crci", &crci); 54 of_property_read_u32(node, "qcom,crci", &gsbi->crci);
45 55
46 dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n", mode, crci); 56 dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n",
57 gsbi->mode, gsbi->crci);
58 gsbi->hclk = devm_clk_get(&pdev->dev, "iface");
59 if (IS_ERR(gsbi->hclk))
60 return PTR_ERR(gsbi->hclk);
47 61
48 hclk = devm_clk_get(&pdev->dev, "iface"); 62 clk_prepare_enable(gsbi->hclk);
49 if (IS_ERR(hclk))
50 return PTR_ERR(hclk);
51 63
52 clk_prepare_enable(hclk); 64 writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
53
54 writel_relaxed((mode << GSBI_PROTOCOL_SHIFT) | crci,
55 base + GSBI_CTRL_REG); 65 base + GSBI_CTRL_REG);
56 66
57 /* make sure the gsbi control write is not reordered */ 67 /* make sure the gsbi control write is not reordered */
58 wmb(); 68 wmb();
59 69
60 clk_disable_unprepare(hclk); 70 platform_set_drvdata(pdev, gsbi);
71
72 return of_platform_populate(node, NULL, NULL, &pdev->dev);
73}
74
75static int gsbi_remove(struct platform_device *pdev)
76{
77 struct gsbi_info *gsbi = platform_get_drvdata(pdev);
78
79 clk_disable_unprepare(gsbi->hclk);
61 80
62 return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 81 return 0;
63} 82}
64 83
65static const struct of_device_id gsbi_dt_match[] = { 84static const struct of_device_id gsbi_dt_match[] = {
@@ -76,6 +95,7 @@ static struct platform_driver gsbi_driver = {
76 .of_match_table = gsbi_dt_match, 95 .of_match_table = gsbi_dt_match,
77 }, 96 },
78 .probe = gsbi_probe, 97 .probe = gsbi_probe,
98 .remove = gsbi_remove,
79}; 99};
80 100
81module_platform_driver(gsbi_driver); 101module_platform_driver(gsbi_driver);