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