0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "LOGIC PIO: " fmt
0010
0011 #include <linux/of.h>
0012 #include <linux/io.h>
0013 #include <linux/logic_pio.h>
0014 #include <linux/mm.h>
0015 #include <linux/rculist.h>
0016 #include <linux/sizes.h>
0017 #include <linux/slab.h>
0018
0019
0020 static LIST_HEAD(io_range_list);
0021 static DEFINE_MUTEX(io_range_mutex);
0022
0023
0024 #define in_range(b, first, len) ((b) >= (first) && (b) < (first) + (len))
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
0037 {
0038 struct logic_pio_hwaddr *range;
0039 resource_size_t start;
0040 resource_size_t end;
0041 resource_size_t mmio_end = 0;
0042 resource_size_t iio_sz = MMIO_UPPER_LIMIT;
0043 int ret = 0;
0044
0045 if (!new_range || !new_range->fwnode || !new_range->size ||
0046 (new_range->flags == LOGIC_PIO_INDIRECT && !new_range->ops))
0047 return -EINVAL;
0048
0049 start = new_range->hw_start;
0050 end = new_range->hw_start + new_range->size;
0051
0052 mutex_lock(&io_range_mutex);
0053 list_for_each_entry(range, &io_range_list, list) {
0054 if (range->fwnode == new_range->fwnode) {
0055
0056 ret = -EEXIST;
0057 goto end_register;
0058 }
0059 if (range->flags == LOGIC_PIO_CPU_MMIO &&
0060 new_range->flags == LOGIC_PIO_CPU_MMIO) {
0061
0062 if (start >= range->hw_start + range->size ||
0063 end < range->hw_start) {
0064 mmio_end = range->io_start + range->size;
0065 } else {
0066 ret = -EFAULT;
0067 goto end_register;
0068 }
0069 } else if (range->flags == LOGIC_PIO_INDIRECT &&
0070 new_range->flags == LOGIC_PIO_INDIRECT) {
0071 iio_sz += range->size;
0072 }
0073 }
0074
0075
0076 if (new_range->flags == LOGIC_PIO_CPU_MMIO) {
0077 if (mmio_end + new_range->size - 1 > MMIO_UPPER_LIMIT) {
0078
0079 if (mmio_end + SZ_64K - 1 > MMIO_UPPER_LIMIT) {
0080 ret = -E2BIG;
0081 goto end_register;
0082 }
0083 new_range->size = SZ_64K;
0084 pr_warn("Requested IO range too big, new size set to 64K\n");
0085 }
0086 new_range->io_start = mmio_end;
0087 } else if (new_range->flags == LOGIC_PIO_INDIRECT) {
0088 if (iio_sz + new_range->size - 1 > IO_SPACE_LIMIT) {
0089 ret = -E2BIG;
0090 goto end_register;
0091 }
0092 new_range->io_start = iio_sz;
0093 } else {
0094
0095 ret = -EINVAL;
0096 goto end_register;
0097 }
0098
0099 list_add_tail_rcu(&new_range->list, &io_range_list);
0100
0101 end_register:
0102 mutex_unlock(&io_range_mutex);
0103 return ret;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112 void logic_pio_unregister_range(struct logic_pio_hwaddr *range)
0113 {
0114 mutex_lock(&io_range_mutex);
0115 list_del_rcu(&range->list);
0116 mutex_unlock(&io_range_mutex);
0117 synchronize_rcu();
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
0129 {
0130 struct logic_pio_hwaddr *range, *found_range = NULL;
0131
0132 rcu_read_lock();
0133 list_for_each_entry_rcu(range, &io_range_list, list) {
0134 if (range->fwnode == fwnode) {
0135 found_range = range;
0136 break;
0137 }
0138 }
0139 rcu_read_unlock();
0140
0141 return found_range;
0142 }
0143
0144
0145 static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
0146 {
0147 struct logic_pio_hwaddr *range, *found_range = NULL;
0148
0149 rcu_read_lock();
0150 list_for_each_entry_rcu(range, &io_range_list, list) {
0151 if (in_range(pio, range->io_start, range->size)) {
0152 found_range = range;
0153 break;
0154 }
0155 }
0156 rcu_read_unlock();
0157
0158 if (!found_range)
0159 pr_err("PIO entry token 0x%lx invalid\n", pio);
0160
0161 return found_range;
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 resource_size_t logic_pio_to_hwaddr(unsigned long pio)
0174 {
0175 struct logic_pio_hwaddr *range;
0176
0177 range = find_io_range(pio);
0178 if (range)
0179 return range->hw_start + pio - range->io_start;
0180
0181 return (resource_size_t)~0;
0182 }
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
0193 resource_size_t addr, resource_size_t size)
0194 {
0195 struct logic_pio_hwaddr *range;
0196
0197 range = find_io_range_by_fwnode(fwnode);
0198 if (!range || range->flags == LOGIC_PIO_CPU_MMIO) {
0199 pr_err("IO range not found or invalid\n");
0200 return ~0UL;
0201 }
0202 if (range->size < size) {
0203 pr_err("resource size %pa cannot fit in IO range size %pa\n",
0204 &size, &range->size);
0205 return ~0UL;
0206 }
0207 return addr - range->hw_start + range->io_start;
0208 }
0209
0210 unsigned long logic_pio_trans_cpuaddr(resource_size_t addr)
0211 {
0212 struct logic_pio_hwaddr *range;
0213
0214 rcu_read_lock();
0215 list_for_each_entry_rcu(range, &io_range_list, list) {
0216 if (range->flags != LOGIC_PIO_CPU_MMIO)
0217 continue;
0218 if (in_range(addr, range->hw_start, range->size)) {
0219 unsigned long cpuaddr;
0220
0221 cpuaddr = addr - range->hw_start + range->io_start;
0222
0223 rcu_read_unlock();
0224 return cpuaddr;
0225 }
0226 }
0227 rcu_read_unlock();
0228
0229 pr_err("addr %pa not registered in io_range_list\n", &addr);
0230
0231 return ~0UL;
0232 }
0233
0234 #if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
0235 #define BUILD_LOGIC_IO(bwl, type) \
0236 type logic_in##bwl(unsigned long addr) \
0237 { \
0238 type ret = (type)~0; \
0239 \
0240 if (addr < MMIO_UPPER_LIMIT) { \
0241 ret = _in##bwl(addr); \
0242 } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
0243 struct logic_pio_hwaddr *entry = find_io_range(addr); \
0244 \
0245 if (entry) \
0246 ret = entry->ops->in(entry->hostdata, \
0247 addr, sizeof(type)); \
0248 else \
0249 WARN_ON_ONCE(1); \
0250 } \
0251 return ret; \
0252 } \
0253 \
0254 void logic_out##bwl(type value, unsigned long addr) \
0255 { \
0256 if (addr < MMIO_UPPER_LIMIT) { \
0257 _out##bwl(value, addr); \
0258 } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
0259 struct logic_pio_hwaddr *entry = find_io_range(addr); \
0260 \
0261 if (entry) \
0262 entry->ops->out(entry->hostdata, \
0263 addr, value, sizeof(type)); \
0264 else \
0265 WARN_ON_ONCE(1); \
0266 } \
0267 } \
0268 \
0269 void logic_ins##bwl(unsigned long addr, void *buffer, \
0270 unsigned int count) \
0271 { \
0272 if (addr < MMIO_UPPER_LIMIT) { \
0273 reads##bwl(PCI_IOBASE + addr, buffer, count); \
0274 } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
0275 struct logic_pio_hwaddr *entry = find_io_range(addr); \
0276 \
0277 if (entry) \
0278 entry->ops->ins(entry->hostdata, \
0279 addr, buffer, sizeof(type), count); \
0280 else \
0281 WARN_ON_ONCE(1); \
0282 } \
0283 \
0284 } \
0285 \
0286 void logic_outs##bwl(unsigned long addr, const void *buffer, \
0287 unsigned int count) \
0288 { \
0289 if (addr < MMIO_UPPER_LIMIT) { \
0290 writes##bwl(PCI_IOBASE + addr, buffer, count); \
0291 } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
0292 struct logic_pio_hwaddr *entry = find_io_range(addr); \
0293 \
0294 if (entry) \
0295 entry->ops->outs(entry->hostdata, \
0296 addr, buffer, sizeof(type), count); \
0297 else \
0298 WARN_ON_ONCE(1); \
0299 } \
0300 }
0301
0302 BUILD_LOGIC_IO(b, u8)
0303 EXPORT_SYMBOL(logic_inb);
0304 EXPORT_SYMBOL(logic_insb);
0305 EXPORT_SYMBOL(logic_outb);
0306 EXPORT_SYMBOL(logic_outsb);
0307
0308 BUILD_LOGIC_IO(w, u16)
0309 EXPORT_SYMBOL(logic_inw);
0310 EXPORT_SYMBOL(logic_insw);
0311 EXPORT_SYMBOL(logic_outw);
0312 EXPORT_SYMBOL(logic_outsw);
0313
0314 BUILD_LOGIC_IO(l, u32)
0315 EXPORT_SYMBOL(logic_inl);
0316 EXPORT_SYMBOL(logic_insl);
0317 EXPORT_SYMBOL(logic_outl);
0318 EXPORT_SYMBOL(logic_outsl);
0319
0320 #endif