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