Linux Audio

Check our new training course

Loading...
v6.2
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _ASM_S390_PCI_IO_H
  3#define _ASM_S390_PCI_IO_H
  4
  5#ifdef CONFIG_PCI
  6
  7#include <linux/kernel.h>
  8#include <linux/slab.h>
  9#include <asm/pci_insn.h>
 10
 11/* I/O size constraints */
 12#define ZPCI_MAX_READ_SIZE	8
 13#define ZPCI_MAX_WRITE_SIZE	128
 
 
 14
 15/* I/O Map */
 16#define ZPCI_IOMAP_SHIFT		48
 17#define ZPCI_IOMAP_ADDR_SHIFT		62
 18#define ZPCI_IOMAP_ADDR_BASE		(1UL << ZPCI_IOMAP_ADDR_SHIFT)
 19#define ZPCI_IOMAP_ADDR_OFF_MASK	((1UL << ZPCI_IOMAP_SHIFT) - 1)
 20#define ZPCI_IOMAP_MAX_ENTRIES							\
 21	(1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT))
 22#define ZPCI_IOMAP_ADDR_IDX_MASK						\
 23	((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK)
 24
 25struct zpci_iomap_entry {
 26	u32 fh;
 27	u8 bar;
 28	u16 count;
 29};
 30
 31extern struct zpci_iomap_entry *zpci_iomap_start;
 32
 33#define ZPCI_ADDR(idx) (ZPCI_IOMAP_ADDR_BASE | ((u64) idx << ZPCI_IOMAP_SHIFT))
 34#define ZPCI_IDX(addr)								\
 35	(((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> ZPCI_IOMAP_SHIFT)
 36#define ZPCI_OFFSET(addr)							\
 37	((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK)
 38
 39#define ZPCI_CREATE_REQ(handle, space, len)					\
 40	((u64) handle << 32 | space << 16 | len)
 41
 42#define zpci_read(LENGTH, RETTYPE)						\
 43static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)	\
 44{										\
 45	u64 data;								\
 46	int rc;									\
 47										\
 48	rc = zpci_load(&data, addr, LENGTH);					\
 49	if (rc)									\
 50		data = -1ULL;							\
 51	return (RETTYPE) data;							\
 52}
 53
 54#define zpci_write(LENGTH, VALTYPE)						\
 55static inline void zpci_write_##VALTYPE(VALTYPE val,				\
 56					const volatile void __iomem *addr)	\
 57{										\
 58	u64 data = (VALTYPE) val;						\
 59										\
 60	zpci_store(addr, data, LENGTH);						\
 61}
 62
 63zpci_read(8, u64)
 64zpci_read(4, u32)
 65zpci_read(2, u16)
 66zpci_read(1, u8)
 67zpci_write(8, u64)
 68zpci_write(4, u32)
 69zpci_write(2, u16)
 70zpci_write(1, u8)
 71
 72static inline int zpci_write_single(volatile void __iomem *dst, const void *src,
 73				    unsigned long len)
 74{
 75	u64 val;
 76
 77	switch (len) {
 78	case 1:
 79		val = (u64) *((u8 *) src);
 80		break;
 81	case 2:
 82		val = (u64) *((u16 *) src);
 83		break;
 84	case 4:
 85		val = (u64) *((u32 *) src);
 86		break;
 87	case 8:
 88		val = (u64) *((u64 *) src);
 89		break;
 90	default:
 91		val = 0;		/* let FW report error */
 92		break;
 93	}
 94	return zpci_store(dst, val, len);
 95}
 96
 97static inline int zpci_read_single(void *dst, const volatile void __iomem *src,
 98				   unsigned long len)
 99{
100	u64 data;
101	int cc;
102
103	cc = zpci_load(&data, src, len);
104	if (cc)
105		goto out;
106
107	switch (len) {
108	case 1:
109		*((u8 *) dst) = (u8) data;
110		break;
111	case 2:
112		*((u16 *) dst) = (u16) data;
113		break;
114	case 4:
115		*((u32 *) dst) = (u32) data;
116		break;
117	case 8:
118		*((u64 *) dst) = (u64) data;
119		break;
120	}
121out:
122	return cc;
123}
124
125int zpci_write_block(volatile void __iomem *dst, const void *src,
126		     unsigned long len);
127
128static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
129{
130	int count = len > max ? max : len, size = 1;
 
131
132	while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) {
133		dst = dst >> 1;
134		src = src >> 1;
135		size = size << 1;
136	}
137	return size;
 
138}
139
140static inline int zpci_memcpy_fromio(void *dst,
141				     const volatile void __iomem *src,
142				     unsigned long n)
143{
144	int size, rc = 0;
145
146	while (n > 0) {
147		size = zpci_get_max_write_size((u64 __force) src,
148					       (u64) dst, n,
149					       ZPCI_MAX_READ_SIZE);
150		rc = zpci_read_single(dst, src, size);
151		if (rc)
152			break;
153		src += size;
154		dst += size;
155		n -= size;
156	}
157	return rc;
158}
159
160static inline int zpci_memcpy_toio(volatile void __iomem *dst,
161				   const void *src, unsigned long n)
162{
163	int size, rc = 0;
164
165	if (!src)
166		return -EINVAL;
167
168	while (n > 0) {
169		size = zpci_get_max_write_size((u64 __force) dst,
170					       (u64) src, n,
171					       ZPCI_MAX_WRITE_SIZE);
172		if (size > 8) /* main path */
173			rc = zpci_write_block(dst, src, size);
174		else
175			rc = zpci_write_single(dst, src, size);
176		if (rc)
177			break;
178		src += size;
179		dst += size;
180		n -= size;
181	}
182	return rc;
183}
184
185static inline int zpci_memset_io(volatile void __iomem *dst,
186				 unsigned char val, size_t count)
187{
188	u8 *src = kmalloc(count, GFP_KERNEL);
189	int rc;
190
191	if (src == NULL)
192		return -ENOMEM;
193	memset(src, val, count);
194
195	rc = zpci_memcpy_toio(dst, src, count);
196	kfree(src);
197	return rc;
198}
199
200#endif /* CONFIG_PCI */
201
202#endif /* _ASM_S390_PCI_IO_H */
v6.13.7
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _ASM_S390_PCI_IO_H
  3#define _ASM_S390_PCI_IO_H
  4
  5#ifdef CONFIG_PCI
  6
  7#include <linux/kernel.h>
  8#include <linux/slab.h>
  9#include <asm/pci_insn.h>
 10
 11/* I/O size constraints */
 12#define ZPCI_MAX_READ_SIZE	8
 13#define ZPCI_MAX_WRITE_SIZE	128
 14#define ZPCI_BOUNDARY_SIZE	(1 << 12)
 15#define ZPCI_BOUNDARY_MASK	(ZPCI_BOUNDARY_SIZE - 1)
 16
 17/* I/O Map */
 18#define ZPCI_IOMAP_SHIFT		48
 19#define ZPCI_IOMAP_ADDR_SHIFT		62
 20#define ZPCI_IOMAP_ADDR_BASE		(1UL << ZPCI_IOMAP_ADDR_SHIFT)
 21#define ZPCI_IOMAP_ADDR_OFF_MASK	((1UL << ZPCI_IOMAP_SHIFT) - 1)
 22#define ZPCI_IOMAP_MAX_ENTRIES							\
 23	(1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT))
 24#define ZPCI_IOMAP_ADDR_IDX_MASK						\
 25	((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK)
 26
 27struct zpci_iomap_entry {
 28	u32 fh;
 29	u8 bar;
 30	u16 count;
 31};
 32
 33extern struct zpci_iomap_entry *zpci_iomap_start;
 34
 35#define ZPCI_ADDR(idx) (ZPCI_IOMAP_ADDR_BASE | ((u64) idx << ZPCI_IOMAP_SHIFT))
 36#define ZPCI_IDX(addr)								\
 37	(((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> ZPCI_IOMAP_SHIFT)
 38#define ZPCI_OFFSET(addr)							\
 39	((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK)
 40
 41#define ZPCI_CREATE_REQ(handle, space, len)					\
 42	((u64) handle << 32 | space << 16 | len)
 43
 44#define zpci_read(LENGTH, RETTYPE)						\
 45static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)	\
 46{										\
 47	u64 data;								\
 48	int rc;									\
 49										\
 50	rc = zpci_load(&data, addr, LENGTH);					\
 51	if (rc)									\
 52		data = -1ULL;							\
 53	return (RETTYPE) data;							\
 54}
 55
 56#define zpci_write(LENGTH, VALTYPE)						\
 57static inline void zpci_write_##VALTYPE(VALTYPE val,				\
 58					const volatile void __iomem *addr)	\
 59{										\
 60	u64 data = (VALTYPE) val;						\
 61										\
 62	zpci_store(addr, data, LENGTH);						\
 63}
 64
 65zpci_read(8, u64)
 66zpci_read(4, u32)
 67zpci_read(2, u16)
 68zpci_read(1, u8)
 69zpci_write(8, u64)
 70zpci_write(4, u32)
 71zpci_write(2, u16)
 72zpci_write(1, u8)
 73
 74static inline int zpci_write_single(volatile void __iomem *dst, const void *src,
 75				    unsigned long len)
 76{
 77	u64 val;
 78
 79	switch (len) {
 80	case 1:
 81		val = (u64) *((u8 *) src);
 82		break;
 83	case 2:
 84		val = (u64) *((u16 *) src);
 85		break;
 86	case 4:
 87		val = (u64) *((u32 *) src);
 88		break;
 89	case 8:
 90		val = (u64) *((u64 *) src);
 91		break;
 92	default:
 93		val = 0;		/* let FW report error */
 94		break;
 95	}
 96	return zpci_store(dst, val, len);
 97}
 98
 99static inline int zpci_read_single(void *dst, const volatile void __iomem *src,
100				   unsigned long len)
101{
102	u64 data;
103	int cc;
104
105	cc = zpci_load(&data, src, len);
106	if (cc)
107		goto out;
108
109	switch (len) {
110	case 1:
111		*((u8 *) dst) = (u8) data;
112		break;
113	case 2:
114		*((u16 *) dst) = (u16) data;
115		break;
116	case 4:
117		*((u32 *) dst) = (u32) data;
118		break;
119	case 8:
120		*((u64 *) dst) = (u64) data;
121		break;
122	}
123out:
124	return cc;
125}
126
127int zpci_write_block(volatile void __iomem *dst, const void *src,
128		     unsigned long len);
129
130static inline int zpci_get_max_io_size(u64 src, u64 dst, int len, int max)
131{
132	int offset = dst & ZPCI_BOUNDARY_MASK;
133	int size;
134
135	size = min3(len, ZPCI_BOUNDARY_SIZE - offset, max);
136	if (IS_ALIGNED(src, 8) && IS_ALIGNED(dst, 8) && IS_ALIGNED(size, 8))
137		return size;
138
139	if (size >= 8)
140		return 8;
141	return rounddown_pow_of_two(size);
142}
143
144static inline int zpci_memcpy_fromio(void *dst,
145				     const volatile void __iomem *src,
146				     size_t n)
147{
148	int size, rc = 0;
149
150	while (n > 0) {
151		size = zpci_get_max_io_size((u64 __force) src,
152					    (u64) dst, n,
153					    ZPCI_MAX_READ_SIZE);
154		rc = zpci_read_single(dst, src, size);
155		if (rc)
156			break;
157		src += size;
158		dst += size;
159		n -= size;
160	}
161	return rc;
162}
163
164static inline int zpci_memcpy_toio(volatile void __iomem *dst,
165				   const void *src, size_t n)
166{
167	int size, rc = 0;
168
169	if (!src)
170		return -EINVAL;
171
172	while (n > 0) {
173		size = zpci_get_max_io_size((u64 __force) dst,
174					    (u64) src, n,
175					    ZPCI_MAX_WRITE_SIZE);
176		if (size > 8) /* main path */
177			rc = zpci_write_block(dst, src, size);
178		else
179			rc = zpci_write_single(dst, src, size);
180		if (rc)
181			break;
182		src += size;
183		dst += size;
184		n -= size;
185	}
186	return rc;
187}
188
189static inline int zpci_memset_io(volatile void __iomem *dst,
190				 int val, size_t count)
191{
192	u8 *src = kmalloc(count, GFP_KERNEL);
193	int rc;
194
195	if (src == NULL)
196		return -ENOMEM;
197	memset(src, val, count);
198
199	rc = zpci_memcpy_toio(dst, src, count);
200	kfree(src);
201	return rc;
202}
203
204#endif /* CONFIG_PCI */
205
206#endif /* _ASM_S390_PCI_IO_H */