1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Netronome Systems, Inc.
12 #include <sys/types.h>
14 #include <rte_byteorder.h>
15 #include <rte_ethdev_pci.h>
18 #include "nfp_target.h"
19 #include "nfp6000/nfp6000.h"
20 #include "nfp6000/nfp_xpb.h"
23 #define NFP_PL_DEVICE_ID 0x00000004
24 #define NFP_PL_DEVICE_ID_MASK 0xff
26 #define NFP6000_ARM_GCSR_SOFTMODEL0 0x00400144
29 nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv)
35 nfp_cpp_priv(struct nfp_cpp *cpp)
41 nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model)
47 nfp_cpp_model(struct nfp_cpp *cpp)
50 return NFP_CPP_MODEL_INVALID;
53 cpp->model = __nfp_cpp_model_autodetect(cpp);
59 nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface)
61 cpp->interface = interface;
65 nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial)
67 *serial = cpp->serial;
68 return cpp->serial_len;
72 nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial,
78 cpp->serial = malloc(serial_len);
82 memcpy(cpp->serial, serial, serial_len);
83 cpp->serial_len = serial_len;
89 nfp_cpp_interface(struct nfp_cpp *cpp)
92 return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0);
94 return cpp->interface;
98 nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
104 nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
106 return cpp_area->cpp;
110 nfp_cpp_area_name(struct nfp_cpp_area *cpp_area)
112 return cpp_area->name;
116 * nfp_cpp_area_alloc - allocate a new CPP area
119 * @address: start address on CPP target
120 * @size: size of area in bytes
122 * Allocate and initialize a CPP area structure. The area must later
123 * be locked down with an 'acquire' before it can be safely accessed.
125 * NOTE: @address and @size must be 32-bit aligned values.
127 struct nfp_cpp_area *
128 nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, uint32_t dest,
129 const char *name, unsigned long long address,
132 struct nfp_cpp_area *area;
133 uint64_t tmp64 = (uint64_t)address;
139 /* CPP bus uses only a 40-bit address */
140 if ((address + size) > (1ULL << 40))
141 return NFP_ERRPTR(EFAULT);
143 /* Remap from cpp_island to cpp_target */
144 err = nfp_target_cpp(dest, tmp64, &dest, &tmp64, cpp->imb_cat_table);
148 address = (unsigned long long)tmp64;
153 area = calloc(1, sizeof(*area) + cpp->op->area_priv_size +
159 area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size;
160 memcpy(area->name, name, strlen(name) + 1);
163 * Preserve errno around the call to area_init, since most
164 * implementations will blindly call nfp_target_action_width()for both
165 * read or write modes, and that will set errno to EINVAL.
169 err = cpp->op->area_init(area, dest, address, size);
178 area->offset = address;
184 struct nfp_cpp_area *
185 nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t dest,
186 unsigned long long address, unsigned long size)
188 return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size);
192 * nfp_cpp_area_alloc_acquire - allocate a new CPP area and lock it down
196 * @address: start address on CPP target
197 * @size: size of area
199 * Allocate and initilizae a CPP area structure, and lock it down so
200 * that it can be accessed directly.
202 * NOTE: @address and @size must be 32-bit aligned values.
204 * NOTE: The area must also be 'released' when the structure is freed.
206 struct nfp_cpp_area *
207 nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, uint32_t destination,
208 unsigned long long address, unsigned long size)
210 struct nfp_cpp_area *area;
212 area = nfp_cpp_area_alloc(cpp, destination, address, size);
216 if (nfp_cpp_area_acquire(area)) {
217 nfp_cpp_area_free(area);
225 * nfp_cpp_area_free - free up the CPP area
226 * area: CPP area handle
228 * Frees up memory resources held by the CPP area.
231 nfp_cpp_area_free(struct nfp_cpp_area *area)
233 if (area->cpp->op->area_cleanup)
234 area->cpp->op->area_cleanup(area);
239 * nfp_cpp_area_release_free - release CPP area and free it
240 * area: CPP area handle
242 * Releases CPP area and frees up memory resources held by the it.
245 nfp_cpp_area_release_free(struct nfp_cpp_area *area)
247 nfp_cpp_area_release(area);
248 nfp_cpp_area_free(area);
252 * nfp_cpp_area_acquire - lock down a CPP area for access
253 * @area: CPP area handle
255 * Locks down the CPP area for a potential long term activity. Area
256 * must always be locked down before being accessed.
259 nfp_cpp_area_acquire(struct nfp_cpp_area *area)
261 if (area->cpp->op->area_acquire) {
262 int err = area->cpp->op->area_acquire(area);
272 * nfp_cpp_area_release - release a locked down CPP area
273 * @area: CPP area handle
275 * Releases a previously locked down CPP area.
278 nfp_cpp_area_release(struct nfp_cpp_area *area)
280 if (area->cpp->op->area_release)
281 area->cpp->op->area_release(area);
285 * nfp_cpp_area_iomem() - get IOMEM region for CPP area
287 * @area: CPP area handle
289 * Returns an iomem pointer for use with readl()/writel() style operations.
291 * NOTE: Area must have been locked down with an 'acquire'.
293 * Return: pointer to the area, or NULL
296 nfp_cpp_area_iomem(struct nfp_cpp_area *area)
300 if (area->cpp->op->area_iomem)
301 iomem = area->cpp->op->area_iomem(area);
307 * nfp_cpp_area_read - read data from CPP area
309 * @area: CPP area handle
310 * @offset: offset into CPP area
311 * @kernel_vaddr: kernel address to put data into
312 * @length: number of bytes to read
314 * Read data from indicated CPP region.
316 * NOTE: @offset and @length must be 32-bit aligned values.
318 * NOTE: Area must have been locked down with an 'acquire'.
321 nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset,
322 void *kernel_vaddr, size_t length)
324 if ((offset + length) > area->size)
325 return NFP_ERRNO(EFAULT);
327 return area->cpp->op->area_read(area, kernel_vaddr, offset, length);
331 * nfp_cpp_area_write - write data to CPP area
333 * @area: CPP area handle
334 * @offset: offset into CPP area
335 * @kernel_vaddr: kernel address to read data from
336 * @length: number of bytes to write
338 * Write data to indicated CPP region.
340 * NOTE: @offset and @length must be 32-bit aligned values.
342 * NOTE: Area must have been locked down with an 'acquire'.
345 nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset,
346 const void *kernel_vaddr, size_t length)
348 if ((offset + length) > area->size)
349 return NFP_ERRNO(EFAULT);
351 return area->cpp->op->area_write(area, kernel_vaddr, offset, length);
355 nfp_cpp_area_mapped(struct nfp_cpp_area *area)
357 if (area->cpp->op->area_mapped)
358 return area->cpp->op->area_mapped(area);
363 * nfp_cpp_area_check_range - check if address range fits in CPP area
365 * @area: CPP area handle
366 * @offset: offset into CPP area
367 * @length: size of address range in bytes
369 * Check if address range fits within CPP area. Return 0 if area fits
373 nfp_cpp_area_check_range(struct nfp_cpp_area *area, unsigned long long offset,
374 unsigned long length)
376 if (((offset + length) > area->size))
377 return NFP_ERRNO(EFAULT);
383 * Return the correct CPP address, and fixup xpb_addr as needed,
384 * based upon NFP model.
387 nfp_xpb_to_cpp(struct nfp_cpp *cpp, uint32_t *xpb_addr)
392 if (!NFP_CPP_MODEL_IS_6000(cpp->model))
395 xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
398 * Ensure that non-local XPB accesses go out through the
401 island = ((*xpb_addr) >> 24) & 0x3f;
408 * Accesses to the ARM Island overlay uses Island 0
411 (*xpb_addr) &= ~0x7f000000;
412 if (*xpb_addr < 0x60000)
413 *xpb_addr |= (1 << 30);
415 /* And only non-ARM interfaces use island id = 1 */
416 if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) !=
417 NFP_CPP_INTERFACE_TYPE_ARM)
418 *xpb_addr |= (1 << 24);
420 (*xpb_addr) |= (1 << 30);
427 nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset,
433 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
434 *value = rte_le_to_cpu_32(tmp);
436 return (sz == sizeof(*value)) ? 0 : -1;
440 nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset,
445 value = rte_cpu_to_le_32(value);
446 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
447 return (sz == sizeof(value)) ? 0 : -1;
451 nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset,
457 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
458 *value = rte_le_to_cpu_64(tmp);
460 return (sz == sizeof(*value)) ? 0 : -1;
464 nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset,
469 value = rte_cpu_to_le_64(value);
470 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
472 return (sz == sizeof(value)) ? 0 : -1;
476 nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
482 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
483 *value = rte_le_to_cpu_32(tmp);
485 return (sz == sizeof(*value)) ? 0 : -1;
489 nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
494 value = rte_cpu_to_le_32(value);
495 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
497 return (sz == sizeof(value)) ? 0 : -1;
501 nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
507 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
508 *value = rte_le_to_cpu_64(tmp);
510 return (sz == sizeof(*value)) ? 0 : -1;
514 nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
519 value = rte_cpu_to_le_64(value);
520 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
522 return (sz == sizeof(value)) ? 0 : -1;
526 nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t value)
530 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
532 return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value);
536 nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t *value)
540 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
542 return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value);
545 static struct nfp_cpp *
546 nfp_cpp_alloc(struct rte_pci_device *dev, int driver_lock_needed)
548 const struct nfp_cpp_operations *ops;
552 ops = nfp_cpp_transport_operations();
554 if (!ops || !ops->init)
555 return NFP_ERRPTR(EINVAL);
557 cpp = calloc(1, sizeof(*cpp));
562 cpp->driver_lock_needed = driver_lock_needed;
565 err = cpp->op->init(cpp, dev);
572 if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) {
576 for (tgt = 0; tgt < ARRAY_SIZE(cpp->imb_cat_table); tgt++) {
577 /* Hardcoded XPB IMB Base, island 0 */
578 xpbaddr = 0x000a0000 + (tgt * 4);
579 err = nfp_xpb_readl(cpp, xpbaddr,
580 (uint32_t *)&cpp->imb_cat_table[tgt]);
592 * nfp_cpp_free - free the CPP handle
596 nfp_cpp_free(struct nfp_cpp *cpp)
598 if (cpp->op && cpp->op->free)
608 nfp_cpp_from_device_name(struct rte_pci_device *dev, int driver_lock_needed)
610 return nfp_cpp_alloc(dev, driver_lock_needed);
614 * Modify bits of a 32-bit value from the XPB bus
616 * @param cpp NFP CPP device handle
617 * @param xpb_tgt XPB target and address
618 * @param mask mask of bits to alter
619 * @param value value to modify
621 * @return 0 on success, or -1 on failure (and set errno accordingly).
624 nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
630 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
635 tmp |= (mask & value);
636 return nfp_xpb_writel(cpp, xpb_tgt, tmp);
640 * Modify bits of a 32-bit value from the XPB bus
642 * @param cpp NFP CPP device handle
643 * @param xpb_tgt XPB target and address
644 * @param mask mask of bits to alter
645 * @param value value to monitor for
646 * @param timeout_us maximum number of us to wait (-1 for forever)
648 * @return >= 0 on success, or -1 on failure (and set errno accordingly).
651 nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
652 uint32_t value, int timeout_us)
658 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
662 if ((tmp & mask) == (value & mask)) {
673 } while (timeout_us >= 0);
676 err = NFP_ERRNO(ETIMEDOUT);
685 * nfp_cpp_read - read from CPP target
687 * @destination: CPP id
688 * @address: offset into CPP target
689 * @kernel_vaddr: kernel buffer for result
690 * @length: number of bytes to read
693 nfp_cpp_read(struct nfp_cpp *cpp, uint32_t destination,
694 unsigned long long address, void *kernel_vaddr, size_t length)
696 struct nfp_cpp_area *area;
699 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
701 printf("Area allocation/acquire failed\n");
705 err = nfp_cpp_area_read(area, 0, kernel_vaddr, length);
707 nfp_cpp_area_release_free(area);
712 * nfp_cpp_write - write to CPP target
714 * @destination: CPP id
715 * @address: offset into CPP target
716 * @kernel_vaddr: kernel buffer to read from
717 * @length: number of bytes to write
720 nfp_cpp_write(struct nfp_cpp *cpp, uint32_t destination,
721 unsigned long long address, const void *kernel_vaddr,
724 struct nfp_cpp_area *area;
727 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
731 err = nfp_cpp_area_write(area, 0, kernel_vaddr, length);
733 nfp_cpp_area_release_free(area);
738 * nfp_cpp_area_fill - fill a CPP area with a value
740 * @offset: offset into CPP area
741 * @value: value to fill with
742 * @length: length of area to fill
745 nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
746 uint32_t value, size_t length)
752 value = rte_cpu_to_le_32(value);
753 value64 = ((uint64_t)value << 32) | value;
755 if ((offset + length) > area->size)
756 return NFP_ERRNO(EINVAL);
758 if ((area->offset + offset) & 3)
759 return NFP_ERRNO(EINVAL);
761 if (((area->offset + offset) & 7) == 4 && length >= 4) {
762 err = nfp_cpp_area_write(area, offset, &value, sizeof(value));
765 if (err != sizeof(value))
766 return NFP_ERRNO(ENOSPC);
767 offset += sizeof(value);
768 length -= sizeof(value);
771 for (i = 0; (i + sizeof(value)) < length; i += sizeof(value64)) {
773 nfp_cpp_area_write(area, offset + i, &value64,
777 if (err != sizeof(value64))
778 return NFP_ERRNO(ENOSPC);
781 if ((i + sizeof(value)) <= length) {
783 nfp_cpp_area_write(area, offset + i, &value, sizeof(value));
786 if (err != sizeof(value))
787 return NFP_ERRNO(ENOSPC);
795 * NOTE: This code should not use nfp_xpb_* functions,
796 * as those are model-specific
799 __nfp_cpp_model_autodetect(struct nfp_cpp *cpp)
801 uint32_t arm_id = NFP_CPP_ID(NFP_CPP_TARGET_ARM, 0, 0);
804 if (nfp_cpp_readl(cpp, arm_id, NFP6000_ARM_GCSR_SOFTMODEL0, &model))
807 if (NFP_CPP_MODEL_IS_6000(model)) {
810 nfp_cpp_model_set(cpp, model);
812 /* The PL's PluDeviceID revision code is authoratative */
814 if (nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) +
815 NFP_PL_DEVICE_ID, &tmp))
818 model |= (NFP_PL_DEVICE_ID_MASK & tmp) - 0x10;
825 * nfp_cpp_map_area() - Helper function to map an area
826 * @cpp: NFP CPP handler
827 * @domain: CPP domain
828 * @target: CPP target
830 * @size: Size of the area
831 * @area: Area handle (output)
833 * Map an area of IOMEM access. To undo the effect of this function call
834 * @nfp_cpp_area_release_free(*area).
836 * Return: Pointer to memory mapped area or ERR_PTR
839 nfp_cpp_map_area(struct nfp_cpp *cpp, int domain, int target, uint64_t addr,
840 unsigned long size, struct nfp_cpp_area **area)
845 dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain);
847 *area = nfp_cpp_area_alloc_acquire(cpp, dest, addr, size);
851 res = nfp_cpp_area_iomem(*area);
853 goto err_release_free;
858 nfp_cpp_area_release_free(*area);