18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Original author:
68c2ecf20Sopenharmony_ci * Ben Collins <bcollins@ubuntu.com>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Additional work by:
98c2ecf20Sopenharmony_ci * John Brooks <john.brooks@bluecherry.net>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "solo6x10.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic int multi_p2m;
198c2ecf20Sopenharmony_cimodule_param(multi_p2m, uint, 0644);
208c2ecf20Sopenharmony_ciMODULE_PARM_DESC(multi_p2m,
218c2ecf20Sopenharmony_ci		 "Use multiple P2M DMA channels (default: no, 6010-only)");
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic int desc_mode;
248c2ecf20Sopenharmony_cimodule_param(desc_mode, uint, 0644);
258c2ecf20Sopenharmony_ciMODULE_PARM_DESC(desc_mode,
268c2ecf20Sopenharmony_ci		 "Allow use of descriptor mode DMA (default: no, 6010-only)");
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciint solo_p2m_dma(struct solo_dev *solo_dev, int wr,
298c2ecf20Sopenharmony_ci		 void *sys_addr, u32 ext_addr, u32 size,
308c2ecf20Sopenharmony_ci		 int repeat, u32 ext_size)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
338c2ecf20Sopenharmony_ci	int ret;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE((unsigned long)sys_addr & 0x03))
368c2ecf20Sopenharmony_ci		return -EINVAL;
378c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(!size))
388c2ecf20Sopenharmony_ci		return -EINVAL;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
418c2ecf20Sopenharmony_ci				  wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
428c2ecf20Sopenharmony_ci	if (pci_dma_mapping_error(solo_dev->pdev, dma_addr))
438c2ecf20Sopenharmony_ci		return -ENOMEM;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	ret = solo_p2m_dma_t(solo_dev, wr, dma_addr, ext_addr, size,
468c2ecf20Sopenharmony_ci			     repeat, ext_size);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	pci_unmap_single(solo_dev->pdev, dma_addr, size,
498c2ecf20Sopenharmony_ci			 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	return ret;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Mutex must be held for p2m_id before calling this!! */
558c2ecf20Sopenharmony_ciint solo_p2m_dma_desc(struct solo_dev *solo_dev,
568c2ecf20Sopenharmony_ci		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
578c2ecf20Sopenharmony_ci		      int desc_cnt)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	struct solo_p2m_dev *p2m_dev;
608c2ecf20Sopenharmony_ci	unsigned int timeout;
618c2ecf20Sopenharmony_ci	unsigned int config = 0;
628c2ecf20Sopenharmony_ci	int ret = 0;
638c2ecf20Sopenharmony_ci	unsigned int p2m_id = 0;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */
668c2ecf20Sopenharmony_ci	if (solo_dev->type != SOLO_DEV_6110 && multi_p2m)
678c2ecf20Sopenharmony_ci		p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	p2m_dev = &solo_dev->p2m_dev[p2m_id];
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&p2m_dev->mutex))
728c2ecf20Sopenharmony_ci		return -EINTR;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	reinit_completion(&p2m_dev->completion);
758c2ecf20Sopenharmony_ci	p2m_dev->error = 0;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && desc_mode) {
788c2ecf20Sopenharmony_ci		/* For 6010 with more than one desc, we can do a one-shot */
798c2ecf20Sopenharmony_ci		p2m_dev->desc_count = p2m_dev->desc_idx = 0;
808c2ecf20Sopenharmony_ci		config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id));
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma);
838c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt);
848c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config |
858c2ecf20Sopenharmony_ci			       SOLO_P2M_DESC_MODE);
868c2ecf20Sopenharmony_ci	} else {
878c2ecf20Sopenharmony_ci		/* For single descriptors and 6110, we need to run each desc */
888c2ecf20Sopenharmony_ci		p2m_dev->desc_count = desc_cnt;
898c2ecf20Sopenharmony_ci		p2m_dev->desc_idx = 1;
908c2ecf20Sopenharmony_ci		p2m_dev->descs = desc;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id),
938c2ecf20Sopenharmony_ci			       desc[1].dma_addr);
948c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id),
958c2ecf20Sopenharmony_ci			       desc[1].ext_addr);
968c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id),
978c2ecf20Sopenharmony_ci			       desc[1].cfg);
988c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id),
998c2ecf20Sopenharmony_ci			       desc[1].ctrl);
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	timeout = wait_for_completion_timeout(&p2m_dev->completion,
1038c2ecf20Sopenharmony_ci					      solo_dev->p2m_jiffies);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(p2m_dev->error))
1068c2ecf20Sopenharmony_ci		ret = -EIO;
1078c2ecf20Sopenharmony_ci	else if (timeout == 0) {
1088c2ecf20Sopenharmony_ci		solo_dev->p2m_timeouts++;
1098c2ecf20Sopenharmony_ci		ret = -EAGAIN;
1108c2ecf20Sopenharmony_ci	}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	/* Don't write here for the no_desc_mode case, because config is 0.
1158c2ecf20Sopenharmony_ci	 * We can't test no_desc_mode again, it might race. */
1168c2ecf20Sopenharmony_ci	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && config)
1178c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	mutex_unlock(&p2m_dev->mutex);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	return ret;
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_civoid solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
1258c2ecf20Sopenharmony_ci			dma_addr_t dma_addr, u32 ext_addr, u32 size,
1268c2ecf20Sopenharmony_ci			int repeat, u32 ext_size)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	WARN_ON_ONCE(dma_addr & 0x03);
1298c2ecf20Sopenharmony_ci	WARN_ON_ONCE(!size);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2);
1328c2ecf20Sopenharmony_ci	desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
1338c2ecf20Sopenharmony_ci		(wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	if (repeat) {
1368c2ecf20Sopenharmony_ci		desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2);
1378c2ecf20Sopenharmony_ci		desc->ctrl |=  SOLO_P2M_PCI_INC(size >> 2) |
1388c2ecf20Sopenharmony_ci			 SOLO_P2M_REPEAT(repeat);
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	desc->dma_addr = dma_addr;
1428c2ecf20Sopenharmony_ci	desc->ext_addr = ext_addr;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ciint solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
1468c2ecf20Sopenharmony_ci		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
1478c2ecf20Sopenharmony_ci		   int repeat, u32 ext_size)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct solo_p2m_desc desc[2];
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	solo_p2m_fill_desc(&desc[1], wr, dma_addr, ext_addr, size, repeat,
1528c2ecf20Sopenharmony_ci			   ext_size);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	/* No need for desc_dma since we know it is a single-shot */
1558c2ecf20Sopenharmony_ci	return solo_p2m_dma_desc(solo_dev, desc, 0, 1);
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_civoid solo_p2m_isr(struct solo_dev *solo_dev, int id)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];
1618c2ecf20Sopenharmony_ci	struct solo_p2m_desc *desc;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	if (p2m_dev->desc_count <= p2m_dev->desc_idx) {
1648c2ecf20Sopenharmony_ci		complete(&p2m_dev->completion);
1658c2ecf20Sopenharmony_ci		return;
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	/* Setup next descriptor */
1698c2ecf20Sopenharmony_ci	p2m_dev->desc_idx++;
1708c2ecf20Sopenharmony_ci	desc = &p2m_dev->descs[p2m_dev->desc_idx];
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
1738c2ecf20Sopenharmony_ci	solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), desc->dma_addr);
1748c2ecf20Sopenharmony_ci	solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), desc->ext_addr);
1758c2ecf20Sopenharmony_ci	solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), desc->cfg);
1768c2ecf20Sopenharmony_ci	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), desc->ctrl);
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_civoid solo_p2m_error_isr(struct solo_dev *solo_dev)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	unsigned int err = solo_reg_read(solo_dev, SOLO_PCI_ERR);
1828c2ecf20Sopenharmony_ci	struct solo_p2m_dev *p2m_dev;
1838c2ecf20Sopenharmony_ci	int i;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (!(err & (SOLO_PCI_ERR_P2M | SOLO_PCI_ERR_P2M_DESC)))
1868c2ecf20Sopenharmony_ci		return;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	for (i = 0; i < SOLO_NR_P2M; i++) {
1898c2ecf20Sopenharmony_ci		p2m_dev = &solo_dev->p2m_dev[i];
1908c2ecf20Sopenharmony_ci		p2m_dev->error = 1;
1918c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
1928c2ecf20Sopenharmony_ci		complete(&p2m_dev->completion);
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_civoid solo_p2m_exit(struct solo_dev *solo_dev)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	int i;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	for (i = 0; i < SOLO_NR_P2M; i++)
2018c2ecf20Sopenharmony_ci		solo_irq_off(solo_dev, SOLO_IRQ_P2M(i));
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic int solo_p2m_test(struct solo_dev *solo_dev, int base, int size)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	u32 *wr_buf;
2078c2ecf20Sopenharmony_ci	u32 *rd_buf;
2088c2ecf20Sopenharmony_ci	int i;
2098c2ecf20Sopenharmony_ci	int ret = -EIO;
2108c2ecf20Sopenharmony_ci	int order = get_order(size);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	wr_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
2138c2ecf20Sopenharmony_ci	if (wr_buf == NULL)
2148c2ecf20Sopenharmony_ci		return -1;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	rd_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
2178c2ecf20Sopenharmony_ci	if (rd_buf == NULL) {
2188c2ecf20Sopenharmony_ci		free_pages((unsigned long)wr_buf, order);
2198c2ecf20Sopenharmony_ci		return -1;
2208c2ecf20Sopenharmony_ci	}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	for (i = 0; i < (size >> 3); i++)
2238c2ecf20Sopenharmony_ci		*(wr_buf + i) = (i << 16) | (i + 1);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	for (i = (size >> 3); i < (size >> 2); i++)
2268c2ecf20Sopenharmony_ci		*(wr_buf + i) = ~((i << 16) | (i + 1));
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	memset(rd_buf, 0x55, size);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (solo_p2m_dma(solo_dev, 1, wr_buf, base, size, 0, 0))
2318c2ecf20Sopenharmony_ci		goto test_fail;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	if (solo_p2m_dma(solo_dev, 0, rd_buf, base, size, 0, 0))
2348c2ecf20Sopenharmony_ci		goto test_fail;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	for (i = 0; i < (size >> 2); i++) {
2378c2ecf20Sopenharmony_ci		if (*(wr_buf + i) != *(rd_buf + i))
2388c2ecf20Sopenharmony_ci			goto test_fail;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	ret = 0;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_citest_fail:
2448c2ecf20Sopenharmony_ci	free_pages((unsigned long)wr_buf, order);
2458c2ecf20Sopenharmony_ci	free_pages((unsigned long)rd_buf, order);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	return ret;
2488c2ecf20Sopenharmony_ci}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ciint solo_p2m_init(struct solo_dev *solo_dev)
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	struct solo_p2m_dev *p2m_dev;
2538c2ecf20Sopenharmony_ci	int i;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	for (i = 0; i < SOLO_NR_P2M; i++) {
2568c2ecf20Sopenharmony_ci		p2m_dev = &solo_dev->p2m_dev[i];
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		mutex_init(&p2m_dev->mutex);
2598c2ecf20Sopenharmony_ci		init_completion(&p2m_dev->completion);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
2628c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
2638c2ecf20Sopenharmony_ci			       SOLO_P2M_CSC_16BIT_565 |
2648c2ecf20Sopenharmony_ci			       SOLO_P2M_DESC_INTR_OPT |
2658c2ecf20Sopenharmony_ci			       SOLO_P2M_DMA_INTERVAL(0) |
2668c2ecf20Sopenharmony_ci			       SOLO_P2M_PCI_MASTER_MODE);
2678c2ecf20Sopenharmony_ci		solo_irq_on(solo_dev, SOLO_IRQ_P2M(i));
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* Find correct SDRAM size */
2718c2ecf20Sopenharmony_ci	for (solo_dev->sdram_size = 0, i = 2; i >= 0; i--) {
2728c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_DMA_CTRL,
2738c2ecf20Sopenharmony_ci			       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
2748c2ecf20Sopenharmony_ci			       SOLO_DMA_CTRL_SDRAM_SIZE(i) |
2758c2ecf20Sopenharmony_ci			       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
2768c2ecf20Sopenharmony_ci			       SOLO_DMA_CTRL_READ_CLK_SELECT |
2778c2ecf20Sopenharmony_ci			       SOLO_DMA_CTRL_LATENCY(1));
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config |
2808c2ecf20Sopenharmony_ci			       SOLO_SYS_CFG_RESET);
2818c2ecf20Sopenharmony_ci		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci		switch (i) {
2848c2ecf20Sopenharmony_ci		case 2:
2858c2ecf20Sopenharmony_ci			if (solo_p2m_test(solo_dev, 0x07ff0000, 0x00010000) ||
2868c2ecf20Sopenharmony_ci			    solo_p2m_test(solo_dev, 0x05ff0000, 0x00010000))
2878c2ecf20Sopenharmony_ci				continue;
2888c2ecf20Sopenharmony_ci			break;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci		case 1:
2918c2ecf20Sopenharmony_ci			if (solo_p2m_test(solo_dev, 0x03ff0000, 0x00010000))
2928c2ecf20Sopenharmony_ci				continue;
2938c2ecf20Sopenharmony_ci			break;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci		default:
2968c2ecf20Sopenharmony_ci			if (solo_p2m_test(solo_dev, 0x01ff0000, 0x00010000))
2978c2ecf20Sopenharmony_ci				continue;
2988c2ecf20Sopenharmony_ci		}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci		solo_dev->sdram_size = (32 << 20) << i;
3018c2ecf20Sopenharmony_ci		break;
3028c2ecf20Sopenharmony_ci	}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (!solo_dev->sdram_size) {
3058c2ecf20Sopenharmony_ci		dev_err(&solo_dev->pdev->dev, "Error detecting SDRAM size\n");
3068c2ecf20Sopenharmony_ci		return -EIO;
3078c2ecf20Sopenharmony_ci	}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	if (SOLO_SDRAM_END(solo_dev) > solo_dev->sdram_size) {
3108c2ecf20Sopenharmony_ci		dev_err(&solo_dev->pdev->dev,
3118c2ecf20Sopenharmony_ci			"SDRAM is not large enough (%u < %u)\n",
3128c2ecf20Sopenharmony_ci			solo_dev->sdram_size, SOLO_SDRAM_END(solo_dev));
3138c2ecf20Sopenharmony_ci		return -EIO;
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	return 0;
3178c2ecf20Sopenharmony_ci}
318