From 1fc0d70f658da30091bcd49f9bf29aecd6b99ba7 Mon Sep 17 00:00:00 2001 From: "Jason M. Bills" Date: Thu, 6 Jan 2022 13:50:19 -0800 Subject: Update to internal 0.86 Signed-off-by: Jason M. Bills --- ...round-to-cover-UART-interrupt-bug-in-AST2.patch | 269 +++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0004-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch (limited to 'meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0004-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch') diff --git a/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0004-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0004-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch new file mode 100644 index 000000000..757b00a25 --- /dev/null +++ b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0004-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch @@ -0,0 +1,269 @@ +From a9b43dbf68a4b5650dd98332243d4a2951717eb5 Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo +Date: Mon, 27 Apr 2020 12:11:06 -0700 +Subject: [PATCH] Add a workaround to cover UART interrupt bug in AST2600 A0 + +This commit adds a workaround to cover UART interrupt bug in +AST2600 A0 revision. It makes infinite reading on the UART +0x7c +register for clearing abnormal interrupts in every milli-second. + +Signed-off-by: Jae Hyun Yoo +--- + .../arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 4 ++ + drivers/tty/serial/8250/8250_aspeed.c | 56 ++++++++++++++++- + drivers/tty/serial/8250/8250_early.c | 1 + + drivers/tty/serial/8250/8250_of.c | 63 +++++++++++++++++++ + 4 files changed, 123 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts +index c648c123c315..bf375634082c 100644 +--- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts ++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts +@@ -392,6 +392,7 @@ + }; + + &uart1 { ++ reg = <0x1e783000 0x20>, <0x1e6e2014 0x4>, <0x1e78307c 0x4>; + status = "okay"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default +@@ -404,6 +405,7 @@ + }; + + &uart2 { ++ reg = <0x1e78d000 0x20>, <0x1e6e2014 0x4>, <0x1e78d07c 0x4>; + status = "okay"; + pinctrl-0 = <&pinctrl_txd2_default + &pinctrl_rxd2_default +@@ -416,11 +418,13 @@ + }; + + &uart3 { ++ reg = <0x1e78e000 0x20>, <0x1e6e2014 0x4>, <0x1e78e07c 0x4>; + status = "okay"; + pinctrl-0 = <>; + }; + + &uart4 { ++ reg = <0x1e78f000 0x20>, <0x1e6e2014 0x4>, <0x1e78f07c 0x4>; + status = "okay"; + pinctrl-0 = <>; + }; +diff --git a/drivers/tty/serial/8250/8250_aspeed.c b/drivers/tty/serial/8250/8250_aspeed.c +index bb3955bb8c24..1ba4423d5e2f 100644 +--- a/drivers/tty/serial/8250/8250_aspeed.c ++++ b/drivers/tty/serial/8250/8250_aspeed.c +@@ -74,6 +74,10 @@ struct ast8250_data { + + struct ast8250_vuart vuart; + struct ast8250_udma dma; ++ ++ struct workqueue_struct *work_queue; ++ struct delayed_work work_handler; ++ void __iomem *wa_base; + }; + + static void ast8250_dma_tx_complete(int tx_rb_rptr, void *id) +@@ -336,12 +340,25 @@ static int __maybe_unused ast8250_resume(struct device *dev) + return 0; + } + ++#define WA_DELAY_JIFFIES msecs_to_jiffies(1) ++static void ast8250_clear_abnormal_int_flags(struct work_struct *work) ++{ ++ struct delayed_work *dwork = to_delayed_work(work); ++ struct ast8250_data *data = container_of(dwork, struct ast8250_data, ++ work_handler); ++ ++ (void) readl(data->wa_base); ++ queue_delayed_work(data->work_queue, &data->work_handler, ++ WA_DELAY_JIFFIES); ++} ++ + static int ast8250_probe(struct platform_device *pdev) + { + int rc; + struct uart_8250_port uart = {}; + struct uart_port *port = &uart.port; + struct device *dev = &pdev->dev; ++ void __iomem *chip_id_base; + struct ast8250_data *data; + + struct resource *res; +@@ -454,6 +471,37 @@ static int ast8250_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + + platform_set_drvdata(pdev, data); ++ ++ #define REV_ID_AST2600A0 0x05000303 ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res || resource_size(res) < 2) ++ return 0; ++ ++ data->wa_base = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(data->wa_base)) ++ return 0; ++ ++ chip_id_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(chip_id_base)) ++ return 0; ++ ++ if (readl(chip_id_base) == REV_ID_AST2600A0) { ++ data->work_queue = alloc_ordered_workqueue(pdev->name, 0); ++ if (data->work_queue) { ++ INIT_DELAYED_WORK(&data->work_handler, ++ ast8250_clear_abnormal_int_flags); ++ queue_delayed_work(data->work_queue, ++ &data->work_handler, ++ WA_DELAY_JIFFIES); ++ dev_info(dev, "AST2600 A0 WA initiated\n"); ++ } else { ++ dev_err(dev, "Can't enable AST2600 A0 UART WA\n"); ++ } ++ } ++ ++ devm_iounmap(dev, chip_id_base); ++ devm_release_mem_region(dev, res->start, resource_size(res)); ++ + return 0; + } + +@@ -464,7 +512,13 @@ static int ast8250_remove(struct platform_device *pdev) + if (data->is_vuart) + ast8250_vuart_set_enable(data, false); + +- serial8250_unregister_port(data->line); ++ if (data->work_queue) { ++ cancel_delayed_work_sync(&data->work_handler); ++ destroy_workqueue(data->work_queue); ++ } ++ ++ serial8250_unregister_port(data->line); ++ + return 0; + } + +diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c +index c171ce6db691..6d7bb63fe0c6 100644 +--- a/drivers/tty/serial/8250/8250_early.c ++++ b/drivers/tty/serial/8250/8250_early.c +@@ -180,6 +180,7 @@ OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup); + OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); + OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup); + OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup); ++OF_EARLYCON_DECLARE(uart, "aspeed,ast2600-uart", early_serial8250_setup); + + #ifdef CONFIG_SERIAL_8250_OMAP + +diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c +index bce28729dd7b..6159d8af6fef 100644 +--- a/drivers/tty/serial/8250/8250_of.c ++++ b/drivers/tty/serial/8250/8250_of.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "8250.h" + +@@ -23,6 +24,9 @@ struct of_serial_info { + struct reset_control *rst; + int type; + int line; ++ struct workqueue_struct *work_queue; ++ struct delayed_work work_handler; ++ void __iomem *wa_base; + }; + + /* +@@ -181,6 +185,18 @@ static int of_platform_serial_setup(struct platform_device *ofdev, + return ret; + } + ++#define WA_DELAY_JIFFIES msecs_to_jiffies(1) ++static void clear_abnormal_int_flags(struct work_struct *work) ++{ ++ struct delayed_work *dwork = to_delayed_work(work); ++ struct of_serial_info *info = container_of(dwork, struct of_serial_info, ++ work_handler); ++ ++ (void) readl(info->wa_base); ++ queue_delayed_work(info->work_queue, &info->work_handler, ++ WA_DELAY_JIFFIES); ++} ++ + /* + * Try to register a serial port + */ +@@ -233,6 +249,47 @@ static int of_platform_serial_probe(struct platform_device *ofdev) + if (ret < 0) + goto err_dispose; + ++ if (of_device_is_compatible(ofdev->dev.of_node, ++ "aspeed,ast2600-uart")) { ++ #define REV_ID_AST2600A0 0x05000303 ++ void __iomem *chip_id_base; ++ struct resource *res = platform_get_resource(ofdev, ++ IORESOURCE_MEM, 1); ++ ++ if (!res || resource_size(res) < 2) ++ goto skip_wa; ++ ++ info->wa_base = devm_platform_ioremap_resource(ofdev, 2); ++ if (IS_ERR(info->wa_base)) ++ goto skip_wa; ++ ++ chip_id_base = devm_ioremap_resource(&ofdev->dev, res); ++ if (IS_ERR(chip_id_base)) ++ goto skip_wa; ++ ++ if (readl(chip_id_base) == REV_ID_AST2600A0) { ++ info->work_queue = alloc_ordered_workqueue(ofdev->name, ++ 0); ++ if (info->work_queue) { ++ INIT_DELAYED_WORK(&info->work_handler, ++ clear_abnormal_int_flags); ++ queue_delayed_work(info->work_queue, ++ &info->work_handler, ++ WA_DELAY_JIFFIES); ++ dev_info(&ofdev->dev, ++ "AST2600 A0 WA initiated\n"); ++ } else { ++ dev_err(&ofdev->dev, ++ "Can't enable AST2600 A0 UART WA\n"); ++ } ++ } ++ ++ devm_iounmap(&ofdev->dev, chip_id_base); ++ devm_release_mem_region(&ofdev->dev, res->start, ++ resource_size(res)); ++ } ++ ++skip_wa: + info->type = port_type; + info->line = ret; + platform_set_drvdata(ofdev, info); +@@ -254,6 +311,11 @@ static int of_platform_serial_remove(struct platform_device *ofdev) + { + struct of_serial_info *info = platform_get_drvdata(ofdev); + ++ if (info->work_queue) { ++ cancel_delayed_work_sync(&info->work_handler); ++ destroy_workqueue(info->work_queue); ++ } ++ + serial8250_unregister_port(info->line); + + reset_control_assert(info->rst); +@@ -324,6 +386,7 @@ static const struct of_device_id of_platform_serial_table[] = { + { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, + { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, ++ { .compatible = "aspeed,ast2600-uart", .data = (void *)PORT_16550A, }, + { /* end of list */ }, + }; + MODULE_DEVICE_TABLE(of, of_platform_serial_table); +-- +2.17.1 + -- cgit v1.2.3