diff options
| -rw-r--r-- | drivers/soc/qcom/qcom_gsbi.c | 46 |
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 | ||
| 25 | struct gsbi_info { | ||
| 26 | struct clk *hclk; | ||
| 27 | u32 mode; | ||
| 28 | u32 crci; | ||
| 29 | }; | ||
| 30 | |||
| 25 | static int gsbi_probe(struct platform_device *pdev) | 31 | static 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 | |||
| 75 | static 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 | ||
| 65 | static const struct of_device_id gsbi_dt_match[] = { | 84 | static 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 | ||
| 81 | module_platform_driver(gsbi_driver); | 101 | module_platform_driver(gsbi_driver); |
