18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Copyright(c) 2020 Intel Corporation. All rights reserved.
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Author: Cezary Rojewski <cezary.rojewski@intel.com>
68c2ecf20Sopenharmony_ci//
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/devcoredump.h>
98c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
108c2ecf20Sopenharmony_ci#include <linux/firmware.h>
118c2ecf20Sopenharmony_ci#include <linux/pci.h>
128c2ecf20Sopenharmony_ci#include <linux/pxa2xx_ssp.h>
138c2ecf20Sopenharmony_ci#include "core.h"
148c2ecf20Sopenharmony_ci#include "messages.h"
158c2ecf20Sopenharmony_ci#include "registers.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistatic bool catpt_dma_filter(struct dma_chan *chan, void *param)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	return param == chan->device->dev;
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/*
238c2ecf20Sopenharmony_ci * Either engine 0 or 1 can be used for image loading.
248c2ecf20Sopenharmony_ci * Align with Windows driver equivalent and stick to engine 1.
258c2ecf20Sopenharmony_ci */
268c2ecf20Sopenharmony_ci#define CATPT_DMA_DEVID		1
278c2ecf20Sopenharmony_ci#define CATPT_DMA_DSP_ADDR_MASK	GENMASK(31, 20)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistruct dma_chan *catpt_dma_request_config_chan(struct catpt_dev *cdev)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	struct dma_slave_config config;
328c2ecf20Sopenharmony_ci	struct dma_chan *chan;
338c2ecf20Sopenharmony_ci	dma_cap_mask_t mask;
348c2ecf20Sopenharmony_ci	int ret;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	dma_cap_zero(mask);
378c2ecf20Sopenharmony_ci	dma_cap_set(DMA_MEMCPY, mask);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	chan = dma_request_channel(mask, catpt_dma_filter, cdev->dev);
408c2ecf20Sopenharmony_ci	if (!chan) {
418c2ecf20Sopenharmony_ci		dev_err(cdev->dev, "request channel failed\n");
428c2ecf20Sopenharmony_ci		return ERR_PTR(-ENODEV);
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	memset(&config, 0, sizeof(config));
468c2ecf20Sopenharmony_ci	config.direction = DMA_MEM_TO_DEV;
478c2ecf20Sopenharmony_ci	config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
488c2ecf20Sopenharmony_ci	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
498c2ecf20Sopenharmony_ci	config.src_maxburst = 16;
508c2ecf20Sopenharmony_ci	config.dst_maxburst = 16;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	ret = dmaengine_slave_config(chan, &config);
538c2ecf20Sopenharmony_ci	if (ret) {
548c2ecf20Sopenharmony_ci		dev_err(cdev->dev, "slave config failed: %d\n", ret);
558c2ecf20Sopenharmony_ci		dma_release_channel(chan);
568c2ecf20Sopenharmony_ci		return ERR_PTR(ret);
578c2ecf20Sopenharmony_ci	}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	return chan;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic int catpt_dma_memcpy(struct catpt_dev *cdev, struct dma_chan *chan,
638c2ecf20Sopenharmony_ci			    dma_addr_t dst_addr, dma_addr_t src_addr,
648c2ecf20Sopenharmony_ci			    size_t size)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	struct dma_async_tx_descriptor *desc;
678c2ecf20Sopenharmony_ci	enum dma_status status;
688c2ecf20Sopenharmony_ci	int ret;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	desc = dmaengine_prep_dma_memcpy(chan, dst_addr, src_addr, size,
718c2ecf20Sopenharmony_ci					 DMA_CTRL_ACK);
728c2ecf20Sopenharmony_ci	if (!desc) {
738c2ecf20Sopenharmony_ci		dev_err(cdev->dev, "prep dma memcpy failed\n");
748c2ecf20Sopenharmony_ci		return -EIO;
758c2ecf20Sopenharmony_ci	}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* enable demand mode for dma channel */
788c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, HMDC,
798c2ecf20Sopenharmony_ci			   CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id),
808c2ecf20Sopenharmony_ci			   CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id));
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	ret = dma_submit_error(dmaengine_submit(desc));
838c2ecf20Sopenharmony_ci	if (ret) {
848c2ecf20Sopenharmony_ci		dev_err(cdev->dev, "submit tx failed: %d\n", ret);
858c2ecf20Sopenharmony_ci		goto clear_hdda;
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	status = dma_wait_for_async_tx(desc);
898c2ecf20Sopenharmony_ci	ret = (status == DMA_COMPLETE) ? 0 : -EPROTO;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ciclear_hdda:
928c2ecf20Sopenharmony_ci	/* regardless of status, disable access to HOST memory in demand mode */
938c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, HMDC,
948c2ecf20Sopenharmony_ci			   CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id), 0);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	return ret;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ciint catpt_dma_memcpy_todsp(struct catpt_dev *cdev, struct dma_chan *chan,
1008c2ecf20Sopenharmony_ci			   dma_addr_t dst_addr, dma_addr_t src_addr,
1018c2ecf20Sopenharmony_ci			   size_t size)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	return catpt_dma_memcpy(cdev, chan, dst_addr | CATPT_DMA_DSP_ADDR_MASK,
1048c2ecf20Sopenharmony_ci				src_addr, size);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ciint catpt_dma_memcpy_fromdsp(struct catpt_dev *cdev, struct dma_chan *chan,
1088c2ecf20Sopenharmony_ci			     dma_addr_t dst_addr, dma_addr_t src_addr,
1098c2ecf20Sopenharmony_ci			     size_t size)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	return catpt_dma_memcpy(cdev, chan, dst_addr,
1128c2ecf20Sopenharmony_ci				src_addr | CATPT_DMA_DSP_ADDR_MASK, size);
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciint catpt_dmac_probe(struct catpt_dev *cdev)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct dw_dma_chip *dmac;
1188c2ecf20Sopenharmony_ci	int ret;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	dmac = devm_kzalloc(cdev->dev, sizeof(*dmac), GFP_KERNEL);
1218c2ecf20Sopenharmony_ci	if (!dmac)
1228c2ecf20Sopenharmony_ci		return -ENOMEM;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	dmac->regs = cdev->lpe_ba + cdev->spec->host_dma_offset[CATPT_DMA_DEVID];
1258c2ecf20Sopenharmony_ci	dmac->dev = cdev->dev;
1268c2ecf20Sopenharmony_ci	dmac->irq = cdev->irq;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
1298c2ecf20Sopenharmony_ci	if (ret)
1308c2ecf20Sopenharmony_ci		return ret;
1318c2ecf20Sopenharmony_ci	/*
1328c2ecf20Sopenharmony_ci	 * Caller is responsible for putting device in D0 to allow
1338c2ecf20Sopenharmony_ci	 * for I/O and memory access before probing DW.
1348c2ecf20Sopenharmony_ci	 */
1358c2ecf20Sopenharmony_ci	ret = dw_dma_probe(dmac);
1368c2ecf20Sopenharmony_ci	if (ret)
1378c2ecf20Sopenharmony_ci		return ret;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	cdev->dmac = dmac;
1408c2ecf20Sopenharmony_ci	return 0;
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_civoid catpt_dmac_remove(struct catpt_dev *cdev)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	/*
1468c2ecf20Sopenharmony_ci	 * As do_dma_remove() juggles with pm_runtime_get_xxx() and
1478c2ecf20Sopenharmony_ci	 * pm_runtime_put_xxx() while both ADSP and DW 'devices' are part of
1488c2ecf20Sopenharmony_ci	 * the same module, caller makes sure pm_runtime_disable() is invoked
1498c2ecf20Sopenharmony_ci	 * before removing DW to prevent postmortem resume and suspend.
1508c2ecf20Sopenharmony_ci	 */
1518c2ecf20Sopenharmony_ci	dw_dma_remove(cdev->dmac);
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic void catpt_dsp_set_srampge(struct catpt_dev *cdev, struct resource *sram,
1558c2ecf20Sopenharmony_ci				  unsigned long mask, unsigned long new)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	unsigned long old;
1588c2ecf20Sopenharmony_ci	u32 off = sram->start;
1598c2ecf20Sopenharmony_ci	u32 b = __ffs(mask);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	old = catpt_readl_pci(cdev, VDRTCTL0) & mask;
1628c2ecf20Sopenharmony_ci	dev_dbg(cdev->dev, "SRAMPGE [0x%08lx] 0x%08lx -> 0x%08lx",
1638c2ecf20Sopenharmony_ci		mask, old, new);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (old == new)
1668c2ecf20Sopenharmony_ci		return;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL0, mask, new);
1698c2ecf20Sopenharmony_ci	/* wait for SRAM power gating to propagate */
1708c2ecf20Sopenharmony_ci	udelay(60);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	/*
1738c2ecf20Sopenharmony_ci	 * Dummy read as the very first access after block enable
1748c2ecf20Sopenharmony_ci	 * to prevent byte loss in future operations.
1758c2ecf20Sopenharmony_ci	 */
1768c2ecf20Sopenharmony_ci	for_each_clear_bit_from(b, &new, fls_long(mask)) {
1778c2ecf20Sopenharmony_ci		u8 buf[4];
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci		/* newly enabled: new bit=0 while old bit=1 */
1808c2ecf20Sopenharmony_ci		if (test_bit(b, &old)) {
1818c2ecf20Sopenharmony_ci			dev_dbg(cdev->dev, "sanitize block %ld: off 0x%08x\n",
1828c2ecf20Sopenharmony_ci				b - __ffs(mask), off);
1838c2ecf20Sopenharmony_ci			memcpy_fromio(buf, cdev->lpe_ba + off, sizeof(buf));
1848c2ecf20Sopenharmony_ci		}
1858c2ecf20Sopenharmony_ci		off += CATPT_MEMBLOCK_SIZE;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_civoid catpt_dsp_update_srampge(struct catpt_dev *cdev, struct resource *sram,
1908c2ecf20Sopenharmony_ci			      unsigned long mask)
1918c2ecf20Sopenharmony_ci{
1928c2ecf20Sopenharmony_ci	struct resource *res;
1938c2ecf20Sopenharmony_ci	unsigned long new = 0;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	/* flag all busy blocks */
1968c2ecf20Sopenharmony_ci	for (res = sram->child; res; res = res->sibling) {
1978c2ecf20Sopenharmony_ci		u32 h, l;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci		h = (res->end - sram->start) / CATPT_MEMBLOCK_SIZE;
2008c2ecf20Sopenharmony_ci		l = (res->start - sram->start) / CATPT_MEMBLOCK_SIZE;
2018c2ecf20Sopenharmony_ci		new |= GENMASK(h, l);
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	/* offset value given mask's start and invert it as ON=b0 */
2058c2ecf20Sopenharmony_ci	new = ~(new << __ffs(mask)) & mask;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* disable core clock gating */
2088c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 0);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, sram, mask, new);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	/* enable core clock gating */
2138c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE,
2148c2ecf20Sopenharmony_ci			  CATPT_VDRTCTL2_DCLCGE);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ciint catpt_dsp_stall(struct catpt_dev *cdev, bool stall)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	u32 reg, val;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	val = stall ? CATPT_CS_STALL : 0;
2228c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1, CATPT_CS_STALL, val);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	return catpt_readl_poll_shim(cdev, CS1,
2258c2ecf20Sopenharmony_ci				     reg, (reg & CATPT_CS_STALL) == val,
2268c2ecf20Sopenharmony_ci				     500, 10000);
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic int catpt_dsp_reset(struct catpt_dev *cdev, bool reset)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	u32 reg, val;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	val = reset ? CATPT_CS_RST : 0;
2348c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1, CATPT_CS_RST, val);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	return catpt_readl_poll_shim(cdev, CS1,
2378c2ecf20Sopenharmony_ci				     reg, (reg & CATPT_CS_RST) == val,
2388c2ecf20Sopenharmony_ci				     500, 10000);
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_civoid lpt_dsp_pll_shutdown(struct catpt_dev *cdev, bool enable)
2428c2ecf20Sopenharmony_ci{
2438c2ecf20Sopenharmony_ci	u32 val;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	val = enable ? LPT_VDRTCTL0_APLLSE : 0;
2468c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL0, LPT_VDRTCTL0_APLLSE, val);
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_civoid wpt_dsp_pll_shutdown(struct catpt_dev *cdev, bool enable)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	u32 val;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	val = enable ? WPT_VDRTCTL2_APLLSE : 0;
2548c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, WPT_VDRTCTL2_APLLSE, val);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	u32 mask, reg, val;
2608c2ecf20Sopenharmony_ci	int ret;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	mutex_lock(&cdev->clk_mutex);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	val = lp ? CATPT_CS_LPCS : 0;
2658c2ecf20Sopenharmony_ci	reg = catpt_readl_shim(cdev, CS1) & CATPT_CS_LPCS;
2668c2ecf20Sopenharmony_ci	dev_dbg(cdev->dev, "LPCS [0x%08lx] 0x%08x -> 0x%08x",
2678c2ecf20Sopenharmony_ci		CATPT_CS_LPCS, reg, val);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	if (reg == val) {
2708c2ecf20Sopenharmony_ci		mutex_unlock(&cdev->clk_mutex);
2718c2ecf20Sopenharmony_ci		return 0;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	if (waiti) {
2758c2ecf20Sopenharmony_ci		/* wait for DSP to signal WAIT state */
2768c2ecf20Sopenharmony_ci		ret = catpt_readl_poll_shim(cdev, ISD,
2778c2ecf20Sopenharmony_ci					    reg, (reg & CATPT_ISD_DCPWM),
2788c2ecf20Sopenharmony_ci					    500, 10000);
2798c2ecf20Sopenharmony_ci		if (ret) {
2808c2ecf20Sopenharmony_ci			dev_warn(cdev->dev, "await WAITI timeout\n");
2818c2ecf20Sopenharmony_ci			/* no signal - only high clock selection allowed */
2828c2ecf20Sopenharmony_ci			if (lp) {
2838c2ecf20Sopenharmony_ci				mutex_unlock(&cdev->clk_mutex);
2848c2ecf20Sopenharmony_ci				return 0;
2858c2ecf20Sopenharmony_ci			}
2868c2ecf20Sopenharmony_ci		}
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	ret = catpt_readl_poll_shim(cdev, CLKCTL,
2908c2ecf20Sopenharmony_ci				    reg, !(reg & CATPT_CLKCTL_CFCIP),
2918c2ecf20Sopenharmony_ci				    500, 10000);
2928c2ecf20Sopenharmony_ci	if (ret)
2938c2ecf20Sopenharmony_ci		dev_warn(cdev->dev, "clock change still in progress\n");
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	/* default to DSP core & audio fabric high clock */
2968c2ecf20Sopenharmony_ci	val |= CATPT_CS_DCS_HIGH;
2978c2ecf20Sopenharmony_ci	mask = CATPT_CS_LPCS | CATPT_CS_DCS;
2988c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1, mask, val);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	ret = catpt_readl_poll_shim(cdev, CLKCTL,
3018c2ecf20Sopenharmony_ci				    reg, !(reg & CATPT_CLKCTL_CFCIP),
3028c2ecf20Sopenharmony_ci				    500, 10000);
3038c2ecf20Sopenharmony_ci	if (ret)
3048c2ecf20Sopenharmony_ci		dev_warn(cdev->dev, "clock change still in progress\n");
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/* update PLL accordingly */
3078c2ecf20Sopenharmony_ci	cdev->spec->pll_shutdown(cdev, lp);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	mutex_unlock(&cdev->clk_mutex);
3108c2ecf20Sopenharmony_ci	return 0;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ciint catpt_dsp_update_lpclock(struct catpt_dev *cdev)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	struct catpt_stream_runtime *stream;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	list_for_each_entry(stream, &cdev->stream_list, node)
3188c2ecf20Sopenharmony_ci		if (stream->prepared)
3198c2ecf20Sopenharmony_ci			return catpt_dsp_select_lpclock(cdev, false, true);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	return catpt_dsp_select_lpclock(cdev, true, true);
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci/* bring registers to their defaults as HW won't reset itself */
3258c2ecf20Sopenharmony_cistatic void catpt_dsp_set_regs_defaults(struct catpt_dev *cdev)
3268c2ecf20Sopenharmony_ci{
3278c2ecf20Sopenharmony_ci	int i;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, CS1, CATPT_CS_DEFAULT);
3308c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, ISC, CATPT_ISC_DEFAULT);
3318c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, ISD, CATPT_ISD_DEFAULT);
3328c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, IMC, CATPT_IMC_DEFAULT);
3338c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, IMD, CATPT_IMD_DEFAULT);
3348c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, IPCC, CATPT_IPCC_DEFAULT);
3358c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, IPCD, CATPT_IPCD_DEFAULT);
3368c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, CLKCTL, CATPT_CLKCTL_DEFAULT);
3378c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, CS2, CATPT_CS2_DEFAULT);
3388c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, LTRC, CATPT_LTRC_DEFAULT);
3398c2ecf20Sopenharmony_ci	catpt_writel_shim(cdev, HMDC, CATPT_HMDC_DEFAULT);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	for (i = 0; i < CATPT_SSP_COUNT; i++) {
3428c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSCR0, CATPT_SSC0_DEFAULT);
3438c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSCR1, CATPT_SSC1_DEFAULT);
3448c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSSR, CATPT_SSS_DEFAULT);
3458c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSITR, CATPT_SSIT_DEFAULT);
3468c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSDR, CATPT_SSD_DEFAULT);
3478c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSTO, CATPT_SSTO_DEFAULT);
3488c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSPSP, CATPT_SSPSP_DEFAULT);
3498c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSTSA, CATPT_SSTSA_DEFAULT);
3508c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSRSA, CATPT_SSRSA_DEFAULT);
3518c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSTSS, CATPT_SSTSS_DEFAULT);
3528c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSCR2, CATPT_SSCR2_DEFAULT);
3538c2ecf20Sopenharmony_ci		catpt_writel_ssp(cdev, i, SSPSP2, CATPT_SSPSP2_DEFAULT);
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ciint lpt_dsp_power_down(struct catpt_dev *cdev)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	catpt_dsp_reset(cdev, true);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/* set 24Mhz clock for both SSPs */
3628c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1),
3638c2ecf20Sopenharmony_ci			   CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1));
3648c2ecf20Sopenharmony_ci	catpt_dsp_select_lpclock(cdev, true, false);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* DRAM power gating all */
3678c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask,
3688c2ecf20Sopenharmony_ci			      cdev->spec->dram_mask);
3698c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask,
3708c2ecf20Sopenharmony_ci			      cdev->spec->iram_mask);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot);
3738c2ecf20Sopenharmony_ci	/* give hw time to drop off */
3748c2ecf20Sopenharmony_ci	udelay(50);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return 0;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ciint lpt_dsp_power_up(struct catpt_dev *cdev)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	/* SRAM power gating none */
3828c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 0);
3838c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 0);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0);
3868c2ecf20Sopenharmony_ci	/* give hw time to wake up */
3878c2ecf20Sopenharmony_ci	udelay(100);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	catpt_dsp_select_lpclock(cdev, false, false);
3908c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1,
3918c2ecf20Sopenharmony_ci			   CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1),
3928c2ecf20Sopenharmony_ci			   CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1));
3938c2ecf20Sopenharmony_ci	/* stagger DSP reset after clock selection */
3948c2ecf20Sopenharmony_ci	udelay(50);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	catpt_dsp_reset(cdev, false);
3978c2ecf20Sopenharmony_ci	/* generate int deassert msg to fix inversed int logic */
3988c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, IMC, CATPT_IMC_IPCDB | CATPT_IMC_IPCCD, 0);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	return 0;
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ciint wpt_dsp_power_down(struct catpt_dev *cdev)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	u32 mask, val;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	/* disable core clock gating */
4088c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 0);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	catpt_dsp_reset(cdev, true);
4118c2ecf20Sopenharmony_ci	/* set 24Mhz clock for both SSPs */
4128c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1),
4138c2ecf20Sopenharmony_ci			   CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1));
4148c2ecf20Sopenharmony_ci	catpt_dsp_select_lpclock(cdev, true, false);
4158c2ecf20Sopenharmony_ci	/* disable MCLK */
4168c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CLKCTL, CATPT_CLKCTL_SMOS, 0);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	catpt_dsp_set_regs_defaults(cdev);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	/* switch clock gating */
4218c2ecf20Sopenharmony_ci	mask = CATPT_VDRTCTL2_CGEALL & (~CATPT_VDRTCTL2_DCLCGE);
4228c2ecf20Sopenharmony_ci	val = mask & (~CATPT_VDRTCTL2_DTCGE);
4238c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, mask, val);
4248c2ecf20Sopenharmony_ci	/* enable DTCGE separatelly */
4258c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DTCGE,
4268c2ecf20Sopenharmony_ci			  CATPT_VDRTCTL2_DTCGE);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* SRAM power gating all */
4298c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask,
4308c2ecf20Sopenharmony_ci			      cdev->spec->dram_mask);
4318c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask,
4328c2ecf20Sopenharmony_ci			      cdev->spec->iram_mask);
4338c2ecf20Sopenharmony_ci	mask = WPT_VDRTCTL0_D3SRAMPGD | WPT_VDRTCTL0_D3PGD;
4348c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL0, mask, WPT_VDRTCTL0_D3PGD);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot);
4378c2ecf20Sopenharmony_ci	/* give hw time to drop off */
4388c2ecf20Sopenharmony_ci	udelay(50);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	/* enable core clock gating */
4418c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE,
4428c2ecf20Sopenharmony_ci			  CATPT_VDRTCTL2_DCLCGE);
4438c2ecf20Sopenharmony_ci	udelay(50);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	return 0;
4468c2ecf20Sopenharmony_ci}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ciint wpt_dsp_power_up(struct catpt_dev *cdev)
4498c2ecf20Sopenharmony_ci{
4508c2ecf20Sopenharmony_ci	u32 mask, val;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	/* disable core clock gating */
4538c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 0);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	/* switch clock gating */
4568c2ecf20Sopenharmony_ci	mask = CATPT_VDRTCTL2_CGEALL & (~CATPT_VDRTCTL2_DCLCGE);
4578c2ecf20Sopenharmony_ci	val = mask & (~CATPT_VDRTCTL2_DTCGE);
4588c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, mask, val);
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/* SRAM power gating none */
4638c2ecf20Sopenharmony_ci	mask = WPT_VDRTCTL0_D3SRAMPGD | WPT_VDRTCTL0_D3PGD;
4648c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL0, mask, mask);
4658c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 0);
4668c2ecf20Sopenharmony_ci	catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 0);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	catpt_dsp_set_regs_defaults(cdev);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	/* restore MCLK */
4718c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CLKCTL, CATPT_CLKCTL_SMOS, CATPT_CLKCTL_SMOS);
4728c2ecf20Sopenharmony_ci	catpt_dsp_select_lpclock(cdev, false, false);
4738c2ecf20Sopenharmony_ci	/* set 24Mhz clock for both SSPs */
4748c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1),
4758c2ecf20Sopenharmony_ci			   CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1));
4768c2ecf20Sopenharmony_ci	catpt_dsp_reset(cdev, false);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	/* enable core clock gating */
4798c2ecf20Sopenharmony_ci	catpt_updatel_pci(cdev, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE,
4808c2ecf20Sopenharmony_ci			  CATPT_VDRTCTL2_DCLCGE);
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	/* generate int deassert msg to fix inversed int logic */
4838c2ecf20Sopenharmony_ci	catpt_updatel_shim(cdev, IMC, CATPT_IMC_IPCDB | CATPT_IMC_IPCCD, 0);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	return 0;
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci#define CATPT_DUMP_MAGIC		0xcd42
4898c2ecf20Sopenharmony_ci#define CATPT_DUMP_SECTION_ID_FILE	0x00
4908c2ecf20Sopenharmony_ci#define CATPT_DUMP_SECTION_ID_IRAM	0x01
4918c2ecf20Sopenharmony_ci#define CATPT_DUMP_SECTION_ID_DRAM	0x02
4928c2ecf20Sopenharmony_ci#define CATPT_DUMP_SECTION_ID_REGS	0x03
4938c2ecf20Sopenharmony_ci#define CATPT_DUMP_HASH_SIZE		20
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistruct catpt_dump_section_hdr {
4968c2ecf20Sopenharmony_ci	u16 magic;
4978c2ecf20Sopenharmony_ci	u8 core_id;
4988c2ecf20Sopenharmony_ci	u8 section_id;
4998c2ecf20Sopenharmony_ci	u32 size;
5008c2ecf20Sopenharmony_ci};
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ciint catpt_coredump(struct catpt_dev *cdev)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct catpt_dump_section_hdr *hdr;
5058c2ecf20Sopenharmony_ci	size_t dump_size, regs_size;
5068c2ecf20Sopenharmony_ci	u8 *dump, *pos;
5078c2ecf20Sopenharmony_ci	const char *eof;
5088c2ecf20Sopenharmony_ci	char *info;
5098c2ecf20Sopenharmony_ci	int i;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	regs_size = CATPT_SHIM_REGS_SIZE;
5128c2ecf20Sopenharmony_ci	regs_size += CATPT_DMA_COUNT * CATPT_DMA_REGS_SIZE;
5138c2ecf20Sopenharmony_ci	regs_size += CATPT_SSP_COUNT * CATPT_SSP_REGS_SIZE;
5148c2ecf20Sopenharmony_ci	dump_size = resource_size(&cdev->dram);
5158c2ecf20Sopenharmony_ci	dump_size += resource_size(&cdev->iram);
5168c2ecf20Sopenharmony_ci	dump_size += regs_size;
5178c2ecf20Sopenharmony_ci	/* account for header of each section and hash chunk */
5188c2ecf20Sopenharmony_ci	dump_size += 4 * sizeof(*hdr) + CATPT_DUMP_HASH_SIZE;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	dump = vzalloc(dump_size);
5218c2ecf20Sopenharmony_ci	if (!dump)
5228c2ecf20Sopenharmony_ci		return -ENOMEM;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	pos = dump;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	hdr = (struct catpt_dump_section_hdr *)pos;
5278c2ecf20Sopenharmony_ci	hdr->magic = CATPT_DUMP_MAGIC;
5288c2ecf20Sopenharmony_ci	hdr->core_id = cdev->spec->core_id;
5298c2ecf20Sopenharmony_ci	hdr->section_id = CATPT_DUMP_SECTION_ID_FILE;
5308c2ecf20Sopenharmony_ci	hdr->size = dump_size - sizeof(*hdr);
5318c2ecf20Sopenharmony_ci	pos += sizeof(*hdr);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	info = cdev->ipc.config.fw_info;
5348c2ecf20Sopenharmony_ci	eof = info + FW_INFO_SIZE_MAX;
5358c2ecf20Sopenharmony_ci	/* navigate to fifth info segment (fw hash) */
5368c2ecf20Sopenharmony_ci	for (i = 0; i < 4 && info < eof; i++, info++) {
5378c2ecf20Sopenharmony_ci		/* info segments are separated by space each */
5388c2ecf20Sopenharmony_ci		info = strnchr(info, eof - info, ' ');
5398c2ecf20Sopenharmony_ci		if (!info)
5408c2ecf20Sopenharmony_ci			break;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (i == 4 && info)
5448c2ecf20Sopenharmony_ci		memcpy(pos, info, min_t(u32, eof - info, CATPT_DUMP_HASH_SIZE));
5458c2ecf20Sopenharmony_ci	pos += CATPT_DUMP_HASH_SIZE;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	hdr = (struct catpt_dump_section_hdr *)pos;
5488c2ecf20Sopenharmony_ci	hdr->magic = CATPT_DUMP_MAGIC;
5498c2ecf20Sopenharmony_ci	hdr->core_id = cdev->spec->core_id;
5508c2ecf20Sopenharmony_ci	hdr->section_id = CATPT_DUMP_SECTION_ID_IRAM;
5518c2ecf20Sopenharmony_ci	hdr->size = resource_size(&cdev->iram);
5528c2ecf20Sopenharmony_ci	pos += sizeof(*hdr);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	memcpy_fromio(pos, cdev->lpe_ba + cdev->iram.start, hdr->size);
5558c2ecf20Sopenharmony_ci	pos += hdr->size;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	hdr = (struct catpt_dump_section_hdr *)pos;
5588c2ecf20Sopenharmony_ci	hdr->magic = CATPT_DUMP_MAGIC;
5598c2ecf20Sopenharmony_ci	hdr->core_id = cdev->spec->core_id;
5608c2ecf20Sopenharmony_ci	hdr->section_id = CATPT_DUMP_SECTION_ID_DRAM;
5618c2ecf20Sopenharmony_ci	hdr->size = resource_size(&cdev->dram);
5628c2ecf20Sopenharmony_ci	pos += sizeof(*hdr);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	memcpy_fromio(pos, cdev->lpe_ba + cdev->dram.start, hdr->size);
5658c2ecf20Sopenharmony_ci	pos += hdr->size;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	hdr = (struct catpt_dump_section_hdr *)pos;
5688c2ecf20Sopenharmony_ci	hdr->magic = CATPT_DUMP_MAGIC;
5698c2ecf20Sopenharmony_ci	hdr->core_id = cdev->spec->core_id;
5708c2ecf20Sopenharmony_ci	hdr->section_id = CATPT_DUMP_SECTION_ID_REGS;
5718c2ecf20Sopenharmony_ci	hdr->size = regs_size;
5728c2ecf20Sopenharmony_ci	pos += sizeof(*hdr);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	memcpy_fromio(pos, catpt_shim_addr(cdev), CATPT_SHIM_REGS_SIZE);
5758c2ecf20Sopenharmony_ci	pos += CATPT_SHIM_REGS_SIZE;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	for (i = 0; i < CATPT_SSP_COUNT; i++) {
5788c2ecf20Sopenharmony_ci		memcpy_fromio(pos, catpt_ssp_addr(cdev, i),
5798c2ecf20Sopenharmony_ci			      CATPT_SSP_REGS_SIZE);
5808c2ecf20Sopenharmony_ci		pos += CATPT_SSP_REGS_SIZE;
5818c2ecf20Sopenharmony_ci	}
5828c2ecf20Sopenharmony_ci	for (i = 0; i < CATPT_DMA_COUNT; i++) {
5838c2ecf20Sopenharmony_ci		memcpy_fromio(pos, catpt_dma_addr(cdev, i),
5848c2ecf20Sopenharmony_ci			      CATPT_DMA_REGS_SIZE);
5858c2ecf20Sopenharmony_ci		pos += CATPT_DMA_REGS_SIZE;
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	dev_coredumpv(cdev->dev, dump, dump_size, GFP_KERNEL);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	return 0;
5918c2ecf20Sopenharmony_ci}
592