18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Misc memory accessors
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/export.h>
98c2ecf20Sopenharmony_ci#include <linux/io.h>
108c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
118c2ecf20Sopenharmony_ci#include <sound/core.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/**
148c2ecf20Sopenharmony_ci * copy_to_user_fromio - copy data from mmio-space to user-space
158c2ecf20Sopenharmony_ci * @dst: the destination pointer on user-space
168c2ecf20Sopenharmony_ci * @src: the source pointer on mmio
178c2ecf20Sopenharmony_ci * @count: the data size to copy in bytes
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * Copies the data from mmio-space to user-space.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * Return: Zero if successful, or non-zero on failure.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ciint copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci#if defined(__i386__) || defined(CONFIG_SPARC32)
268c2ecf20Sopenharmony_ci	return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0;
278c2ecf20Sopenharmony_ci#else
288c2ecf20Sopenharmony_ci	char buf[256];
298c2ecf20Sopenharmony_ci	while (count) {
308c2ecf20Sopenharmony_ci		size_t c = count;
318c2ecf20Sopenharmony_ci		if (c > sizeof(buf))
328c2ecf20Sopenharmony_ci			c = sizeof(buf);
338c2ecf20Sopenharmony_ci		memcpy_fromio(buf, (void __iomem *)src, c);
348c2ecf20Sopenharmony_ci		if (copy_to_user(dst, buf, c))
358c2ecf20Sopenharmony_ci			return -EFAULT;
368c2ecf20Sopenharmony_ci		count -= c;
378c2ecf20Sopenharmony_ci		dst += c;
388c2ecf20Sopenharmony_ci		src += c;
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci	return 0;
418c2ecf20Sopenharmony_ci#endif
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(copy_to_user_fromio);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/**
468c2ecf20Sopenharmony_ci * copy_from_user_toio - copy data from user-space to mmio-space
478c2ecf20Sopenharmony_ci * @dst: the destination pointer on mmio-space
488c2ecf20Sopenharmony_ci * @src: the source pointer on user-space
498c2ecf20Sopenharmony_ci * @count: the data size to copy in bytes
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci * Copies the data from user-space to mmio-space.
528c2ecf20Sopenharmony_ci *
538c2ecf20Sopenharmony_ci * Return: Zero if successful, or non-zero on failure.
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_ciint copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci#if defined(__i386__) || defined(CONFIG_SPARC32)
588c2ecf20Sopenharmony_ci	return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0;
598c2ecf20Sopenharmony_ci#else
608c2ecf20Sopenharmony_ci	char buf[256];
618c2ecf20Sopenharmony_ci	while (count) {
628c2ecf20Sopenharmony_ci		size_t c = count;
638c2ecf20Sopenharmony_ci		if (c > sizeof(buf))
648c2ecf20Sopenharmony_ci			c = sizeof(buf);
658c2ecf20Sopenharmony_ci		if (copy_from_user(buf, src, c))
668c2ecf20Sopenharmony_ci			return -EFAULT;
678c2ecf20Sopenharmony_ci		memcpy_toio(dst, buf, c);
688c2ecf20Sopenharmony_ci		count -= c;
698c2ecf20Sopenharmony_ci		dst += c;
708c2ecf20Sopenharmony_ci		src += c;
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci	return 0;
738c2ecf20Sopenharmony_ci#endif
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(copy_from_user_toio);
76