summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2020-11-17 00:51:01 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2020-11-17 01:37:09 +0300
commit18576aaaa49bf249aef0b72dd12fc452fccb6aed (patch)
treee3f3d79d24a0e6966b33fbdbbbecfe3bb2932efb /meta-openbmc-mods/meta-common/recipes-kernel
parent989cbcf37fea988ef6b76b9bc1cc5774bacda2cf (diff)
downloadopenbmc-18576aaaa49bf249aef0b72dd12fc452fccb6aed.tar.xz
Update to internal 0.74-155
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch512
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0121-Add-a-WA-to-defer-flash-writes-on-PS_ALERT_N-asserti.patch191
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0123-peci-fix-error-handling-in-peci_dev_ioctl.patch43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/1001-Igore-0x3FF-in-aspeed_adc-driver.patch75
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend4
6 files changed, 829 insertions, 4 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
index 088e1a02b..7a9a5626c 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
@@ -1,4 +1,4 @@
-From 7ad89fd032d56cc20622d34cf9d0d09adacb2796 Mon Sep 17 00:00:00 2001
+From e82178e44348a8594bc4ae2c3c5473336033483f Mon Sep 17 00:00:00 2001
From: Yuan Li <yuan.li@linux.intel.com>
Date: Tue, 19 Sep 2017 15:55:39 +0800
Subject: [PATCH] arm: dts: add DTS for Intel ast2500 platforms
@@ -24,7 +24,7 @@ Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
new file mode 100644
-index 000000000000..7a09ca54f161
+index 000000000000..09198052fdd5
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
@@ -0,0 +1,477 @@
@@ -56,9 +56,9 @@ index 000000000000..7a09ca54f161
+ #size-cells = <1>;
+ ranges;
+
-+ vga_memory: framebuffer@7f000000 {
++ vga_memory: framebuffer@9f000000 {
+ no-map;
-+ reg = <0x7f000000 0x01000000>;
++ reg = <0x9f000000 0x01000000>;
+ };
+
+ gfx_memory: framebuffer {
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch
new file mode 100644
index 000000000..3474f0c8b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch
@@ -0,0 +1,512 @@
+From 82109f3a6a9d044e7244f186eff53dac0bbe87fe Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 29 Sep 2020 16:29:28 -0700
+Subject: [PATCH] media: aspeed: adjust irq enabling timing and resource
+ handling
+
+This commit makes irq enabling to be after video engine
+initialization to avoid any garbage interrupt handling in
+uninitialized state. Also, this commit changes behavior of DMA
+memory allocation for frame buffers and JPEG header buffer from
+dynamic to static for better performance and to avoid any potential
+memory corruption issue caused by invalid DMA address or length.
+This commit also changes VR004[5] bit handling logic to set the bit
+only when capture and compression is triggered.
+
+Also, it fixes the clock enabling flow to give a sufficient delay
+to the video engine hardware to make it get stablized itself.
+Currently, only eclk is coupled with SCU04[6] reset flag for
+video engine so 10ms of delay will be made by the clk-aspeed module
+when this driver enables eclk. Thus, clock enabling order should
+be vclk and then eclk to get sufficient delay after enabling
+clocks and resetting the hardware.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/media/platform/aspeed-video.c | 245 ++++++++++++++++----------
+ 1 file changed, 151 insertions(+), 94 deletions(-)
+
+diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
+index a09cdb148c53..cf49c52fa5f0 100644
+--- a/drivers/media/platform/aspeed-video.c
++++ b/drivers/media/platform/aspeed-video.c
+@@ -52,9 +52,12 @@
+
+ #define VE_MAX_SRC_BUFFER_SIZE 0x8ca000 /* 1920 * 1200, 32bpp */
+ #define VE_JPEG_HEADER_SIZE 0x006000 /* 512 * 12 * 4 */
++#define VE_MAX_COMP_BUFFER_SIZE 0x400000 /* 128KB * 32 */
++#define VE_MAX_BCD_FLAG_BUFFER_SIZE 0x008ca0 /* (1920 / 4) * (1200 / 4) */
+
+ #define VE_PROTECTION_KEY 0x000
+ #define VE_PROTECTION_KEY_UNLOCK 0x1a038aa8
++#define VE_PROTECTION_KEY_LOCK 0x0
+
+ #define VE_SEQ_CTRL 0x004
+ #define VE_SEQ_CTRL_TRIG_MODE_DET BIT(0)
+@@ -105,6 +108,8 @@
+ #define VE_SCALING_FILTER2 0x020
+ #define VE_SCALING_FILTER3 0x024
+
++#define VE_BCD_CTRL 0x02c
++
+ #define VE_CAP_WINDOW 0x030
+ #define VE_COMP_WINDOW 0x034
+ #define VE_COMP_PROC_OFFSET 0x038
+@@ -113,6 +118,7 @@
+ #define VE_SRC0_ADDR 0x044
+ #define VE_SRC_SCANLINE_OFFSET 0x048
+ #define VE_SRC1_ADDR 0x04c
++#define VE_BCD_ADDR 0x050
+ #define VE_COMP_ADDR 0x054
+
+ #define VE_STREAM_BUF_SIZE 0x058
+@@ -168,6 +174,9 @@
+ #define VE_SYNC_STATUS_VSYNC_SHF 16
+ #define VE_SYNC_STATUS_VSYNC GENMASK(27, VE_SYNC_STATUS_VSYNC_SHF)
+
++#define VE_VM_SRC_ADDR 0x244
++#define VE_VM_COMP_ADDR 0x254
++
+ #define VE_INTERRUPT_CTRL 0x304
+ #define VE_INTERRUPT_STATUS 0x308
+ #define VE_INTERRUPT_MODE_DETECT_WD BIT(0)
+@@ -234,8 +243,11 @@ struct aspeed_video {
+ unsigned int sequence;
+
+ unsigned int max_compressed_size;
++ struct reserved_mem *rsvd_mem;
+ struct aspeed_video_addr srcs[2];
+- struct aspeed_video_addr jpeg;
++ struct aspeed_video_addr jpeg_hdr;
++ struct aspeed_video_addr comp;
++ struct aspeed_video_addr bcd;
+
+ bool yuv420;
+ unsigned int frame_rate;
+@@ -439,6 +451,7 @@ static int aspeed_video_start_frame(struct aspeed_video *video)
+ unsigned long flags;
+ struct aspeed_video_buffer *buf;
+ u32 seq_ctrl = aspeed_video_read(video, VE_SEQ_CTRL);
++ u32 comp_ctrl;
+
+ if (video->v4l2_input_status) {
+ dev_dbg(video->dev, "No signal; don't start frame\n");
+@@ -467,12 +480,23 @@ static int aspeed_video_start_frame(struct aspeed_video *video)
+ aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
+ aspeed_video_write(video, VE_COMP_OFFSET, 0);
+ aspeed_video_write(video, VE_COMP_ADDR, addr);
++ comp_ctrl = VE_COMP_CTRL_RSVD |
++ FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
++ FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
++ aspeed_video_update(video, VE_COMP_CTRL,
++ VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR,
++ comp_ctrl);
+
+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
+ VE_INTERRUPT_COMP_COMPLETE);
+
++ /* VE_SEQ_CTRL_AUTO_COMP should be set before VE_SEQ_CTRL_TRIG_COMP */
++ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_AUTO_COMP);
++ if (video->yuv420)
++ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420);
+ aspeed_video_update(video, VE_SEQ_CTRL, 0,
+- VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP);
++ VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP |
++ VE_SEQ_CTRL_JPEG_MODE);
+
+ return 0;
+ }
+@@ -497,8 +521,8 @@ static void aspeed_video_off(struct aspeed_video *video)
+ aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
+
+ /* Turn off the relevant clocks */
+- clk_disable(video->vclk);
+ clk_disable(video->eclk);
++ clk_disable(video->vclk);
+
+ clear_bit(VIDEO_CLOCKS_ON, &video->flags);
+ }
+@@ -509,8 +533,8 @@ static void aspeed_video_on(struct aspeed_video *video)
+ return;
+
+ /* Turn on the relevant clocks */
+- clk_enable(video->eclk);
+ clk_enable(video->vclk);
++ clk_enable(video->eclk);
+
+ set_bit(VIDEO_CLOCKS_ON, &video->flags);
+ }
+@@ -602,7 +626,10 @@ static irqreturn_t aspeed_video_irq(int irq, void *arg)
+ aspeed_video_update(video, VE_SEQ_CTRL,
+ VE_SEQ_CTRL_TRIG_CAPTURE |
+ VE_SEQ_CTRL_FORCE_IDLE |
+- VE_SEQ_CTRL_TRIG_COMP, 0);
++ VE_SEQ_CTRL_TRIG_COMP |
++ VE_SEQ_CTRL_AUTO_COMP |
++ VE_SEQ_CTRL_YUV420 |
++ VE_SEQ_CTRL_JPEG_MODE, 0);
+ aspeed_video_update(video, VE_INTERRUPT_CTRL,
+ VE_INTERRUPT_COMP_COMPLETE, 0);
+ aspeed_video_write(video, VE_INTERRUPT_STATUS,
+@@ -686,6 +713,9 @@ static bool aspeed_video_alloc_buf(struct aspeed_video *video,
+ static void aspeed_video_free_buf(struct aspeed_video *video,
+ struct aspeed_video_addr *addr)
+ {
++ if (!addr->virt)
++ return;
++
+ dma_free_coherent(video->dev, addr->size, addr->virt, addr->dma);
+ addr->size = 0;
+ addr->dma = 0ULL;
+@@ -824,14 +854,10 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
+ det->width = (video->frame_right - video->frame_left) + 1;
+ video->v4l2_input_status = 0;
+
+- /*
+- * Enable mode-detect watchdog, resolution-change watchdog and
+- * automatic compression after frame capture.
+- */
++ /* Enable mode-detect watchdog and resolution-change watchdog */
+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
+ VE_INTERRUPT_MODE_DETECT_WD);
+- aspeed_video_update(video, VE_SEQ_CTRL, 0,
+- VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG);
++ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_EN_WATCHDOG);
+
+ dev_dbg(video->dev, "Got resolution: %dx%d\n", det->width,
+ det->height);
+@@ -880,64 +906,38 @@ static void aspeed_video_set_resolution(struct aspeed_video *video)
+ } else {
+ aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_DIRECT_FETCH);
+ }
+-
+- size *= 4;
+-
+- if (size != video->srcs[0].size) {
+- if (video->srcs[0].size)
+- aspeed_video_free_buf(video, &video->srcs[0]);
+- if (video->srcs[1].size)
+- aspeed_video_free_buf(video, &video->srcs[1]);
+-
+- if (!aspeed_video_alloc_buf(video, &video->srcs[0], size))
+- goto err_mem;
+- if (!aspeed_video_alloc_buf(video, &video->srcs[1], size))
+- goto err_mem;
+-
+- aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
+- aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
+- }
+-
+- return;
+-
+-err_mem:
+- dev_err(video->dev, "Failed to allocate source buffers\n");
+-
+- if (video->srcs[0].size)
+- aspeed_video_free_buf(video, &video->srcs[0]);
+ }
+
+ static void aspeed_video_init_regs(struct aspeed_video *video)
+ {
+- u32 comp_ctrl = VE_COMP_CTRL_RSVD |
+- FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
+- FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
+ u32 ctrl = VE_CTRL_AUTO_OR_CURSOR;
+- u32 seq_ctrl = VE_SEQ_CTRL_JPEG_MODE;
+
+ if (video->frame_rate)
+ ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate);
+
+- if (video->yuv420)
+- seq_ctrl |= VE_SEQ_CTRL_YUV420;
+-
+ /* Unlock VE registers */
+ aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_UNLOCK);
+
++ /* Set buffer addresses */
++ aspeed_video_write(video, VE_MEM_RESTRICT_START, video->rsvd_mem->base);
++ aspeed_video_write(video, VE_MEM_RESTRICT_END,
++ video->rsvd_mem->base + video->rsvd_mem->size);
++ aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg_hdr.dma);
++ aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
++ aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
++ aspeed_video_write(video, VE_BCD_ADDR, video->bcd.dma);
++ aspeed_video_write(video, VE_VM_SRC_ADDR, video->srcs[0].dma);
++ aspeed_video_write(video, VE_VM_COMP_ADDR, video->comp.dma);
++
+ /* Disable interrupts */
+ aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);
+ aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
+
+- /* Clear the offset */
+- aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
+- aspeed_video_write(video, VE_COMP_OFFSET, 0);
+-
+- aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma);
+-
+ /* Set control registers */
+- aspeed_video_write(video, VE_SEQ_CTRL, seq_ctrl);
++ aspeed_video_write(video, VE_SEQ_CTRL, 0);
++ aspeed_video_write(video, VE_COMP_CTRL, 0);
++ aspeed_video_write(video, VE_BCD_CTRL, 0);
+ aspeed_video_write(video, VE_CTRL, ctrl);
+- aspeed_video_write(video, VE_COMP_CTRL, comp_ctrl);
+
+ /* Don't downscale */
+ aspeed_video_write(video, VE_SCALING_FACTOR, 0x10001000);
+@@ -975,11 +975,8 @@ static void aspeed_video_stop(struct aspeed_video *video)
+
+ aspeed_video_off(video);
+
+- if (video->srcs[0].size)
+- aspeed_video_free_buf(video, &video->srcs[0]);
+-
+- if (video->srcs[1].size)
+- aspeed_video_free_buf(video, &video->srcs[1]);
++ /* Lock VE registers */
++ aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_LOCK);
+
+ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
+ video->flags = 0;
+@@ -1275,8 +1272,9 @@ static void aspeed_video_update_jpeg_quality(struct aspeed_video *video)
+
+ static void aspeed_video_update_subsampling(struct aspeed_video *video)
+ {
+- if (video->jpeg.virt)
+- aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
++ if (video->jpeg_hdr.virt)
++ aspeed_video_init_jpeg_table(video->jpeg_hdr.virt,
++ video->yuv420);
+
+ if (video->yuv420)
+ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420);
+@@ -1511,6 +1509,8 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+ struct v4l2_device *v4l2_dev = &video->v4l2_dev;
+ struct vb2_queue *vbq = &video->queue;
+ struct video_device *vdev = &video->vdev;
++ struct device *dev = video->dev;
++ int irq;
+ int rc;
+
+ video->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG;
+@@ -1535,12 +1535,9 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+ V4L2_JPEG_CHROMA_SUBSAMPLING_444);
+
+ if (video->ctrl_handler.error) {
+- v4l2_ctrl_handler_free(&video->ctrl_handler);
+- v4l2_device_unregister(v4l2_dev);
+-
+ dev_err(video->dev, "Failed to init controls: %d\n",
+ video->ctrl_handler.error);
+- return rc;
++ goto err_release_v4l2_dev;
+ }
+
+ v4l2_dev->ctrl_handler = &video->ctrl_handler;
+@@ -1558,11 +1555,8 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+
+ rc = vb2_queue_init(vbq);
+ if (rc) {
+- v4l2_ctrl_handler_free(&video->ctrl_handler);
+- v4l2_device_unregister(v4l2_dev);
+-
+ dev_err(video->dev, "Failed to init vb2 queue\n");
+- return rc;
++ goto err_release_v4l2_dev;
+ }
+
+ vdev->queue = vbq;
+@@ -1580,36 +1574,41 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+ video_set_drvdata(vdev, video);
+ rc = video_register_device(vdev, VFL_TYPE_GRABBER, 0);
+ if (rc) {
+- vb2_queue_release(vbq);
+- v4l2_ctrl_handler_free(&video->ctrl_handler);
+- v4l2_device_unregister(v4l2_dev);
+-
+ dev_err(video->dev, "Failed to register video device\n");
+- return rc;
++ goto err_release_vb2_queue;
+ }
+
+- return 0;
+-}
+-
+-static int aspeed_video_init(struct aspeed_video *video)
+-{
+- int irq;
+- int rc;
+- struct device *dev = video->dev;
+-
+ irq = irq_of_parse_and_map(dev->of_node, 0);
+ if (!irq) {
+ dev_err(dev, "Unable to find IRQ\n");
+- return -ENODEV;
++ rc = -ENODEV;
++ goto err_release_vb2_queue;
+ }
+
+ rc = devm_request_threaded_irq(dev, irq, NULL, aspeed_video_irq,
+ IRQF_ONESHOT, DEVICE_NAME, video);
+- if (rc < 0) {
++ if (rc) {
+ dev_err(dev, "Unable to request IRQ %d\n", irq);
+- return rc;
++ goto err_release_vb2_queue;
+ }
+
++ return 0;
++
++err_release_vb2_queue:
++ vb2_queue_release(vbq);
++err_release_v4l2_dev:
++ v4l2_ctrl_handler_free(&video->ctrl_handler);
++ v4l2_device_unregister(v4l2_dev);
++
++ return rc;
++}
++
++static int aspeed_video_init(struct aspeed_video *video)
++{
++ int rc;
++ struct device *dev = video->dev;
++ struct device_node *node;
++
+ video->eclk = devm_clk_get(dev, "eclk");
+ if (IS_ERR(video->eclk)) {
+ dev_err(dev, "Unable to get ECLK\n");
+@@ -1631,7 +1630,24 @@ static int aspeed_video_init(struct aspeed_video *video)
+ if (rc)
+ goto err_unprepare_eclk;
+
+- of_reserved_mem_device_init(dev);
++ rc = of_reserved_mem_device_init(dev);
++ if (rc) {
++ dev_err(dev, "Unable to get reserved memory %d\n", rc);
++ goto err_unprepare_eclk;
++ }
++
++ node = of_parse_phandle(dev->of_node, "memory-region", 0);
++ if (!node) {
++ rc = -ENOENT;
++ goto err_unprepare_eclk;
++ }
++
++ video->rsvd_mem = of_reserved_mem_lookup(node);
++ of_node_put(node);
++ if (!video->rsvd_mem) {
++ rc = -ENOENT;
++ goto err_unprepare_eclk;
++ }
+
+ rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (rc) {
+@@ -1639,17 +1655,55 @@ static int aspeed_video_init(struct aspeed_video *video)
+ goto err_release_reserved_mem;
+ }
+
+- if (!aspeed_video_alloc_buf(video, &video->jpeg,
++ if (!aspeed_video_alloc_buf(video, &video->jpeg_hdr,
+ VE_JPEG_HEADER_SIZE)) {
+ dev_err(dev, "Failed to allocate DMA for JPEG header\n");
+ rc = -ENOMEM;
+ goto err_release_reserved_mem;
+ }
+
+- aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
++ if (!aspeed_video_alloc_buf(video, &video->srcs[0],
++ VE_MAX_SRC_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for SRCS[0]\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ if (!aspeed_video_alloc_buf(video, &video->srcs[1],
++ VE_MAX_SRC_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for SRCS[1]\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ if (!aspeed_video_alloc_buf(video, &video->comp,
++ VE_MAX_COMP_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for compressed video\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ if (!aspeed_video_alloc_buf(video, &video->bcd,
++ VE_MAX_BCD_FLAG_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for BCD flag\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ aspeed_video_init_jpeg_table(video->jpeg_hdr.virt, video->yuv420);
++
++ aspeed_video_on(video);
++ aspeed_video_init_regs(video);
++ aspeed_video_off(video);
+
+ return 0;
+
++err_release_dma_mem:
++ aspeed_video_free_buf(video, &video->comp);
++ aspeed_video_free_buf(video, &video->bcd);
++ aspeed_video_free_buf(video, &video->jpeg_hdr);
++ aspeed_video_free_buf(video, &video->srcs[0]);
++ aspeed_video_free_buf(video, &video->srcs[1]);
+ err_release_reserved_mem:
+ of_reserved_mem_device_release(dev);
+ clk_unprepare(video->vclk);
+@@ -1662,7 +1716,6 @@ static int aspeed_video_init(struct aspeed_video *video)
+ static int aspeed_video_probe(struct platform_device *pdev)
+ {
+ int rc;
+- struct resource *res;
+ struct aspeed_video *video =
+ devm_kzalloc(&pdev->dev, sizeof(*video), GFP_KERNEL);
+
+@@ -1677,10 +1730,7 @@ static int aspeed_video_probe(struct platform_device *pdev)
+ INIT_DELAYED_WORK(&video->res_work, aspeed_video_resolution_work);
+ INIT_LIST_HEAD(&video->buffers);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-
+- video->base = devm_ioremap_resource(video->dev, res);
+-
++ video->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(video->base))
+ return PTR_ERR(video->base);
+
+@@ -1689,8 +1739,12 @@ static int aspeed_video_probe(struct platform_device *pdev)
+ return rc;
+
+ rc = aspeed_video_setup_video(video);
+- if (rc)
++ if (rc) {
++ of_reserved_mem_device_release(video->dev);
++ clk_unprepare(video->vclk);
++ clk_unprepare(video->eclk);
+ return rc;
++ }
+
+ return 0;
+ }
+@@ -1714,8 +1768,11 @@ static int aspeed_video_remove(struct platform_device *pdev)
+
+ v4l2_device_unregister(v4l2_dev);
+
+- dma_free_coherent(video->dev, VE_JPEG_HEADER_SIZE, video->jpeg.virt,
+- video->jpeg.dma);
++ aspeed_video_free_buf(video, &video->comp);
++ aspeed_video_free_buf(video, &video->bcd);
++ aspeed_video_free_buf(video, &video->jpeg_hdr);
++ aspeed_video_free_buf(video, &video->srcs[0]);
++ aspeed_video_free_buf(video, &video->srcs[1]);
+
+ of_reserved_mem_device_release(dev);
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0121-Add-a-WA-to-defer-flash-writes-on-PS_ALERT_N-asserti.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0121-Add-a-WA-to-defer-flash-writes-on-PS_ALERT_N-asserti.patch
new file mode 100644
index 000000000..0c9bae00d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0121-Add-a-WA-to-defer-flash-writes-on-PS_ALERT_N-asserti.patch
@@ -0,0 +1,191 @@
+From 90035d4ef6ffb7893f629fa427db77c79e1e50e7 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Sat, 24 Oct 2020 13:43:23 -0700
+Subject: [PATCH] Add a WA to defer flash writes on PS_ALERT_N assertion
+
+To prevent SPI flash corruption, this commit adds a WA which monitors
+PS_ALERT_N signal for detecting AC loss and it defers flash writes
+when the signal is asserted. Actually, the PS_ALERT_N is asserted
+even when PSU is in an unhealthy state so it also adds 10 seconds
+of timeout for the deferring that covers AC loss case effectively.
+If PSU gets back to healthy state, flash writes will be continued
+immediately.
+
+Note: This would be a customization for some specific platforms
+and this is a WA to cover a defect of H/W design. Do not try
+upstream it.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ .../arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 7 ++-
+ .../arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 4 ++
+ drivers/mtd/spi-nor/aspeed-smc.c | 61 +++++++++++++++++++
+ 3 files changed, 71 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+index e4ac4e3696f5..74fd5c52d7e3 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+@@ -3,6 +3,7 @@
+ #include "aspeed-g5.dtsi"
+ #include <dt-bindings/gpio/aspeed-gpio.h>
+ #include <dt-bindings/i2c/i2c.h>
++#include <dt-bindings/interrupt-controller/irq.h>
+
+ / {
+ model = "Intel AST2500 BMC";
+@@ -92,6 +93,10 @@
+ };
+
+ &fmc {
++ /delete-property/ interrupts;
++ interrupts-extended = <&vic 19>,
++ <&gpio ASPEED_GPIO(AA, 1) IRQ_TYPE_EDGE_BOTH>;
++ ps-alert-gpio = <&gpio ASPEED_GPIO(AA, 1) GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ flash@0 {
+ status = "okay";
+@@ -185,7 +190,7 @@
+ /*X0-X7*/ "","","","","","","","",
+ /*Y0-Y7*/ "SIO_S3","SIO_S5","","SIO_ONCONTROL","","","","",
+ /*Z0-Z7*/ "","SIO_POWER_GOOD","","","","","","",
+- /*AA0-AA7*/ "P3VBAT_BRIDGE_EN","","","","PREQ_N","TCK_MUX_SEL","SMI","POST_COMPLETE",
++ /*AA0-AA7*/ "P3VBAT_BRIDGE_EN","IRQ_SML1_PMBUS_BMC_ALERT_N","","","PREQ_N","TCK_MUX_SEL","SMI","POST_COMPLETE",
+ /*AB0-AB7*/ "","NMI_BUTTON","ID_BUTTON","PS_PWROK","","","","",
+ /*AC0-AC7*/ "","","","","","","","";
+ };
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+index e9cea7b63836..0ff929a68dd4 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+@@ -85,6 +85,10 @@
+ };
+
+ &fmc {
++ /delete-property/ interrupts;
++ interrupts-extended = <&gic GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
++ <&gpio0 ASPEED_GPIO(Y, 3) IRQ_TYPE_EDGE_BOTH>;
++ ps-alert-gpio = <&gpio0 ASPEED_GPIO(Y, 3) GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ flash@0 {
+ status = "okay";
+diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
+index 6e2f3802d162..397c2998e620 100644
+--- a/drivers/mtd/spi-nor/aspeed-smc.c
++++ b/drivers/mtd/spi-nor/aspeed-smc.c
+@@ -9,12 +9,14 @@
+ #include <linux/clk.h>
+ #include <linux/device.h>
+ #include <linux/io.h>
++#include <linux/gpio.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/spi-nor.h>
+ #include <linux/of.h>
++#include <linux/of_gpio.h>
+ #include <linux/of_platform.h>
+ #include <linux/sizes.h>
+ #include <linux/slab.h>
+@@ -216,10 +218,16 @@ struct aspeed_smc_controller {
+ u32 ahb_window_size; /* full mapping window size */
+
+ unsigned long clk_frequency;
++ unsigned int ps_alert_gpio;
+
+ struct aspeed_smc_chip *chips[0]; /* pointers to attached chips */
+ };
+
++static unsigned long aspeed_smc_flags = 0;
++#define FLAG_DEFER_WRITE 0
++#define WRITE_DEFER_MSEC 100 /* 100ms */
++#define WRITE_DEFER_MAX_COUNT 100 /* 100 x 100 = 10secs */
++
+ #define ASPEED_SPI_DEFAULT_FREQ 50000000
+
+ /*
+@@ -411,6 +419,17 @@ static int aspeed_smc_write_to_ahb(void __iomem *dst, const void *buf,
+ size_t len)
+ {
+ size_t offset = 0;
++ int defer_cnt = 0;
++
++ while (test_bit(FLAG_DEFER_WRITE, &aspeed_smc_flags)) {
++ pr_warn("%s deferring write, count: %d\n", DEVICE_NAME,
++ defer_cnt);
++ msleep(WRITE_DEFER_MSEC);
++ if (defer_cnt++ > WRITE_DEFER_MAX_COUNT) {
++ clear_bit(FLAG_DEFER_WRITE, &aspeed_smc_flags);
++ break;
++ }
++ }
+
+ if (IS_ALIGNED((uintptr_t)dst, sizeof(uintptr_t)) &&
+ IS_ALIGNED((uintptr_t)buf, sizeof(uintptr_t))) {
+@@ -1363,6 +1382,21 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
+ return ret;
+ }
+
++static irqreturn_t aspeed_smc_ps_alert_irq(int irq, void *arg)
++{
++ struct aspeed_smc_controller *controller = arg;
++
++ if (gpio_get_value(controller->ps_alert_gpio)) {
++ clear_bit(FLAG_DEFER_WRITE, &aspeed_smc_flags);
++ dev_warn(controller->dev, "clear FLAG_DEFER_WRITE\n");
++ } else {
++ set_bit(FLAG_DEFER_WRITE, &aspeed_smc_flags);
++ dev_warn(controller->dev, "set FLAG_DEFER_WRITE\n");
++ }
++
++ return IRQ_HANDLED;
++}
++
+ static int aspeed_smc_probe(struct platform_device *pdev)
+ {
+ struct device_node *np = pdev->dev.of_node;
+@@ -1373,6 +1407,7 @@ static int aspeed_smc_probe(struct platform_device *pdev)
+ struct clk *clk;
+ struct resource *res;
+ int ret;
++ int irq;
+
+ match = of_match_device(aspeed_smc_matches, &pdev->dev);
+ if (!match || !match->data)
+@@ -1409,6 +1444,32 @@ static int aspeed_smc_probe(struct platform_device *pdev)
+ controller->clk_frequency = clk_get_rate(clk);
+ devm_clk_put(&pdev->dev, clk);
+
++ controller->ps_alert_gpio = of_get_named_gpio(np, "ps-alert-gpio", 0);
++ if (!gpio_is_valid(controller->ps_alert_gpio)) {
++ dev_err(dev, "No valid ps-alert-gpio\n");
++ ret = controller->ps_alert_gpio;
++ return ret;
++ }
++
++ ret = devm_gpio_request_one(dev, controller->ps_alert_gpio,
++ GPIOF_DIR_IN, "ps-alert-gpio");
++ if (ret) {
++ dev_err(dev, "request gpio failed %d\n", ret);
++ return ret;
++ }
++
++ irq = platform_get_irq(pdev, 1);
++ if (irq < 0)
++ return irq;
++
++ ret = devm_request_irq(&pdev->dev, irq, aspeed_smc_ps_alert_irq,
++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
++ "ps-alert-irq", controller);
++ if (ret) {
++ dev_err(dev, "request irq failed %d\n", ret);
++ return ret;
++ }
++
+ ret = aspeed_smc_setup_flash(controller, np, res);
+ if (ret)
+ dev_err(dev, "Aspeed SMC probe failed %d\n", ret);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0123-peci-fix-error-handling-in-peci_dev_ioctl.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0123-peci-fix-error-handling-in-peci_dev_ioctl.patch
new file mode 100644
index 000000000..f82a08a1f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0123-peci-fix-error-handling-in-peci_dev_ioctl.patch
@@ -0,0 +1,43 @@
+From f0a37caf96a1583ed190abd7837f124dfadd5743 Mon Sep 17 00:00:00 2001
+From: Zev Weiss <zev@bewilderbeest.net>
+Date: Sun, 27 Sep 2020 07:27:33 +1000
+Subject: [PATCH] peci: fix error-handling in peci_dev_ioctl()
+
+peci_get_xfer_msg() returns NULL on failure, not an ERR_PTR. Also
+avoid calling kfree() on an ERR_PTR.
+
+Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
+Reviewed-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+---
+ drivers/peci/peci-dev.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/peci/peci-dev.c b/drivers/peci/peci-dev.c
+index c574d13213af..8104468864bf 100644
+--- a/drivers/peci/peci-dev.c
++++ b/drivers/peci/peci-dev.c
+@@ -122,8 +122,8 @@ static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg)
+ }
+
+ xmsg = peci_get_xfer_msg(uxmsg.tx_len, uxmsg.rx_len);
+- if (IS_ERR(xmsg)) {
+- ret = PTR_ERR(xmsg);
++ if (!xmsg) {
++ ret = -ENOMEM;
+ break;
+ }
+
+@@ -172,7 +172,8 @@ static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg)
+ }
+
+ peci_put_xfer_msg(xmsg);
+- kfree(msg);
++ if (!IS_ERR(msg))
++ kfree(msg);
+
+ return (long)ret;
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/1001-Igore-0x3FF-in-aspeed_adc-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/1001-Igore-0x3FF-in-aspeed_adc-driver.patch
new file mode 100644
index 000000000..5f74d6993
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/1001-Igore-0x3FF-in-aspeed_adc-driver.patch
@@ -0,0 +1,75 @@
+From d1fb9431676f37ddf2a8673f84368793e5a88ab0 Mon Sep 17 00:00:00 2001
+From: Zhikui Ren <zhikui.ren@intel.com>
+Date: Mon, 14 Sep 2020 12:02:03 -0700
+Subject: [PATCH] Igore 0x3FF in aspeed_adc driver
+
+ADC are 10 bits, 0x3FF means voltage exceeded reference voltage
+Several ADC voltages reported rare transient events corresponding
+to this value. Aspeed was consulted and did not identify possible
+root causes. As a work around, igore these valuse and return
+previous readings. If there were real issues, a slightly different
+reading like 0x3FE will still be returned and resulted in a sensor
+event.
+
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+---
+ drivers/iio/adc/aspeed_adc.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
+index 1dd5a97a16bc..c115797c4cc5 100644
+--- a/drivers/iio/adc/aspeed_adc.c
++++ b/drivers/iio/adc/aspeed_adc.c
+@@ -53,6 +53,9 @@
+ #define ASPEED_ADC_INIT_POLLING_TIME 500
+ #define ASPEED_ADC_INIT_TIMEOUT 500000
+
++#define ASPEED_ADC_CHANNELS_MAX 16
++#define ASPEED_ADC_RAW_VALUE_MAX 0x3ff
++
+ struct aspeed_adc_model_data {
+ const char *model_name;
+ unsigned int min_sampling_rate; // Hz
+@@ -71,6 +74,7 @@ struct aspeed_adc_data {
+ struct clk_hw *clk_scaler;
+ struct reset_control *rst;
+ int cv;
++ int channel_raw_value[ASPEED_ADC_CHANNELS_MAX];
+ };
+
+ #define ASPEED_CHAN(_idx, _data_reg_addr) { \
+@@ -124,6 +128,13 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ *val = readw(data->base + chan->address);
++ if (*val == ASPEED_ADC_RAW_VALUE_MAX) {
++ *val = data->channel_raw_value[chan->channel];
++ pr_err("aspeed_adc: channel %d drop invalid raw reading 0x3FF %d\n",
++ chan->channel, ASPEED_ADC_RAW_VALUE_MAX);
++ } else {
++ data->channel_raw_value[chan->channel] = *val;
++ }
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+@@ -206,6 +217,7 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ int ret;
+ u32 eng_ctrl = 0;
+ u32 adc_engine_control_reg_val;
++ int i;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data));
+ if (!indio_dev)
+@@ -298,6 +310,9 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+
+ data->cv = 0x200 - (readl(data->base + 0x10) & GENMASK(9, 0));
+
++ for (i = 0; i < ASPEED_ADC_CHANNELS_MAX; i++)
++ data->channel_raw_value[i] = ASPEED_ADC_RAW_VALUE_MAX;
++
+ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL |
+ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL);
+ printk(KERN_INFO "aspeed_adc: cv %d \n", data->cv);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
index 271b6035e..908dc0a8d 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -90,6 +90,10 @@ SRC_URI += " \
file://0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch \
file://0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch \
file://0119-Handle-pending-eSPI-HOST-OOB-RESET-VW-events.patch \
+ file://0123-peci-fix-error-handling-in-peci_dev_ioctl.patch \
+ file://1001-Igore-0x3FF-in-aspeed_adc-driver.patch \
+ file://0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch \
+ file://0121-Add-a-WA-to-defer-flash-writes-on-PS_ALERT_N-asserti.patch \
"
# CVE-2020-16166 vulnerability fix