Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drivers/soc: qcom: do not disable the iface clock in probe

since commit 31964ffebbb9 ("tty: serial: msm: Remove direct access to GSBI")'
serial hangs if earlyprintk are enabled.

This hang is noticed only when the GSBI driver is probed and all the
earlyprintks before gsbi probe are seen on the console.
The reason why it hangs is because GSBI driver disables hclk in its
probe function without realizing that the serial IP might be in use by
a bootconsole. As gsbi driver disables the clock in probe the
bootconsole locks up.

Turning off hclk's could be dangerous if there are system components
like earlyprintk using the hclk.

This patch fixes the issue by delegating the clock management to
probe and remove functions in gsbi rather than disabling the clock in probe.

More detailed problem description can be found here:
http://www.spinics.net/lists/linux-arm-msm/msg10589.html

Tested-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Olof Johansson <olof@lixom.net>

authored by

Srinivas Kandagatla and committed by
Olof Johansson
fa9eb324 21c68e7c

+33 -13
+33 -13
drivers/soc/qcom/qcom_gsbi.c
··· 22 22 #define GSBI_CTRL_REG 0x0000 23 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 31 static int gsbi_probe(struct platform_device *pdev) 26 32 { 27 33 struct device_node *node = pdev->dev.of_node; 28 34 struct resource *res; 29 35 void __iomem *base; 30 - struct clk *hclk; 31 - u32 mode, crci = 0; 36 + struct gsbi_info *gsbi; 37 + 38 + gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL); 39 + 40 + if (!gsbi) 41 + return -ENOMEM; 32 42 33 43 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 34 44 base = devm_ioremap_resource(&pdev->dev, res); 35 45 if (IS_ERR(base)) 36 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 49 dev_err(&pdev->dev, "missing mode configuration\n"); 40 50 return -EINVAL; 41 51 } 42 52 43 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"); 49 - if (IS_ERR(hclk)) 50 - return PTR_ERR(hclk); 62 + clk_prepare_enable(gsbi->hclk); 51 63 52 - clk_prepare_enable(hclk); 53 - 54 - writel_relaxed((mode << GSBI_PROTOCOL_SHIFT) | crci, 64 + writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci, 55 65 base + GSBI_CTRL_REG); 56 66 57 67 /* make sure the gsbi control write is not reordered */ 58 68 wmb(); 59 69 60 - clk_disable_unprepare(hclk); 70 + platform_set_drvdata(pdev, gsbi); 61 71 62 - return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 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); 80 + 81 + return 0; 63 82 } 64 83 65 84 static const struct of_device_id gsbi_dt_match[] = { ··· 95 76 .of_match_table = gsbi_dt_match, 96 77 }, 97 78 .probe = gsbi_probe, 79 + .remove = gsbi_remove, 98 80 }; 99 81 100 82 module_platform_driver(gsbi_driver);