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