Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // This file is provided under a dual BSD/GPLv2 license.  When using or
0004 // redistributing this file, you may do so under either license.
0005 //
0006 // Copyright(c) 2018-2022 Intel Corporation. All rights reserved.
0007 //
0008 // Author: Keyon Jie <yang.jie@linux.intel.com>
0009 //
0010 
0011 #include <linux/io-64-nonatomic-lo-hi.h>
0012 #include <linux/platform_device.h>
0013 #include <asm/unaligned.h>
0014 #include <sound/soc.h>
0015 #include <sound/sof.h>
0016 #include "sof-priv.h"
0017 #include "ops.h"
0018 
0019 /*
0020  * Register IO
0021  *
0022  * The sof_io_xyz() wrappers are typically referenced in snd_sof_dsp_ops
0023  * structures and cannot be inlined.
0024  */
0025 
0026 void sof_io_write(struct snd_sof_dev *sdev, void __iomem *addr, u32 value)
0027 {
0028     writel(value, addr);
0029 }
0030 EXPORT_SYMBOL(sof_io_write);
0031 
0032 u32 sof_io_read(struct snd_sof_dev *sdev, void __iomem *addr)
0033 {
0034     return readl(addr);
0035 }
0036 EXPORT_SYMBOL(sof_io_read);
0037 
0038 void sof_io_write64(struct snd_sof_dev *sdev, void __iomem *addr, u64 value)
0039 {
0040     writeq(value, addr);
0041 }
0042 EXPORT_SYMBOL(sof_io_write64);
0043 
0044 u64 sof_io_read64(struct snd_sof_dev *sdev, void __iomem *addr)
0045 {
0046     return readq(addr);
0047 }
0048 EXPORT_SYMBOL(sof_io_read64);
0049 
0050 /*
0051  * IPC Mailbox IO
0052  */
0053 
0054 void sof_mailbox_write(struct snd_sof_dev *sdev, u32 offset,
0055                void *message, size_t bytes)
0056 {
0057     void __iomem *dest = sdev->bar[sdev->mailbox_bar] + offset;
0058 
0059     memcpy_toio(dest, message, bytes);
0060 }
0061 EXPORT_SYMBOL(sof_mailbox_write);
0062 
0063 void sof_mailbox_read(struct snd_sof_dev *sdev, u32 offset,
0064               void *message, size_t bytes)
0065 {
0066     void __iomem *src = sdev->bar[sdev->mailbox_bar] + offset;
0067 
0068     memcpy_fromio(message, src, bytes);
0069 }
0070 EXPORT_SYMBOL(sof_mailbox_read);
0071 
0072 /*
0073  * Memory copy.
0074  */
0075 
0076 int sof_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
0077             u32 offset, void *src, size_t size)
0078 {
0079     int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
0080     const u8 *src_byte = src;
0081     void __iomem *dest;
0082     u32 affected_mask;
0083     u32 tmp;
0084     int m, n;
0085 
0086     if (bar < 0)
0087         return bar;
0088 
0089     dest = sdev->bar[bar] + offset;
0090 
0091     m = size / 4;
0092     n = size % 4;
0093 
0094     /* __iowrite32_copy use 32bit size values so divide by 4 */
0095     __iowrite32_copy(dest, src, m);
0096 
0097     if (n) {
0098         affected_mask = (1 << (8 * n)) - 1;
0099 
0100         /* first read the 32bit data of dest, then change affected
0101          * bytes, and write back to dest. For unaffected bytes, it
0102          * should not be changed
0103          */
0104         tmp = ioread32(dest + m * 4);
0105         tmp &= ~affected_mask;
0106 
0107         tmp |= *(u32 *)(src_byte + m * 4) & affected_mask;
0108         iowrite32(tmp, dest + m * 4);
0109     }
0110 
0111     return 0;
0112 }
0113 EXPORT_SYMBOL(sof_block_write);
0114 
0115 int sof_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
0116            u32 offset, void *dest, size_t size)
0117 {
0118     int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
0119 
0120     if (bar < 0)
0121         return bar;
0122 
0123     memcpy_fromio(dest, sdev->bar[bar] + offset, size);
0124 
0125     return 0;
0126 }
0127 EXPORT_SYMBOL(sof_block_read);