2 * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
3 * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/acpi.h>
22 #include <linux/rculist.h>
23 #include <linux/sizes.h>
24 #include <linux/slab.h>
26 /* A list of all the IO hosts registered. ONLY THE HOST nodes. */
27 static LIST_HEAD(io_range_list
);
28 static DEFINE_MUTEX(io_range_mutex
);
31 * allocate a free range for this registration.
33 * @new_range: point to the node awaiting this registration.
34 * part of the fields are as input parameters. This node
35 * is allocated and initialized by caller;
36 * @prev: points to the last node before the return;
38 * return 0 for success, other are fail.
40 static int libio_alloc_range(struct libio_range
*new_range
,
41 struct list_head
**prev
)
43 struct libio_range
*entry
;
44 unsigned long align
= 1;
45 unsigned long tmp_start
;
46 unsigned long idle_start
, idle_end
;
48 if (new_range
->flags
& IO_CPU_MMIO
)
51 *prev
= &io_range_list
;
52 list_for_each_entry_rcu(entry
, &io_range_list
, list
) {
53 if (idle_start
> entry
->io_start
) {
54 WARN(1, "skip an invalid io range during traversal!\n");
57 /* set the end edge. */
58 if (idle_start
== entry
->io_start
) {
59 struct libio_range
*next
;
61 idle_start
= entry
->io_start
+ entry
->size
;
62 next
= list_next_or_null_rcu(&io_range_list
,
63 &entry
->list
, struct libio_range
, list
);
71 idle_end
= entry
->io_start
- 1;
73 /* contiguous range... */
74 if (idle_start
> idle_end
)
77 tmp_start
= idle_start
;
78 idle_start
= ALIGN(idle_start
, align
);
79 if (idle_start
>= tmp_start
&&
80 idle_start
+ new_range
->size
<= idle_end
) {
81 new_range
->io_start
= idle_start
;
87 idle_start
= entry
->io_start
+ entry
->size
;
90 /* check the last free gap... */
91 idle_end
= IO_SPACE_LIMIT
;
93 tmp_start
= idle_start
;
94 idle_start
= ALIGN(idle_start
, align
);
95 if (idle_start
>= tmp_start
&&
96 idle_start
+ new_range
->size
<= idle_end
) {
97 new_range
->io_start
= idle_start
;
105 * traverse the io_range_list to find the registered node whose device node
106 * and/or physical IO address match to.
108 struct libio_range
*find_io_range_from_fwnode(struct fwnode_handle
*fwnode
)
110 struct libio_range
*range
;
112 list_for_each_entry_rcu(range
, &io_range_list
, list
) {
113 if (range
->node
== fwnode
)
120 * Search a io_range registered which match the fwnode and addr.
122 * @fwnode: the host fwnode which must be valid;
123 * @start: the start hardware address of this search;
124 * @end: the end hardware address of this search. can be equal to @start;
126 * return NULL when there is no matched node; IS_ERR() means ERROR;
127 * valid virtual address represent a matched node was found.
129 static struct libio_range
*
130 libio_find_range_byaddr(struct fwnode_handle
*fwnode
,
131 resource_size_t start
, resource_size_t end
)
133 struct libio_range
*entry
;
135 list_for_each_entry_rcu(entry
, &io_range_list
, list
) {
136 if (entry
->node
!= fwnode
)
138 /* without any overlap with current range */
139 if (start
>= entry
->hw_start
+ entry
->size
||
140 end
< entry
->hw_start
)
142 /* overlap is not supported now. */
143 if (start
< entry
->hw_start
||
144 end
>= entry
->hw_start
+ entry
->size
)
145 return ERR_PTR(-EBUSY
);
146 /* had been registered. */
154 * register a io range node in the io range list.
156 * @newrange: pointer to the io range to be registered.
158 * return 'newrange' when success, ERR_VALUE() is for failures.
159 * specially, return a valid pointer which is not equal to 'newrange' when
160 * the io range had been registered before.
162 struct libio_range
*register_libio_range(struct libio_range
*newrange
)
165 struct libio_range
*range
;
166 struct list_head
*prev
;
168 if (!newrange
|| !newrange
->node
|| !newrange
->size
)
169 return ERR_PTR(-EINVAL
);
171 mutex_lock(&io_range_mutex
);
172 range
= libio_find_range_byaddr(newrange
->node
, newrange
->hw_start
,
173 newrange
->hw_start
+ newrange
->size
- 1);
176 pr_info("the request IO range had been registered!\n");
178 pr_err("registering IO[%pa - sz%pa) got failed!\n",
179 &newrange
->hw_start
, &newrange
->size
);
183 err
= libio_alloc_range(newrange
, &prev
);
185 /* the bus IO range list is ordered by pio. */
186 list_add_rcu(&newrange
->list
, prev
);
188 pr_err("can't find free %pa logical IO range!\n",
191 mutex_unlock(&io_range_mutex
);
192 return err
? ERR_PTR(err
) : newrange
;
196 * Translate the input logical pio to the corresponding hardware address.
197 * The input pio should be unique in the whole logical PIO space.
199 resource_size_t
libio_to_hwaddr(unsigned long pio
)
201 struct libio_range
*range
;
203 list_for_each_entry_rcu(range
, &io_range_list
, list
) {
204 if (pio
< range
->io_start
)
207 if (pio
< range
->io_start
+ range
->size
)
208 return pio
- range
->io_start
+ range
->hw_start
;
215 * This function is generic for translating a hardware address to logical PIO.
216 * @hw_addr: the hardware address of host, can be CPU address or host-local
220 libio_translate_hwaddr(struct fwnode_handle
*fwnode
, resource_size_t addr
)
222 struct libio_range
*range
;
224 range
= libio_find_range_byaddr(fwnode
, addr
, addr
);
228 return addr
- range
->hw_start
+ range
->io_start
;
232 libio_translate_cpuaddr(resource_size_t addr
)
234 struct libio_range
*range
;
236 list_for_each_entry_rcu(range
, &io_range_list
, list
) {
237 if (!(range
->flags
& IO_CPU_MMIO
))
239 if (addr
>= range
->hw_start
&&
240 addr
< range
->hw_start
+ range
->size
)
241 return addr
- range
->hw_start
+ range
->io_start
;
247 static inline bool acpi_libio_supported_resource(struct acpi_resource
*res
)
250 case ACPI_RESOURCE_TYPE_ADDRESS32
:
251 case ACPI_RESOURCE_TYPE_ADDRESS64
:
257 static acpi_status
acpi_count_libiores(struct acpi_resource
*res
,
262 if (acpi_libio_supported_resource(res
) &&
263 !acpi_dev_filter_resource_type(res
, IORESOURCE_IO
))
269 static acpi_status
acpi_read_one_libiores(struct acpi_resource
*res
,
272 struct acpi_resource
**resource
= data
;
274 if (acpi_libio_supported_resource(res
) &&
275 !acpi_dev_filter_resource_type(res
, IORESOURCE_IO
)) {
276 memcpy((*resource
), res
, sizeof(struct acpi_resource
));
277 (*resource
)->length
= sizeof(struct acpi_resource
);
278 (*resource
)->type
= res
->type
;
286 acpi_build_libiores_template(struct acpi_device
*adev
,
287 struct acpi_buffer
*buffer
)
289 acpi_handle handle
= adev
->handle
;
290 struct acpi_resource
*resource
;
294 status
= acpi_walk_resources(handle
, METHOD_NAME__CRS
,
295 acpi_count_libiores
, &res_cnt
);
296 if (ACPI_FAILURE(status
) || !res_cnt
) {
297 dev_err(&adev
->dev
, "can't evaluate _CRS: %d\n", status
);
301 buffer
->length
= sizeof(struct acpi_resource
) * (res_cnt
+ 1) + 1;
302 buffer
->pointer
= kzalloc(buffer
->length
- 1, GFP_KERNEL
);
303 if (!buffer
->pointer
)
306 resource
= (struct acpi_resource
*)buffer
->pointer
;
307 status
= acpi_walk_resources(handle
, METHOD_NAME__CRS
,
308 acpi_read_one_libiores
, &resource
);
309 if (ACPI_FAILURE(status
)) {
310 kfree(buffer
->pointer
);
311 dev_err(&adev
->dev
, "can't evaluate _CRS: %d\n", status
);
315 resource
->type
= ACPI_RESOURCE_TYPE_END_TAG
;
316 resource
->length
= sizeof(struct acpi_resource
);
321 static int acpi_translate_libiores(struct acpi_device
*adev
,
322 struct acpi_device
*host
, struct acpi_buffer
*buffer
)
324 int res_cnt
= (buffer
->length
- 1) / sizeof(struct acpi_resource
) - 1;
325 struct acpi_resource
*resource
= buffer
->pointer
;
326 struct acpi_resource_address64 addr
;
327 unsigned long sys_port
;
328 struct device
*dev
= &adev
->dev
;
330 /* only one I/O resource now */
332 dev_err(dev
, "encode %d resources whose type is(%d)!\n",
333 res_cnt
, resource
->type
);
337 if (ACPI_FAILURE(acpi_resource_to_address64(resource
, &addr
))) {
338 dev_err(dev
, "convert acpi resource(%d) as addr64 FAIL!\n",
343 /* For indirect-IO, addr length must be fixed. (>0, 0/1, 0/1)(0,0,0) */
344 if (addr
.min_address_fixed
!= addr
.max_address_fixed
) {
345 dev_warn(dev
, "variable I/O resource is invalid!\n");
349 dev_dbg(dev
, "CRS IO: len=0x%llx [0x%llx - 0x%llx]\n",
350 addr
.address
.address_length
, addr
.address
.minimum
,
351 addr
.address
.maximum
);
352 sys_port
= libio_translate_hwaddr(&host
->fwnode
, addr
.address
.minimum
);
353 if (sys_port
== -1) {
354 dev_err(dev
, "translate bus-addr(0x%llx) fail!\n",
355 addr
.address
.minimum
);
359 switch (resource
->type
) {
360 case ACPI_RESOURCE_TYPE_ADDRESS32
:
362 struct acpi_resource_address32
*out_res
;
364 out_res
= &resource
->data
.address32
;
365 if (!addr
.address
.address_length
)
366 addr
.address
.address_length
= out_res
->address
.maximum
-
367 out_res
->address
.minimum
+ 1;
368 out_res
->address
.minimum
= sys_port
;
369 out_res
->address
.maximum
= sys_port
+
370 addr
.address
.address_length
- 1;
371 out_res
->address
.address_length
= addr
.address
.address_length
;
373 dev_info(dev
, "_SRS 32IO: [0x%x - 0x%x] len = 0x%x\n",
374 out_res
->address
.minimum
,
375 out_res
->address
.maximum
,
376 out_res
->address
.address_length
);
381 case ACPI_RESOURCE_TYPE_ADDRESS64
:
383 struct acpi_resource_address64
*out_res
;
385 out_res
= &resource
->data
.address64
;
386 if (!addr
.address
.address_length
)
387 addr
.address
.address_length
= out_res
->address
.maximum
-
388 out_res
->address
.minimum
+ 1;
389 out_res
->address
.minimum
= sys_port
;
390 out_res
->address
.maximum
= sys_port
+
391 addr
.address
.address_length
- 1;
392 out_res
->address
.address_length
= addr
.address
.address_length
;
394 dev_info(dev
, "_SRS 64IO: [0x%llx - 0x%llx] len = 0x%llx\n",
395 out_res
->address
.minimum
,
396 out_res
->address
.maximum
,
397 out_res
->address
.address_length
);
411 * update/set the current I/O resource of the designated device node.
412 * after this calling, the enumeration can be started as the I/O resource
413 * had been translated to logicial I/O from bus-local I/O.
415 * @adev: the device node to be updated the I/O resource;
416 * @host: the device node where 'adev' is attached, which can be not
417 * the parent of 'adev';
419 * return 0 when successful, negative is for failure.
421 int acpi_set_libio_resource(struct device
*child
,
422 struct device
*hostdev
)
424 struct acpi_device
*adev
;
425 struct acpi_device
*host
;
426 struct acpi_buffer buffer
;
430 if (!child
|| !hostdev
)
433 host
= to_acpi_device(hostdev
);
434 adev
= to_acpi_device(child
);
436 /* check the device state */
437 if (!adev
->status
.present
) {
438 dev_info(child
, "ACPI: device is not present!\n");
441 /* whether the child had been enumerated? */
442 if (acpi_device_enumerated(adev
)) {
443 dev_info(child
, "ACPI: had been enumerated!\n");
447 /* read the _CRS and convert as acpi_buffer */
448 status
= acpi_build_libiores_template(adev
, &buffer
);
449 if (ACPI_FAILURE(status
)) {
450 dev_warn(child
, "Failure evaluating %s\n", METHOD_NAME__CRS
);
454 /* translate the I/O resources */
455 ret
= acpi_translate_libiores(adev
, host
, &buffer
);
457 kfree(buffer
.pointer
);
458 dev_err(child
, "Translate I/O range FAIL!\n");
462 /* set current resource... */
463 status
= acpi_set_current_resources(adev
->handle
, &buffer
);
464 kfree(buffer
.pointer
);
465 if (ACPI_FAILURE(status
)) {
466 dev_err(child
, "Error evaluating _SRS (0x%x)\n", status
);
475 static struct libio_range
*find_io_range(unsigned long pio
)
477 struct libio_range
*range
;
479 list_for_each_entry_rcu(range
, &io_range_list
, list
) {
480 if (range
->io_start
> pio
)
482 if (pio
< range
->io_start
+ range
->size
)
488 #define BUILD_IO(bw, type) \
489 type libio_in##bw(unsigned long addr) \
491 struct libio_range *entry = find_io_range(addr); \
493 if (entry && entry->ops) \
494 return entry->ops->pfin(entry->devpara, \
495 addr, sizeof(type)); \
496 return read##bw(PCI_IOBASE + addr); \
499 void libio_out##bw(type value, unsigned long addr) \
501 struct libio_range *entry = find_io_range(addr); \
503 if (entry && entry->ops) \
504 entry->ops->pfout(entry->devpara, \
505 addr, value, sizeof(type)); \
507 write##bw(value, PCI_IOBASE + addr); \
510 void libio_ins##bw(unsigned long addr, void *buffer, unsigned int count)\
512 struct libio_range *entry = find_io_range(addr); \
514 if (entry && entry->ops) \
515 entry->ops->pfins(entry->devpara, \
516 addr, buffer, sizeof(type), count); \
518 reads##bw(PCI_IOBASE + addr, buffer, count); \
521 void libio_outs##bw(unsigned long addr, const void *buffer, \
522 unsigned int count) \
524 struct libio_range *entry = find_io_range(addr); \
526 if (entry && entry->ops) \
527 entry->ops->pfouts(entry->devpara, \
528 addr, buffer, sizeof(type), count); \
530 writes##bw(PCI_IOBASE + addr, buffer, count); \
535 EXPORT_SYMBOL(libio_inb
);
536 EXPORT_SYMBOL(libio_outb
);
537 EXPORT_SYMBOL(libio_insb
);
538 EXPORT_SYMBOL(libio_outsb
);
542 EXPORT_SYMBOL(libio_inw
);
543 EXPORT_SYMBOL(libio_outw
);
544 EXPORT_SYMBOL(libio_insw
);
545 EXPORT_SYMBOL(libio_outsw
);
549 EXPORT_SYMBOL(libio_inl
);
550 EXPORT_SYMBOL(libio_outl
);
551 EXPORT_SYMBOL(libio_insl
);
552 EXPORT_SYMBOL(libio_outsl
);
553 #endif /* PCI_IOBASE */