diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch new file mode 100644 index 000000000..220283e24 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch @@ -0,0 +1,166 @@ +From db310b43e5b444a4e2854f3d69d002c2f0d0605c Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +Date: Wed, 13 Mar 2019 15:53:24 -0700 +Subject: [PATCH] misc: Add clock control logic into Aspeed LPC MBOX driver + +If LPC MBOX driver is registered ahead of lpc-ctrl module, LPC +MBOX block will be enabled without heart beating of LCLK until +lpc-ctrl enables the LCLK. This issue causes improper handling on +host interrupts when the host sends interrupt in that time frame. +Then kernel eventually forcibly disables the interrupt with dumping +stack and printing a 'nobody cared this irq' message out. + +To prevent this issue, all LPC sub-nodes should enable LCLK +individually so this patch adds clock control logic into the LPC +MBOX driver. + +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +--- + arch/arm/boot/dts/aspeed-g4.dtsi | 1 + + arch/arm/boot/dts/aspeed-g5.dtsi | 1 + + drivers/misc/aspeed-lpc-mbox.c | 42 +++++++++++++++++++++++++++++++--------- + 3 files changed, 35 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi +index a5072ed1f823..729245b74c13 100644 +--- a/arch/arm/boot/dts/aspeed-g4.dtsi ++++ b/arch/arm/boot/dts/aspeed-g4.dtsi +@@ -389,6 +389,7 @@ + reg = <0x180 0x5c>; + interrupts = <46>; + #mbox-cells = <1>; ++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; + }; +diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi +index 6a2f161e7548..df9d63a94264 100644 +--- a/arch/arm/boot/dts/aspeed-g5.dtsi ++++ b/arch/arm/boot/dts/aspeed-g5.dtsi +@@ -493,6 +493,7 @@ + reg = <0x180 0x5c>; + interrupts = <46>; + #mbox-cells = <1>; ++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; + }; +diff --git a/drivers/misc/aspeed-lpc-mbox.c b/drivers/misc/aspeed-lpc-mbox.c +index 0933e0553953..f105d27786ac 100644 +--- a/drivers/misc/aspeed-lpc-mbox.c ++++ b/drivers/misc/aspeed-lpc-mbox.c +@@ -7,6 +7,7 @@ + * 2 of the License, or (at your option) any later version. + */ + ++#include <linux/clk.h> + #include <linux/interrupt.h> + #include <linux/mfd/syscon.h> + #include <linux/miscdevice.h> +@@ -37,7 +38,9 @@ + struct aspeed_mbox { + struct miscdevice miscdev; + struct regmap *regmap; ++ struct clk *clk; + unsigned int base; ++ int irq; + wait_queue_head_t queue; + struct mutex mutex; + }; +@@ -237,16 +240,16 @@ static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox, + struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- int rc, irq; ++ int rc; + +- irq = irq_of_parse_and_map(dev->of_node, 0); +- if (!irq) ++ mbox->irq = platform_get_irq(pdev, 0); ++ if (!mbox->irq) + return -ENODEV; + +- rc = devm_request_irq(dev, irq, aspeed_mbox_irq, +- IRQF_SHARED, DEVICE_NAME, mbox); ++ rc = devm_request_irq(dev, mbox->irq, aspeed_mbox_irq, ++ IRQF_SHARED, DEVICE_NAME, mbox); + if (rc < 0) { +- dev_err(dev, "Unable to request IRQ %d\n", irq); ++ dev_err(dev, "Unable to request IRQ %d\n", mbox->irq); + return rc; + } + +@@ -301,6 +304,19 @@ static int aspeed_mbox_probe(struct platform_device *pdev) + mutex_init(&mbox->mutex); + init_waitqueue_head(&mbox->queue); + ++ mbox->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(mbox->clk)) { ++ rc = PTR_ERR(mbox->clk); ++ if (rc != -EPROBE_DEFER) ++ dev_err(dev, "couldn't get clock\n"); ++ return rc; ++ } ++ rc = clk_prepare_enable(mbox->clk); ++ if (rc) { ++ dev_err(dev, "couldn't enable clock\n"); ++ return rc; ++ } ++ + mbox->miscdev.minor = MISC_DYNAMIC_MINOR; + mbox->miscdev.name = DEVICE_NAME; + mbox->miscdev.fops = &aspeed_mbox_fops; +@@ -308,17 +324,24 @@ static int aspeed_mbox_probe(struct platform_device *pdev) + rc = misc_register(&mbox->miscdev); + if (rc) { + dev_err(dev, "Unable to register device\n"); +- return rc; ++ goto err; + } + + rc = aspeed_mbox_config_irq(mbox, pdev); + if (rc) { + dev_err(dev, "Failed to configure IRQ\n"); + misc_deregister(&mbox->miscdev); +- return rc; ++ goto err; + } + ++ dev_info(&pdev->dev, "LPC mbox registered, irq %d\n", mbox->irq); ++ + return 0; ++ ++err: ++ clk_disable_unprepare(mbox->clk); ++ ++ return rc; + } + + static int aspeed_mbox_remove(struct platform_device *pdev) +@@ -326,6 +349,7 @@ static int aspeed_mbox_remove(struct platform_device *pdev) + struct aspeed_mbox *mbox = dev_get_drvdata(&pdev->dev); + + misc_deregister(&mbox->miscdev); ++ clk_disable_unprepare(mbox->clk); + + return 0; + } +@@ -335,6 +359,7 @@ static const struct of_device_id aspeed_mbox_match[] = { + { .compatible = "aspeed,ast2500-mbox" }, + { }, + }; ++MODULE_DEVICE_TABLE(of, aspeed_mbox_match); + + static struct platform_driver aspeed_mbox_driver = { + .driver = { +@@ -347,7 +372,6 @@ static struct platform_driver aspeed_mbox_driver = { + + module_platform_driver(aspeed_mbox_driver); + +-MODULE_DEVICE_TABLE(of, aspeed_mbox_match); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>"); + MODULE_DESCRIPTION("Aspeed mailbox device driver"); +-- +2.7.4 + |