1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Netronome Systems, Inc.
12 #include <sys/types.h>
14 #include <rte_byteorder.h>
17 #include "nfp_target.h"
18 #include "nfp6000/nfp6000.h"
19 #include "nfp6000/nfp_xpb.h"
22 #define NFP_PL_DEVICE_ID 0x00000004
23 #define NFP_PL_DEVICE_ID_MASK 0xff
25 #define NFP6000_ARM_GCSR_SOFTMODEL0 0x00400144
28 nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv)
34 nfp_cpp_priv(struct nfp_cpp *cpp)
40 nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model)
46 nfp_cpp_model(struct nfp_cpp *cpp)
49 return NFP_CPP_MODEL_INVALID;
52 cpp->model = __nfp_cpp_model_autodetect(cpp);
58 nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface)
60 cpp->interface = interface;
64 nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial)
66 *serial = cpp->serial;
67 return cpp->serial_len;
71 nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial,
77 cpp->serial = malloc(serial_len);
81 memcpy(cpp->serial, serial, serial_len);
82 cpp->serial_len = serial_len;
88 nfp_cpp_interface(struct nfp_cpp *cpp)
91 return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0);
93 return cpp->interface;
97 nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
103 nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
105 return cpp_area->cpp;
109 nfp_cpp_area_name(struct nfp_cpp_area *cpp_area)
111 return cpp_area->name;
115 * nfp_cpp_area_alloc - allocate a new CPP area
118 * @address: start address on CPP target
119 * @size: size of area in bytes
121 * Allocate and initialize a CPP area structure. The area must later
122 * be locked down with an 'acquire' before it can be safely accessed.
124 * NOTE: @address and @size must be 32-bit aligned values.
126 struct nfp_cpp_area *
127 nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, uint32_t dest,
128 const char *name, unsigned long long address,
131 struct nfp_cpp_area *area;
132 uint64_t tmp64 = (uint64_t)address;
138 /* CPP bus uses only a 40-bit address */
139 if ((address + size) > (1ULL << 40))
140 return NFP_ERRPTR(EFAULT);
142 /* Remap from cpp_island to cpp_target */
143 err = nfp_target_cpp(dest, tmp64, &dest, &tmp64, cpp->imb_cat_table);
147 address = (unsigned long long)tmp64;
152 area = calloc(1, sizeof(*area) + cpp->op->area_priv_size +
158 area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size;
159 memcpy(area->name, name, strlen(name) + 1);
162 * Preserve errno around the call to area_init, since most
163 * implementations will blindly call nfp_target_action_width()for both
164 * read or write modes, and that will set errno to EINVAL.
168 err = cpp->op->area_init(area, dest, address, size);
177 area->offset = address;
183 struct nfp_cpp_area *
184 nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t dest,
185 unsigned long long address, unsigned long size)
187 return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size);
191 * nfp_cpp_area_alloc_acquire - allocate a new CPP area and lock it down
195 * @address: start address on CPP target
196 * @size: size of area
198 * Allocate and initilizae a CPP area structure, and lock it down so
199 * that it can be accessed directly.
201 * NOTE: @address and @size must be 32-bit aligned values.
203 * NOTE: The area must also be 'released' when the structure is freed.
205 struct nfp_cpp_area *
206 nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, uint32_t destination,
207 unsigned long long address, unsigned long size)
209 struct nfp_cpp_area *area;
211 area = nfp_cpp_area_alloc(cpp, destination, address, size);
215 if (nfp_cpp_area_acquire(area)) {
216 nfp_cpp_area_free(area);
224 * nfp_cpp_area_free - free up the CPP area
225 * area: CPP area handle
227 * Frees up memory resources held by the CPP area.
230 nfp_cpp_area_free(struct nfp_cpp_area *area)
232 if (area->cpp->op->area_cleanup)
233 area->cpp->op->area_cleanup(area);
238 * nfp_cpp_area_release_free - release CPP area and free it
239 * area: CPP area handle
241 * Releases CPP area and frees up memory resources held by the it.
244 nfp_cpp_area_release_free(struct nfp_cpp_area *area)
246 nfp_cpp_area_release(area);
247 nfp_cpp_area_free(area);
251 * nfp_cpp_area_acquire - lock down a CPP area for access
252 * @area: CPP area handle
254 * Locks down the CPP area for a potential long term activity. Area
255 * must always be locked down before being accessed.
258 nfp_cpp_area_acquire(struct nfp_cpp_area *area)
260 if (area->cpp->op->area_acquire) {
261 int err = area->cpp->op->area_acquire(area);
271 * nfp_cpp_area_release - release a locked down CPP area
272 * @area: CPP area handle
274 * Releases a previously locked down CPP area.
277 nfp_cpp_area_release(struct nfp_cpp_area *area)
279 if (area->cpp->op->area_release)
280 area->cpp->op->area_release(area);
284 * nfp_cpp_area_iomem() - get IOMEM region for CPP area
286 * @area: CPP area handle
288 * Returns an iomem pointer for use with readl()/writel() style operations.
290 * NOTE: Area must have been locked down with an 'acquire'.
292 * Return: pointer to the area, or NULL
295 nfp_cpp_area_iomem(struct nfp_cpp_area *area)
299 if (area->cpp->op->area_iomem)
300 iomem = area->cpp->op->area_iomem(area);
306 * nfp_cpp_area_read - read data from CPP area
308 * @area: CPP area handle
309 * @offset: offset into CPP area
310 * @kernel_vaddr: kernel address to put data into
311 * @length: number of bytes to read
313 * Read data from indicated CPP region.
315 * NOTE: @offset and @length must be 32-bit aligned values.
317 * NOTE: Area must have been locked down with an 'acquire'.
320 nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset,
321 void *kernel_vaddr, size_t length)
323 if ((offset + length) > area->size)
324 return NFP_ERRNO(EFAULT);
326 return area->cpp->op->area_read(area, kernel_vaddr, offset, length);
330 * nfp_cpp_area_write - write data to CPP area
332 * @area: CPP area handle
333 * @offset: offset into CPP area
334 * @kernel_vaddr: kernel address to read data from
335 * @length: number of bytes to write
337 * Write data to indicated CPP region.
339 * NOTE: @offset and @length must be 32-bit aligned values.
341 * NOTE: Area must have been locked down with an 'acquire'.
344 nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset,
345 const void *kernel_vaddr, size_t length)
347 if ((offset + length) > area->size)
348 return NFP_ERRNO(EFAULT);
350 return area->cpp->op->area_write(area, kernel_vaddr, offset, length);
354 nfp_cpp_area_mapped(struct nfp_cpp_area *area)
356 if (area->cpp->op->area_mapped)
357 return area->cpp->op->area_mapped(area);
362 * nfp_cpp_area_check_range - check if address range fits in CPP area
364 * @area: CPP area handle
365 * @offset: offset into CPP area
366 * @length: size of address range in bytes
368 * Check if address range fits within CPP area. Return 0 if area fits
372 nfp_cpp_area_check_range(struct nfp_cpp_area *area, unsigned long long offset,
373 unsigned long length)
375 if (((offset + length) > area->size))
376 return NFP_ERRNO(EFAULT);
382 * Return the correct CPP address, and fixup xpb_addr as needed,
383 * based upon NFP model.
386 nfp_xpb_to_cpp(struct nfp_cpp *cpp, uint32_t *xpb_addr)
391 if (!NFP_CPP_MODEL_IS_6000(cpp->model))
394 xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
397 * Ensure that non-local XPB accesses go out through the
400 island = ((*xpb_addr) >> 24) & 0x3f;
407 * Accesses to the ARM Island overlay uses Island 0
410 (*xpb_addr) &= ~0x7f000000;
411 if (*xpb_addr < 0x60000)
412 *xpb_addr |= (1 << 30);
414 /* And only non-ARM interfaces use island id = 1 */
415 if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) !=
416 NFP_CPP_INTERFACE_TYPE_ARM)
417 *xpb_addr |= (1 << 24);
419 (*xpb_addr) |= (1 << 30);
426 nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset,
432 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
433 *value = rte_le_to_cpu_32(tmp);
435 return (sz == sizeof(*value)) ? 0 : -1;
439 nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset,
444 value = rte_cpu_to_le_32(value);
445 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
446 return (sz == sizeof(value)) ? 0 : -1;
450 nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset,
456 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
457 *value = rte_le_to_cpu_64(tmp);
459 return (sz == sizeof(*value)) ? 0 : -1;
463 nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset,
468 value = rte_cpu_to_le_64(value);
469 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
471 return (sz == sizeof(value)) ? 0 : -1;
475 nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
481 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
482 *value = rte_le_to_cpu_32(tmp);
484 return (sz == sizeof(*value)) ? 0 : -1;
488 nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
493 value = rte_cpu_to_le_32(value);
494 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
496 return (sz == sizeof(value)) ? 0 : -1;
500 nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
506 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
507 *value = rte_le_to_cpu_64(tmp);
509 return (sz == sizeof(*value)) ? 0 : -1;
513 nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
518 value = rte_cpu_to_le_64(value);
519 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
521 return (sz == sizeof(value)) ? 0 : -1;
525 nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t value)
529 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
531 return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value);
535 nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t *value)
539 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
541 return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value);
544 static struct nfp_cpp *
545 nfp_cpp_alloc(const char *devname)
547 const struct nfp_cpp_operations *ops;
551 ops = nfp_cpp_transport_operations();
553 if (!ops || !ops->init)
554 return NFP_ERRPTR(EINVAL);
556 cpp = calloc(1, sizeof(*cpp));
563 err = cpp->op->init(cpp, devname);
570 if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) {
574 for (tgt = 0; tgt < ARRAY_SIZE(cpp->imb_cat_table); tgt++) {
575 /* Hardcoded XPB IMB Base, island 0 */
576 xpbaddr = 0x000a0000 + (tgt * 4);
577 err = nfp_xpb_readl(cpp, xpbaddr,
578 (uint32_t *)&cpp->imb_cat_table[tgt]);
590 * nfp_cpp_free - free the CPP handle
594 nfp_cpp_free(struct nfp_cpp *cpp)
596 if (cpp->op && cpp->op->free)
606 nfp_cpp_from_device_name(const char *devname)
608 return nfp_cpp_alloc(devname);
612 * Modify bits of a 32-bit value from the XPB bus
614 * @param cpp NFP CPP device handle
615 * @param xpb_tgt XPB target and address
616 * @param mask mask of bits to alter
617 * @param value value to modify
619 * @return 0 on success, or -1 on failure (and set errno accordingly).
622 nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
628 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
633 tmp |= (mask & value);
634 return nfp_xpb_writel(cpp, xpb_tgt, tmp);
638 * Modify bits of a 32-bit value from the XPB bus
640 * @param cpp NFP CPP device handle
641 * @param xpb_tgt XPB target and address
642 * @param mask mask of bits to alter
643 * @param value value to monitor for
644 * @param timeout_us maximum number of us to wait (-1 for forever)
646 * @return >= 0 on success, or -1 on failure (and set errno accordingly).
649 nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
650 uint32_t value, int timeout_us)
656 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
660 if ((tmp & mask) == (value & mask)) {
671 } while (timeout_us >= 0);
674 err = NFP_ERRNO(ETIMEDOUT);
683 * nfp_cpp_read - read from CPP target
685 * @destination: CPP id
686 * @address: offset into CPP target
687 * @kernel_vaddr: kernel buffer for result
688 * @length: number of bytes to read
691 nfp_cpp_read(struct nfp_cpp *cpp, uint32_t destination,
692 unsigned long long address, void *kernel_vaddr, size_t length)
694 struct nfp_cpp_area *area;
697 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
699 printf("Area allocation/acquire failed\n");
703 err = nfp_cpp_area_read(area, 0, kernel_vaddr, length);
705 nfp_cpp_area_release_free(area);
710 * nfp_cpp_write - write to CPP target
712 * @destination: CPP id
713 * @address: offset into CPP target
714 * @kernel_vaddr: kernel buffer to read from
715 * @length: number of bytes to write
718 nfp_cpp_write(struct nfp_cpp *cpp, uint32_t destination,
719 unsigned long long address, const void *kernel_vaddr,
722 struct nfp_cpp_area *area;
725 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
729 err = nfp_cpp_area_write(area, 0, kernel_vaddr, length);
731 nfp_cpp_area_release_free(area);
736 * nfp_cpp_area_fill - fill a CPP area with a value
738 * @offset: offset into CPP area
739 * @value: value to fill with
740 * @length: length of area to fill
743 nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
744 uint32_t value, size_t length)
750 value = rte_cpu_to_le_32(value);
751 value64 = ((uint64_t)value << 32) | value;
753 if ((offset + length) > area->size)
754 return NFP_ERRNO(EINVAL);
756 if ((area->offset + offset) & 3)
757 return NFP_ERRNO(EINVAL);
759 if (((area->offset + offset) & 7) == 4 && length >= 4) {
760 err = nfp_cpp_area_write(area, offset, &value, sizeof(value));
763 if (err != sizeof(value))
764 return NFP_ERRNO(ENOSPC);
765 offset += sizeof(value);
766 length -= sizeof(value);
769 for (i = 0; (i + sizeof(value)) < length; i += sizeof(value64)) {
771 nfp_cpp_area_write(area, offset + i, &value64,
775 if (err != sizeof(value64))
776 return NFP_ERRNO(ENOSPC);
779 if ((i + sizeof(value)) <= length) {
781 nfp_cpp_area_write(area, offset + i, &value, sizeof(value));
784 if (err != sizeof(value))
785 return NFP_ERRNO(ENOSPC);
793 * NOTE: This code should not use nfp_xpb_* functions,
794 * as those are model-specific
797 __nfp_cpp_model_autodetect(struct nfp_cpp *cpp)
799 uint32_t arm_id = NFP_CPP_ID(NFP_CPP_TARGET_ARM, 0, 0);
802 nfp_cpp_readl(cpp, arm_id, NFP6000_ARM_GCSR_SOFTMODEL0, &model);
804 if (NFP_CPP_MODEL_IS_6000(model)) {
807 nfp_cpp_model_set(cpp, model);
809 /* The PL's PluDeviceID revision code is authoratative */
811 nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) +
812 NFP_PL_DEVICE_ID, &tmp);
813 model |= (NFP_PL_DEVICE_ID_MASK & tmp) - 0x10;
820 * nfp_cpp_map_area() - Helper function to map an area
821 * @cpp: NFP CPP handler
822 * @domain: CPP domain
823 * @target: CPP target
825 * @size: Size of the area
826 * @area: Area handle (output)
828 * Map an area of IOMEM access. To undo the effect of this function call
829 * @nfp_cpp_area_release_free(*area).
831 * Return: Pointer to memory mapped area or ERR_PTR
834 nfp_cpp_map_area(struct nfp_cpp *cpp, int domain, int target, uint64_t addr,
835 unsigned long size, struct nfp_cpp_area **area)
840 dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain);
842 *area = nfp_cpp_area_alloc_acquire(cpp, dest, addr, size);
846 res = nfp_cpp_area_iomem(*area);
848 goto err_release_free;
853 nfp_cpp_area_release_free(*area);