1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
3 * Wave5 series multi-standard codec IP - low level access functions
5 * Copyright (C) 2021 CHIPS&MEDIA INC
10 #include "wave5-vpu.h"
11 #include "wave5-regdefine.h"
12 #include <linux/delay.h>
13 #ifdef CONFIG_SIFIVE_FLUSH
14 #include <soc/sifive/sifive_l2_cache.h>
17 #define VDI_SRAM_BASE_ADDR 0x00
19 #define VDI_SYSTEM_ENDIAN VDI_LITTLE_ENDIAN
20 #define VDI_128BIT_BUS_SYSTEM_ENDIAN VDI_128BIT_LITTLE_ENDIAN
22 static int wave5_vdi_allocate_common_memory(struct device *dev)
24 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
26 if (!vpu_dev->common_mem.vaddr) {
29 vpu_dev->common_mem.size = SIZE_COMMON;
30 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem);
32 dev_err(dev, "unable to allocate common buffer\n");
37 dev_dbg(dev, "[VDI] common_mem: daddr=%pad size=%zu vaddr=0x%p\n",
38 &vpu_dev->common_mem.daddr, vpu_dev->common_mem.size, vpu_dev->common_mem.vaddr);
43 int wave5_vdi_init(struct device *dev)
45 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
48 ret = wave5_vdi_allocate_common_memory(dev);
50 dev_err(dev, "[VDI] failed to get vpu common buffer from driver\n");
54 if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {
55 WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code);
59 // if BIT processor is not running.
60 if (wave5_vdi_readl(vpu_dev, W5_VCPU_CUR_PC) == 0) {
63 for (i = 0; i < 64; i++)
64 wave5_vdi_write_register(vpu_dev, (i * 4) + 0x100, 0x0);
67 dev_dbg(dev, "[VDI] driver initialized successfully\n");
72 int wave5_vdi_release(struct device *dev)
74 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
76 vpu_dev->vdb_register = NULL;
77 wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem);
82 void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data)
84 writel(data, vpu_dev->vdb_register + addr);
87 unsigned int wave5_vdi_readl(struct vpu_device *vpu_dev, u32 addr)
89 return readl(vpu_dev->vdb_register + addr);
92 int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)
94 if (!vb || !vb->vaddr) {
95 dev_err(vpu_dev->dev, "%s: unable to clear unmapped buffer\n", __func__);
99 memset(vb->vaddr, 0, vb->size);
100 #ifdef CONFIG_SIFIVE_FLUSH
101 sifive_flush64_range(vb->daddr, vb->size);
106 static void wave5_swap_endian(struct vpu_device *vpu_dev, u8 *data, size_t len,
107 unsigned int endian);
109 int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset,
110 u8 *data, size_t len, unsigned int endian)
112 if (!vb || !vb->vaddr) {
113 dev_err(vpu_dev->dev, "%s: unable to write to unmapped buffer\n", __func__);
117 if (offset > vb->size || len > vb->size || offset + len > vb->size) {
118 dev_err(vpu_dev->dev, "%s: buffer too small\n", __func__);
122 wave5_swap_endian(vpu_dev, data, len, endian);
123 memcpy(vb->vaddr + offset, data, len);
124 #ifdef CONFIG_SIFIVE_FLUSH
125 sifive_flush64_range(vb->daddr + offset, len);
131 int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)
137 dev_err(vpu_dev->dev, "%s: requested size==0\n", __func__);
141 vaddr = dma_alloc_coherent(vpu_dev->dev, vb->size, &daddr, GFP_KERNEL);
147 #ifdef CONFIG_SIFIVE_FLUSH
148 sifive_flush64_range(daddr, vb->size);
154 void wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)
160 dev_err(vpu_dev->dev, "%s: requested free of unmapped buffer\n", __func__);
162 dma_free_coherent(vpu_dev->dev, vb->size, vb->vaddr, vb->daddr);
164 memset(vb, 0, sizeof(*vb));
167 unsigned int wave5_vdi_convert_endian(struct vpu_device *vpu_dev, unsigned int endian)
169 if (PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {
171 case VDI_LITTLE_ENDIAN:
177 case VDI_32BIT_LITTLE_ENDIAN:
180 case VDI_32BIT_BIG_ENDIAN:
186 return (endian & 0x0f);
189 static void byte_swap(unsigned char *data, size_t len)
193 for (i = 0; i < len; i += 2)
194 swap(data[i], data[i + 1]);
197 static void word_swap(unsigned char *data, size_t len)
199 u16 *ptr = (u16 *)data;
201 size_t size = len / sizeof(uint16_t);
203 for (i = 0; i < size; i += 2)
204 swap(ptr[i], ptr[i + 1]);
207 static void dword_swap(unsigned char *data, size_t len)
209 u32 *ptr = (u32 *)data;
210 size_t size = len / sizeof(u32);
213 for (i = 0; i < size; i += 2)
214 swap(ptr[i], ptr[i + 1]);
217 static void lword_swap(unsigned char *data, size_t len)
219 u64 *ptr = (u64 *)data;
220 size_t size = len / sizeof(uint64_t);
223 for (i = 0; i < size; i += 2)
224 swap(ptr[i], ptr[i + 1]);
227 static void wave5_swap_endian(struct vpu_device *vpu_dev, u8 *data, size_t len,
231 unsigned int sys_endian = VDI_128BIT_BUS_SYSTEM_ENDIAN;
232 bool byte_change, word_change, dword_change, lword_change;
234 if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {
235 dev_err(vpu_dev->dev, "unknown product id: %08x\n", vpu_dev->product_code);
239 endian = wave5_vdi_convert_endian(vpu_dev, endian);
240 sys_endian = wave5_vdi_convert_endian(vpu_dev, sys_endian);
241 if (endian == sys_endian)
244 changes = endian ^ sys_endian;
245 byte_change = changes & 0x01;
246 word_change = ((changes & 0x02) == 0x02);
247 dword_change = ((changes & 0x04) == 0x04);
248 lword_change = ((changes & 0x08) == 0x08);
251 byte_swap(data, len);
253 word_swap(data, len);
255 dword_swap(data, len);
257 lword_swap(data, len);