1c7e9729dSAlejandro Lucero /* SPDX-License-Identifier: BSD-3-Clause 2c7e9729dSAlejandro Lucero * Copyright(c) 2018 Netronome Systems, Inc. 3c7e9729dSAlejandro Lucero * All rights reserved. 4c7e9729dSAlejandro Lucero */ 5c7e9729dSAlejandro Lucero 6ff627b74SChaoyong He #include "nfp_cpp.h" 7c7e9729dSAlejandro Lucero 8a3460357SChaoyong He #include <nfp_platform.h> 9a3460357SChaoyong He 1052d810dcSJames Hershaw #include "nfp_logs.h" 11055ccb33SChaoyong He #include "nfp_target.h" 12c7e9729dSAlejandro Lucero #include "nfp6000/nfp6000.h" 13c7e9729dSAlejandro Lucero #include "nfp6000/nfp_xpb.h" 14e96559a1SChaoyong He #include "nfp6000_pcie.h" 15c7e9729dSAlejandro Lucero 16ff627b74SChaoyong He #define NFP_PL_DEVICE_PART_NFP6000 0x6200 17c7e9729dSAlejandro Lucero #define NFP_PL_DEVICE_ID 0x00000004 18c7e9729dSAlejandro Lucero #define NFP_PL_DEVICE_ID_MASK 0xff 19c0a8b024SHeinrich Kuhn #define NFP_PL_DEVICE_PART_MASK 0xffff0000 20c0a8b024SHeinrich Kuhn #define NFP_PL_DEVICE_MODEL_MASK (NFP_PL_DEVICE_PART_MASK | \ 21c0a8b024SHeinrich Kuhn NFP_PL_DEVICE_ID_MASK) 22c7e9729dSAlejandro Lucero 23ff627b74SChaoyong He /* NFP CPP handle */ 24ff627b74SChaoyong He struct nfp_cpp { 25ff627b74SChaoyong He void *priv; /**< Private data of the low-level implementation */ 26ff627b74SChaoyong He 27ff627b74SChaoyong He uint32_t model; /**< Chip model */ 28ff627b74SChaoyong He uint16_t interface; /**< Chip interface id */ 29ff627b74SChaoyong He uint8_t serial[NFP_SERIAL_LEN]; /**< Chip serial number */ 30ff627b74SChaoyong He 31ff627b74SChaoyong He /** Low-level implementation ops */ 32ff627b74SChaoyong He const struct nfp_cpp_operations *op; 33ff627b74SChaoyong He 34ff627b74SChaoyong He /* 35ff627b74SChaoyong He * NFP-6xxx originating island IMB CPP Address Translation. CPP Target 36ff627b74SChaoyong He * ID is index into array. Values are obtained at runtime from local 37ff627b74SChaoyong He * island XPB CSRs. 38ff627b74SChaoyong He */ 39ff627b74SChaoyong He uint32_t imb_cat_table[16]; 40ff627b74SChaoyong He 41ff627b74SChaoyong He /**< MU access type bit offset */ 42ff627b74SChaoyong He uint32_t mu_locality_lsb; 43ff627b74SChaoyong He 44ff627b74SChaoyong He bool driver_lock_needed; 45ff627b74SChaoyong He }; 46ff627b74SChaoyong He 47ff627b74SChaoyong He /* NFP CPP device area handle */ 48ff627b74SChaoyong He struct nfp_cpp_area { 49ff627b74SChaoyong He struct nfp_cpp *cpp; 50ff627b74SChaoyong He char *name; 51ff627b74SChaoyong He uint64_t offset; 52ff627b74SChaoyong He uint32_t size; 53ff627b74SChaoyong He /* Here follows the 'priv' part of nfp_cpp_area. */ 54ff627b74SChaoyong He /* Here follows the ASCII name, pointed by @name */ 55ff627b74SChaoyong He }; 56ff627b74SChaoyong He 576d03aa61SChaoyong He /** 586d03aa61SChaoyong He * Set the private data of the nfp_cpp instance 596d03aa61SChaoyong He * 606d03aa61SChaoyong He * @param cpp 616d03aa61SChaoyong He * NFP CPP operations structure 626d03aa61SChaoyong He * 636d03aa61SChaoyong He * @return 646d03aa61SChaoyong He * Opaque device pointer 656d03aa61SChaoyong He */ 66c7e9729dSAlejandro Lucero void 67d108b9e9SChaoyong He nfp_cpp_priv_set(struct nfp_cpp *cpp, 68d108b9e9SChaoyong He void *priv) 69c7e9729dSAlejandro Lucero { 70c7e9729dSAlejandro Lucero cpp->priv = priv; 71c7e9729dSAlejandro Lucero } 72c7e9729dSAlejandro Lucero 736d03aa61SChaoyong He /** 746d03aa61SChaoyong He * Return the private data of the nfp_cpp instance 756d03aa61SChaoyong He * 766d03aa61SChaoyong He * @param cpp 776d03aa61SChaoyong He * NFP CPP operations structure 786d03aa61SChaoyong He * 796d03aa61SChaoyong He * @return 806d03aa61SChaoyong He * Opaque device pointer 816d03aa61SChaoyong He */ 82c7e9729dSAlejandro Lucero void * 83c7e9729dSAlejandro Lucero nfp_cpp_priv(struct nfp_cpp *cpp) 84c7e9729dSAlejandro Lucero { 85c7e9729dSAlejandro Lucero return cpp->priv; 86c7e9729dSAlejandro Lucero } 87c7e9729dSAlejandro Lucero 886d03aa61SChaoyong He /** 896d03aa61SChaoyong He * Set the model id 906d03aa61SChaoyong He * 916d03aa61SChaoyong He * @param cpp 926d03aa61SChaoyong He * NFP CPP operations structure 936d03aa61SChaoyong He * @param model 946d03aa61SChaoyong He * Model ID 956d03aa61SChaoyong He */ 96c7e9729dSAlejandro Lucero void 97d108b9e9SChaoyong He nfp_cpp_model_set(struct nfp_cpp *cpp, 98d108b9e9SChaoyong He uint32_t model) 99c7e9729dSAlejandro Lucero { 100c7e9729dSAlejandro Lucero cpp->model = model; 101c7e9729dSAlejandro Lucero } 102c7e9729dSAlejandro Lucero 1036d03aa61SChaoyong He /** 1046d03aa61SChaoyong He * Retrieve the Model ID of the NFP 1056d03aa61SChaoyong He * 1066d03aa61SChaoyong He * @param cpp 1076d03aa61SChaoyong He * NFP CPP handle 1086d03aa61SChaoyong He * 1096d03aa61SChaoyong He * @return 1106d03aa61SChaoyong He * NFP CPP Model ID 1116d03aa61SChaoyong He */ 112c7e9729dSAlejandro Lucero uint32_t 113c7e9729dSAlejandro Lucero nfp_cpp_model(struct nfp_cpp *cpp) 114c7e9729dSAlejandro Lucero { 115c0a8b024SHeinrich Kuhn int err; 116c0a8b024SHeinrich Kuhn uint32_t model; 117c0a8b024SHeinrich Kuhn 118cbcbfd73SJames Hershaw if (cpp == NULL) 119c7e9729dSAlejandro Lucero return NFP_CPP_MODEL_INVALID; 120c7e9729dSAlejandro Lucero 121588c5b10SChaoyong He err = nfp_cpp_model_autodetect(cpp, &model); 122c7e9729dSAlejandro Lucero 123c0a8b024SHeinrich Kuhn if (err < 0) 124c0a8b024SHeinrich Kuhn return err; 125c0a8b024SHeinrich Kuhn 126c0a8b024SHeinrich Kuhn return model; 127c7e9729dSAlejandro Lucero } 128c7e9729dSAlejandro Lucero 1296d03aa61SChaoyong He /** 1306d03aa61SChaoyong He * Set the private instance owned data of a nfp_cpp struct 1316d03aa61SChaoyong He * 1326d03aa61SChaoyong He * @param cpp 1336d03aa61SChaoyong He * NFP CPP operations structure 1346d03aa61SChaoyong He * @param interface 1356d03aa61SChaoyong He * Interface ID 1366d03aa61SChaoyong He */ 137c7e9729dSAlejandro Lucero void 138d108b9e9SChaoyong He nfp_cpp_interface_set(struct nfp_cpp *cpp, 139d108b9e9SChaoyong He uint32_t interface) 140c7e9729dSAlejandro Lucero { 141c7e9729dSAlejandro Lucero cpp->interface = interface; 142c7e9729dSAlejandro Lucero } 143c7e9729dSAlejandro Lucero 1446d03aa61SChaoyong He /** 1456d03aa61SChaoyong He * Retrieve the Serial ID of the NFP 1466d03aa61SChaoyong He * 1476d03aa61SChaoyong He * @param cpp 1486d03aa61SChaoyong He * NFP CPP handle 1496d03aa61SChaoyong He * @param serial 1506d03aa61SChaoyong He * Pointer to NFP serial number 1516d03aa61SChaoyong He * 1526d03aa61SChaoyong He * @return 1536d03aa61SChaoyong He * Length of NFP serial number 1546d03aa61SChaoyong He */ 155ff627b74SChaoyong He uint32_t 156d108b9e9SChaoyong He nfp_cpp_serial(struct nfp_cpp *cpp, 157d108b9e9SChaoyong He const uint8_t **serial) 158c7e9729dSAlejandro Lucero { 159ff627b74SChaoyong He *serial = &cpp->serial[0]; 160ff627b74SChaoyong He 161ff627b74SChaoyong He return sizeof(cpp->serial); 162c7e9729dSAlejandro Lucero } 163c7e9729dSAlejandro Lucero 1646d03aa61SChaoyong He /** 1656d03aa61SChaoyong He * Set the private instance owned data of a nfp_cpp struct 1666d03aa61SChaoyong He * 1676d03aa61SChaoyong He * @param cpp 1686d03aa61SChaoyong He * NFP CPP operations structure 1696d03aa61SChaoyong He * @param serial 1706d03aa61SChaoyong He * NFP serial byte array 1716d03aa61SChaoyong He * @param serial_len 1726d03aa61SChaoyong He * Length of the serial byte array 1736d03aa61SChaoyong He */ 174ff627b74SChaoyong He void 175d108b9e9SChaoyong He nfp_cpp_serial_set(struct nfp_cpp *cpp, 176d108b9e9SChaoyong He const uint8_t *serial, 177c7e9729dSAlejandro Lucero size_t serial_len) 178c7e9729dSAlejandro Lucero { 179c7e9729dSAlejandro Lucero memcpy(cpp->serial, serial, serial_len); 180c7e9729dSAlejandro Lucero } 181c7e9729dSAlejandro Lucero 1826d03aa61SChaoyong He /** 1836d03aa61SChaoyong He * Retrieve the Interface ID of the NFP 1846d03aa61SChaoyong He * 1856d03aa61SChaoyong He * @param cpp 1866d03aa61SChaoyong He * NFP CPP handle 1876d03aa61SChaoyong He * 1886d03aa61SChaoyong He * @return 1896d03aa61SChaoyong He * NFP CPP Interface ID 1906d03aa61SChaoyong He */ 191c7e9729dSAlejandro Lucero uint16_t 192c7e9729dSAlejandro Lucero nfp_cpp_interface(struct nfp_cpp *cpp) 193c7e9729dSAlejandro Lucero { 194cbcbfd73SJames Hershaw if (cpp == NULL) 195c7e9729dSAlejandro Lucero return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0); 196c7e9729dSAlejandro Lucero 197c7e9729dSAlejandro Lucero return cpp->interface; 198c7e9729dSAlejandro Lucero } 199c7e9729dSAlejandro Lucero 2006d03aa61SChaoyong He /** 201ff627b74SChaoyong He * Retrieve the driver need lock flag 202ff627b74SChaoyong He * 203ff627b74SChaoyong He * @param cpp 204ff627b74SChaoyong He * NFP CPP handle 205ff627b74SChaoyong He * 206ff627b74SChaoyong He * @return 207ff627b74SChaoyong He * The driver need lock flag 208ff627b74SChaoyong He */ 209ff627b74SChaoyong He bool 210ff627b74SChaoyong He nfp_cpp_driver_need_lock(const struct nfp_cpp *cpp) 211ff627b74SChaoyong He { 212ff627b74SChaoyong He return cpp->driver_lock_needed; 213ff627b74SChaoyong He } 214ff627b74SChaoyong He 215ff627b74SChaoyong He /** 2166d03aa61SChaoyong He * Get the privately allocated portion of a NFP CPP area handle 2176d03aa61SChaoyong He * 2186d03aa61SChaoyong He * @param cpp_area 2196d03aa61SChaoyong He * NFP CPP area handle 2206d03aa61SChaoyong He * 2216d03aa61SChaoyong He * @return 2226d03aa61SChaoyong He * Pointer to the private area, or NULL on failure 2236d03aa61SChaoyong He */ 224c7e9729dSAlejandro Lucero void * 225c7e9729dSAlejandro Lucero nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area) 226c7e9729dSAlejandro Lucero { 227c7e9729dSAlejandro Lucero return &cpp_area[1]; 228c7e9729dSAlejandro Lucero } 229c7e9729dSAlejandro Lucero 2306d03aa61SChaoyong He /** 2316d03aa61SChaoyong He * Get the NFP CPP handle that is the pci_dev of a NFP CPP area handle 2326d03aa61SChaoyong He * 2336d03aa61SChaoyong He * @param cpp_area 2346d03aa61SChaoyong He * NFP CPP area handle 2356d03aa61SChaoyong He * 2366d03aa61SChaoyong He * @return 2376d03aa61SChaoyong He * NFP CPP handle 2386d03aa61SChaoyong He */ 239c7e9729dSAlejandro Lucero struct nfp_cpp * 240c7e9729dSAlejandro Lucero nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area) 241c7e9729dSAlejandro Lucero { 242c7e9729dSAlejandro Lucero return cpp_area->cpp; 243c7e9729dSAlejandro Lucero } 244c7e9729dSAlejandro Lucero 2456d03aa61SChaoyong He /** 2466d03aa61SChaoyong He * Get the name passed during allocation of the NFP CPP area handle 2476d03aa61SChaoyong He * 2486d03aa61SChaoyong He * @param cpp_area 2496d03aa61SChaoyong He * NFP CPP area handle 2506d03aa61SChaoyong He * 2516d03aa61SChaoyong He * @return 2526d03aa61SChaoyong He * Pointer to the area's name 2536d03aa61SChaoyong He */ 254c7e9729dSAlejandro Lucero const char * 255c7e9729dSAlejandro Lucero nfp_cpp_area_name(struct nfp_cpp_area *cpp_area) 256c7e9729dSAlejandro Lucero { 257c7e9729dSAlejandro Lucero return cpp_area->name; 258c7e9729dSAlejandro Lucero } 259c7e9729dSAlejandro Lucero 260925c27ecSChaoyong He #define NFP_IMB_TGTADDRESSMODECFG_MODE_of(_x) (((_x) >> 13) & 0x7) 261925c27ecSChaoyong He #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE RTE_BIT32(12) 262925c27ecSChaoyong He 263925c27ecSChaoyong He static int 264925c27ecSChaoyong He nfp_cpp_set_mu_locality_lsb(struct nfp_cpp *cpp) 265925c27ecSChaoyong He { 266925c27ecSChaoyong He int ret; 267925c27ecSChaoyong He int mode; 268925c27ecSChaoyong He int addr40; 269925c27ecSChaoyong He uint32_t imbcppat; 270925c27ecSChaoyong He 271925c27ecSChaoyong He imbcppat = cpp->imb_cat_table[NFP_CPP_TARGET_MU]; 272925c27ecSChaoyong He mode = NFP_IMB_TGTADDRESSMODECFG_MODE_of(imbcppat); 273925c27ecSChaoyong He addr40 = imbcppat & NFP_IMB_TGTADDRESSMODECFG_ADDRMODE; 274925c27ecSChaoyong He 275925c27ecSChaoyong He ret = nfp_cppat_mu_locality_lsb(mode, addr40); 276925c27ecSChaoyong He if (ret < 0) 277925c27ecSChaoyong He return ret; 278925c27ecSChaoyong He 279925c27ecSChaoyong He cpp->mu_locality_lsb = ret; 280925c27ecSChaoyong He 281925c27ecSChaoyong He return 0; 282925c27ecSChaoyong He } 283925c27ecSChaoyong He 284925c27ecSChaoyong He uint32_t 285925c27ecSChaoyong He nfp_cpp_mu_locality_lsb(struct nfp_cpp *cpp) 286925c27ecSChaoyong He { 287925c27ecSChaoyong He return cpp->mu_locality_lsb; 288925c27ecSChaoyong He } 289925c27ecSChaoyong He 2906d03aa61SChaoyong He /** 2916d03aa61SChaoyong He * Allocate and initialize a CPP area structure. 2926d03aa61SChaoyong He * The area must later be locked down with an 'acquire' before 2936d03aa61SChaoyong He * it can be safely accessed. 294c7e9729dSAlejandro Lucero * 2956d03aa61SChaoyong He * @param cpp 2966d03aa61SChaoyong He * CPP device handle 2976d03aa61SChaoyong He * @param dest 2986d03aa61SChaoyong He * CPP id 2996d03aa61SChaoyong He * @param name 3006d03aa61SChaoyong He * Name of region 3016d03aa61SChaoyong He * @param address 3026d03aa61SChaoyong He * Address of region 3036d03aa61SChaoyong He * @param size 3046d03aa61SChaoyong He * Size of region 3056d03aa61SChaoyong He * 3066d03aa61SChaoyong He * @return 3076d03aa61SChaoyong He * NFP CPP area handle, or NULL 308c7e9729dSAlejandro Lucero * 309c7e9729dSAlejandro Lucero * NOTE: @address and @size must be 32-bit aligned values. 310c7e9729dSAlejandro Lucero */ 311c7e9729dSAlejandro Lucero struct nfp_cpp_area * 312d108b9e9SChaoyong He nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, 313d108b9e9SChaoyong He uint32_t dest, 314d108b9e9SChaoyong He const char *name, 315c69debceSChaoyong He uint64_t address, 316c69debceSChaoyong He uint32_t size) 317c7e9729dSAlejandro Lucero { 318610bf14bSChaoyong He int err; 319ff627b74SChaoyong He size_t name_len; 320ff627b74SChaoyong He uint32_t target_id; 321ff627b74SChaoyong He uint64_t target_addr; 322c7e9729dSAlejandro Lucero struct nfp_cpp_area *area; 323c7e9729dSAlejandro Lucero 324cbcbfd73SJames Hershaw if (cpp == NULL) 325c7e9729dSAlejandro Lucero return NULL; 326c7e9729dSAlejandro Lucero 327c7e9729dSAlejandro Lucero /* Remap from cpp_island to cpp_target */ 328ff627b74SChaoyong He err = nfp_target_cpp(dest, address, &target_id, &target_addr, 329ff627b74SChaoyong He cpp->imb_cat_table); 330c7e9729dSAlejandro Lucero if (err < 0) 331c7e9729dSAlejandro Lucero return NULL; 332c7e9729dSAlejandro Lucero 333cbcbfd73SJames Hershaw if (name == NULL) 334ff627b74SChaoyong He name = "(reserved)"; 335c7e9729dSAlejandro Lucero 336ff627b74SChaoyong He name_len = strlen(name) + 1; 337ff627b74SChaoyong He area = calloc(1, sizeof(*area) + cpp->op->area_priv_size + name_len); 338cbcbfd73SJames Hershaw if (area == NULL) 339c7e9729dSAlejandro Lucero return NULL; 340c7e9729dSAlejandro Lucero 341c7e9729dSAlejandro Lucero area->cpp = cpp; 342c7e9729dSAlejandro Lucero area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size; 343ff627b74SChaoyong He memcpy(area->name, name, name_len); 344c7e9729dSAlejandro Lucero 345ff627b74SChaoyong He err = cpp->op->area_init(area, target_id, target_addr, size); 346c7e9729dSAlejandro Lucero if (err < 0) { 347*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Area init op failed."); 348c7e9729dSAlejandro Lucero free(area); 349c7e9729dSAlejandro Lucero return NULL; 350c7e9729dSAlejandro Lucero } 351c7e9729dSAlejandro Lucero 352ff627b74SChaoyong He area->offset = target_addr; 353c7e9729dSAlejandro Lucero area->size = size; 354c7e9729dSAlejandro Lucero 355c7e9729dSAlejandro Lucero return area; 356c7e9729dSAlejandro Lucero } 357c7e9729dSAlejandro Lucero 3586d03aa61SChaoyong He /** 3596d03aa61SChaoyong He * Allocate and initialize a CPP area structure. 3606d03aa61SChaoyong He * The area must later be locked down with an 'acquire' before 3616d03aa61SChaoyong He * it can be safely accessed. 3626d03aa61SChaoyong He * 3636d03aa61SChaoyong He * @param cpp 3646d03aa61SChaoyong He * CPP device handle 3656d03aa61SChaoyong He * @param dest 3666d03aa61SChaoyong He * CPP id 3676d03aa61SChaoyong He * @param address 3686d03aa61SChaoyong He * Address of region 3696d03aa61SChaoyong He * @param size 3706d03aa61SChaoyong He * Size of region 3716d03aa61SChaoyong He * 3726d03aa61SChaoyong He * @return 3736d03aa61SChaoyong He * NFP CPP area handle, or NULL 3746d03aa61SChaoyong He * 3756d03aa61SChaoyong He * NOTE: @address and @size must be 32-bit aligned values. 3766d03aa61SChaoyong He */ 377c7e9729dSAlejandro Lucero struct nfp_cpp_area * 378d108b9e9SChaoyong He nfp_cpp_area_alloc(struct nfp_cpp *cpp, 379d108b9e9SChaoyong He uint32_t dest, 380c69debceSChaoyong He uint64_t address, 381c69debceSChaoyong He size_t size) 382c7e9729dSAlejandro Lucero { 383c7e9729dSAlejandro Lucero return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size); 384c7e9729dSAlejandro Lucero } 385c7e9729dSAlejandro Lucero 3866d03aa61SChaoyong He /** 3877be78d02SJosh Soref * Allocate and initialize a CPP area structure, and lock it down so 388c7e9729dSAlejandro Lucero * that it can be accessed directly. 389c7e9729dSAlejandro Lucero * 3906d03aa61SChaoyong He * @param cpp 3916d03aa61SChaoyong He * CPP device handle 3926d03aa61SChaoyong He * @param destination 3936d03aa61SChaoyong He * CPP id 3946d03aa61SChaoyong He * @param address 3956d03aa61SChaoyong He * Address of region 3966d03aa61SChaoyong He * @param size 3976d03aa61SChaoyong He * Size of region 3986d03aa61SChaoyong He * 3996d03aa61SChaoyong He * @return 4006d03aa61SChaoyong He * NFP CPP area handle, or NULL 4016d03aa61SChaoyong He * 402c7e9729dSAlejandro Lucero * NOTE: @address and @size must be 32-bit aligned values. 403c7e9729dSAlejandro Lucero * 404c7e9729dSAlejandro Lucero * NOTE: The area must also be 'released' when the structure is freed. 405c7e9729dSAlejandro Lucero */ 406c7e9729dSAlejandro Lucero struct nfp_cpp_area * 407d108b9e9SChaoyong He nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, 408d108b9e9SChaoyong He uint32_t destination, 409c69debceSChaoyong He uint64_t address, 410c69debceSChaoyong He size_t size) 411c7e9729dSAlejandro Lucero { 412c7e9729dSAlejandro Lucero struct nfp_cpp_area *area; 413c7e9729dSAlejandro Lucero 414c7e9729dSAlejandro Lucero area = nfp_cpp_area_alloc(cpp, destination, address, size); 415efa766e1SChaoyong He if (area == NULL) { 416*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed to allocate CPP area."); 417c7e9729dSAlejandro Lucero return NULL; 418efa766e1SChaoyong He } 419c7e9729dSAlejandro Lucero 4204aa75cadSChaoyong He if (nfp_cpp_area_acquire(area) != 0) { 421*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed to acquire CPP area."); 422c7e9729dSAlejandro Lucero nfp_cpp_area_free(area); 423c7e9729dSAlejandro Lucero return NULL; 424c7e9729dSAlejandro Lucero } 425c7e9729dSAlejandro Lucero 426c7e9729dSAlejandro Lucero return area; 427c7e9729dSAlejandro Lucero } 428c7e9729dSAlejandro Lucero 4296d03aa61SChaoyong He /** 430c7e9729dSAlejandro Lucero * Frees up memory resources held by the CPP area. 4316d03aa61SChaoyong He * 4326d03aa61SChaoyong He * @param area 4336d03aa61SChaoyong He * CPP area handle 434c7e9729dSAlejandro Lucero */ 435c7e9729dSAlejandro Lucero void 436c7e9729dSAlejandro Lucero nfp_cpp_area_free(struct nfp_cpp_area *area) 437c7e9729dSAlejandro Lucero { 4384aa75cadSChaoyong He if (area->cpp->op->area_cleanup != NULL) 439c7e9729dSAlejandro Lucero area->cpp->op->area_cleanup(area); 440c7e9729dSAlejandro Lucero free(area); 441c7e9729dSAlejandro Lucero } 442c7e9729dSAlejandro Lucero 4436d03aa61SChaoyong He /** 4446d03aa61SChaoyong He * Releases CPP area and frees up memory resources held by it. 445c7e9729dSAlejandro Lucero * 4466d03aa61SChaoyong He * @param area 4476d03aa61SChaoyong He * CPP area handle 448c7e9729dSAlejandro Lucero */ 449c7e9729dSAlejandro Lucero void 450c7e9729dSAlejandro Lucero nfp_cpp_area_release_free(struct nfp_cpp_area *area) 451c7e9729dSAlejandro Lucero { 452c7e9729dSAlejandro Lucero nfp_cpp_area_release(area); 453c7e9729dSAlejandro Lucero nfp_cpp_area_free(area); 454c7e9729dSAlejandro Lucero } 455c7e9729dSAlejandro Lucero 4566d03aa61SChaoyong He /** 4576d03aa61SChaoyong He * Locks down the CPP area for a potential long term activity. 4586d03aa61SChaoyong He * Area must always be locked down before being accessed. 459c7e9729dSAlejandro Lucero * 4606d03aa61SChaoyong He * @param area 4616d03aa61SChaoyong He * CPP area handle 4626d03aa61SChaoyong He * 4636d03aa61SChaoyong He * @return 4646d03aa61SChaoyong He * 0 on success, -1 on failure. 465c7e9729dSAlejandro Lucero */ 466c7e9729dSAlejandro Lucero int 467c7e9729dSAlejandro Lucero nfp_cpp_area_acquire(struct nfp_cpp_area *area) 468c7e9729dSAlejandro Lucero { 4694aa75cadSChaoyong He if (area->cpp->op->area_acquire != NULL) { 470c7e9729dSAlejandro Lucero int err = area->cpp->op->area_acquire(area); 471efa766e1SChaoyong He if (err < 0) { 472*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Area acquire op failed."); 473c7e9729dSAlejandro Lucero return -1; 474c7e9729dSAlejandro Lucero } 475efa766e1SChaoyong He } 476c7e9729dSAlejandro Lucero 477c7e9729dSAlejandro Lucero return 0; 478c7e9729dSAlejandro Lucero } 479c7e9729dSAlejandro Lucero 4806d03aa61SChaoyong He /** 481c7e9729dSAlejandro Lucero * Releases a previously locked down CPP area. 4826d03aa61SChaoyong He * 4836d03aa61SChaoyong He * @param area 4846d03aa61SChaoyong He * CPP area handle 485c7e9729dSAlejandro Lucero */ 486c7e9729dSAlejandro Lucero void 487c7e9729dSAlejandro Lucero nfp_cpp_area_release(struct nfp_cpp_area *area) 488c7e9729dSAlejandro Lucero { 4894aa75cadSChaoyong He if (area->cpp->op->area_release != NULL) 490c7e9729dSAlejandro Lucero area->cpp->op->area_release(area); 491c7e9729dSAlejandro Lucero } 492c7e9729dSAlejandro Lucero 4936d03aa61SChaoyong He /** 494c7e9729dSAlejandro Lucero * Returns an iomem pointer for use with readl()/writel() style operations. 495c7e9729dSAlejandro Lucero * 4966d03aa61SChaoyong He * @param area 4976d03aa61SChaoyong He * CPP area handle 498c7e9729dSAlejandro Lucero * 4996d03aa61SChaoyong He * @return 5006d03aa61SChaoyong He * Pointer to the area, or NULL 5016d03aa61SChaoyong He * 5026d03aa61SChaoyong He * NOTE: Area must have been locked down with an 'acquire'. 503c7e9729dSAlejandro Lucero */ 504c7e9729dSAlejandro Lucero void * 505c7e9729dSAlejandro Lucero nfp_cpp_area_iomem(struct nfp_cpp_area *area) 506c7e9729dSAlejandro Lucero { 507c7e9729dSAlejandro Lucero void *iomem = NULL; 508c7e9729dSAlejandro Lucero 5094aa75cadSChaoyong He if (area->cpp->op->area_iomem != NULL) 510c7e9729dSAlejandro Lucero iomem = area->cpp->op->area_iomem(area); 511c7e9729dSAlejandro Lucero 512c7e9729dSAlejandro Lucero return iomem; 513c7e9729dSAlejandro Lucero } 514c7e9729dSAlejandro Lucero 5156d03aa61SChaoyong He /** 516c7e9729dSAlejandro Lucero * Read data from indicated CPP region. 517c7e9729dSAlejandro Lucero * 5186d03aa61SChaoyong He * @param area 5196d03aa61SChaoyong He * CPP area handle 5206d03aa61SChaoyong He * @param offset 5216d03aa61SChaoyong He * Offset into CPP area 522588c5b10SChaoyong He * @param address 5236d03aa61SChaoyong He * Address to put data into 5246d03aa61SChaoyong He * @param length 5256d03aa61SChaoyong He * Number of bytes to read 526c7e9729dSAlejandro Lucero * 5276d03aa61SChaoyong He * @return 5286d03aa61SChaoyong He * Length of io, or -ERRNO 5296d03aa61SChaoyong He * 5306d03aa61SChaoyong He * NOTE: @offset and @length must be 32-bit aligned values. 531c7e9729dSAlejandro Lucero * NOTE: Area must have been locked down with an 'acquire'. 532c7e9729dSAlejandro Lucero */ 533c7e9729dSAlejandro Lucero int 534d108b9e9SChaoyong He nfp_cpp_area_read(struct nfp_cpp_area *area, 535c69debceSChaoyong He uint32_t offset, 536588c5b10SChaoyong He void *address, 537d108b9e9SChaoyong He size_t length) 538c7e9729dSAlejandro Lucero { 539c7e9729dSAlejandro Lucero if ((offset + length) > area->size) 540b29d5df4SChaoyong He return -EFAULT; 541c7e9729dSAlejandro Lucero 542588c5b10SChaoyong He return area->cpp->op->area_read(area, address, offset, length); 543c7e9729dSAlejandro Lucero } 544c7e9729dSAlejandro Lucero 5456d03aa61SChaoyong He /** 546c7e9729dSAlejandro Lucero * Write data to indicated CPP region. 547c7e9729dSAlejandro Lucero * 5486d03aa61SChaoyong He * @param area 5496d03aa61SChaoyong He * CPP area handle 5506d03aa61SChaoyong He * @param offset 5516d03aa61SChaoyong He * Offset into CPP area 552588c5b10SChaoyong He * @param address 5536d03aa61SChaoyong He * Address to put data into 5546d03aa61SChaoyong He * @param length 5556d03aa61SChaoyong He * Number of bytes to read 556c7e9729dSAlejandro Lucero * 5576d03aa61SChaoyong He * @return 5586d03aa61SChaoyong He * Length of io, or -ERRNO 5596d03aa61SChaoyong He * 5606d03aa61SChaoyong He * NOTE: @offset and @length must be 32-bit aligned values. 561c7e9729dSAlejandro Lucero * NOTE: Area must have been locked down with an 'acquire'. 562c7e9729dSAlejandro Lucero */ 563c7e9729dSAlejandro Lucero int 564d108b9e9SChaoyong He nfp_cpp_area_write(struct nfp_cpp_area *area, 565c69debceSChaoyong He uint32_t offset, 566588c5b10SChaoyong He const void *address, 567d108b9e9SChaoyong He size_t length) 568c7e9729dSAlejandro Lucero { 569c7e9729dSAlejandro Lucero if ((offset + length) > area->size) 570b29d5df4SChaoyong He return -EFAULT; 571c7e9729dSAlejandro Lucero 572588c5b10SChaoyong He return area->cpp->op->area_write(area, address, offset, length); 573c7e9729dSAlejandro Lucero } 574c7e9729dSAlejandro Lucero 575c7e9729dSAlejandro Lucero /* 576c7e9729dSAlejandro Lucero * Return the correct CPP address, and fixup xpb_addr as needed, 577c7e9729dSAlejandro Lucero * based upon NFP model. 578c7e9729dSAlejandro Lucero */ 579c7e9729dSAlejandro Lucero static uint32_t 580d108b9e9SChaoyong He nfp_xpb_to_cpp(struct nfp_cpp *cpp, 581d108b9e9SChaoyong He uint32_t *xpb_addr) 582c7e9729dSAlejandro Lucero { 583c7e9729dSAlejandro Lucero int island; 584610bf14bSChaoyong He uint32_t xpb; 585c7e9729dSAlejandro Lucero 586c7e9729dSAlejandro Lucero xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0); 587c7e9729dSAlejandro Lucero 588c7e9729dSAlejandro Lucero /* 589c7e9729dSAlejandro Lucero * Ensure that non-local XPB accesses go out through the 590c7e9729dSAlejandro Lucero * global XPBM bus. 591c7e9729dSAlejandro Lucero */ 592ff627b74SChaoyong He island = (*xpb_addr >> 24) & 0x3f; 593c7e9729dSAlejandro Lucero 594cbcbfd73SJames Hershaw if (island == 0) 595c7e9729dSAlejandro Lucero return xpb; 596c7e9729dSAlejandro Lucero 597ff627b74SChaoyong He if (island != 1) { 598ff627b74SChaoyong He *xpb_addr |= (1 << 30); 599ff627b74SChaoyong He return xpb; 600ff627b74SChaoyong He } 601ff627b74SChaoyong He 602c7e9729dSAlejandro Lucero /* 603c7e9729dSAlejandro Lucero * Accesses to the ARM Island overlay uses Island 0 604c7e9729dSAlejandro Lucero * Global Bit 605c7e9729dSAlejandro Lucero */ 606ff627b74SChaoyong He *xpb_addr &= ~0x7f000000; 607ff627b74SChaoyong He if (*xpb_addr < 0x60000) { 608c7e9729dSAlejandro Lucero *xpb_addr |= (1 << 30); 609ff627b74SChaoyong He } else { 610c7e9729dSAlejandro Lucero /* And only non-ARM interfaces use island id = 1 */ 611c7e9729dSAlejandro Lucero if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) != 612c7e9729dSAlejandro Lucero NFP_CPP_INTERFACE_TYPE_ARM) 613c7e9729dSAlejandro Lucero *xpb_addr |= (1 << 24); 614c7e9729dSAlejandro Lucero } 615c7e9729dSAlejandro Lucero 616c7e9729dSAlejandro Lucero return xpb; 617c7e9729dSAlejandro Lucero } 618c7e9729dSAlejandro Lucero 6196d03aa61SChaoyong He /** 6206d03aa61SChaoyong He * Read a uint32_t value from an area 6216d03aa61SChaoyong He * 6226d03aa61SChaoyong He * @param area 6236d03aa61SChaoyong He * CPP Area handle 6246d03aa61SChaoyong He * @param offset 6256d03aa61SChaoyong He * Offset into area 6266d03aa61SChaoyong He * @param value 6276d03aa61SChaoyong He * Pointer to read buffer 6286d03aa61SChaoyong He * 6296d03aa61SChaoyong He * @return 6306d03aa61SChaoyong He * 0 on success, or -ERRNO 6316d03aa61SChaoyong He */ 632c7e9729dSAlejandro Lucero int 633d108b9e9SChaoyong He nfp_cpp_area_readl(struct nfp_cpp_area *area, 634c69debceSChaoyong He uint32_t offset, 635c7e9729dSAlejandro Lucero uint32_t *value) 636c7e9729dSAlejandro Lucero { 637c7e9729dSAlejandro Lucero int sz; 638c7e9729dSAlejandro Lucero uint32_t tmp = 0; 639c7e9729dSAlejandro Lucero 640c7e9729dSAlejandro Lucero sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp)); 641ff627b74SChaoyong He if (sz != sizeof(tmp)) 642ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 643ff627b74SChaoyong He 644c7e9729dSAlejandro Lucero *value = rte_le_to_cpu_32(tmp); 645c7e9729dSAlejandro Lucero 646ff627b74SChaoyong He return 0; 647c7e9729dSAlejandro Lucero } 648c7e9729dSAlejandro Lucero 6496d03aa61SChaoyong He /** 6506d03aa61SChaoyong He * Write a uint32_t vale to an area 6516d03aa61SChaoyong He * 6526d03aa61SChaoyong He * @param area 6536d03aa61SChaoyong He * CPP Area handle 6546d03aa61SChaoyong He * @param offset 6556d03aa61SChaoyong He * Offset into area 6566d03aa61SChaoyong He * @param value 6576d03aa61SChaoyong He * Value to write 6586d03aa61SChaoyong He * 6596d03aa61SChaoyong He * @return 6606d03aa61SChaoyong He * 0 on success, or -ERRNO 6616d03aa61SChaoyong He */ 662c7e9729dSAlejandro Lucero int 663d108b9e9SChaoyong He nfp_cpp_area_writel(struct nfp_cpp_area *area, 664c69debceSChaoyong He uint32_t offset, 665c7e9729dSAlejandro Lucero uint32_t value) 666c7e9729dSAlejandro Lucero { 667c7e9729dSAlejandro Lucero int sz; 668c7e9729dSAlejandro Lucero 669c7e9729dSAlejandro Lucero value = rte_cpu_to_le_32(value); 670c7e9729dSAlejandro Lucero sz = nfp_cpp_area_write(area, offset, &value, sizeof(value)); 671ff627b74SChaoyong He if (sz != sizeof(value)) 672ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 673ff627b74SChaoyong He 674ff627b74SChaoyong He return 0; 675c7e9729dSAlejandro Lucero } 676c7e9729dSAlejandro Lucero 6776d03aa61SChaoyong He /** 6786d03aa61SChaoyong He * Read a uint64_t value from an area 6796d03aa61SChaoyong He * 6806d03aa61SChaoyong He * @param area 6816d03aa61SChaoyong He * CPP Area handle 6826d03aa61SChaoyong He * @param offset 6836d03aa61SChaoyong He * Offset into area 6846d03aa61SChaoyong He * @param value 6856d03aa61SChaoyong He * Pointer to read buffer 6866d03aa61SChaoyong He * 6876d03aa61SChaoyong He * @return 6886d03aa61SChaoyong He * 0 on success, or -ERRNO 6896d03aa61SChaoyong He */ 690c7e9729dSAlejandro Lucero int 691d108b9e9SChaoyong He nfp_cpp_area_readq(struct nfp_cpp_area *area, 692c69debceSChaoyong He uint32_t offset, 693c7e9729dSAlejandro Lucero uint64_t *value) 694c7e9729dSAlejandro Lucero { 695c7e9729dSAlejandro Lucero int sz; 696c7e9729dSAlejandro Lucero uint64_t tmp = 0; 697c7e9729dSAlejandro Lucero 698c7e9729dSAlejandro Lucero sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp)); 699ff627b74SChaoyong He if (sz != sizeof(tmp)) 700ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 701ff627b74SChaoyong He 702c7e9729dSAlejandro Lucero *value = rte_le_to_cpu_64(tmp); 703c7e9729dSAlejandro Lucero 704ff627b74SChaoyong He return 0; 705c7e9729dSAlejandro Lucero } 706c7e9729dSAlejandro Lucero 7076d03aa61SChaoyong He /** 7086d03aa61SChaoyong He * Write a uint64_t vale to an area 7096d03aa61SChaoyong He * 7106d03aa61SChaoyong He * @param area 7116d03aa61SChaoyong He * CPP Area handle 7126d03aa61SChaoyong He * @param offset 7136d03aa61SChaoyong He * Offset into area 7146d03aa61SChaoyong He * @param value 7156d03aa61SChaoyong He * Value to write 7166d03aa61SChaoyong He * 7176d03aa61SChaoyong He * @return 7186d03aa61SChaoyong He * 0 on success, or -ERRNO 7196d03aa61SChaoyong He */ 720c7e9729dSAlejandro Lucero int 721d108b9e9SChaoyong He nfp_cpp_area_writeq(struct nfp_cpp_area *area, 722c69debceSChaoyong He uint32_t offset, 723c7e9729dSAlejandro Lucero uint64_t value) 724c7e9729dSAlejandro Lucero { 725c7e9729dSAlejandro Lucero int sz; 726c7e9729dSAlejandro Lucero 727c7e9729dSAlejandro Lucero value = rte_cpu_to_le_64(value); 728c7e9729dSAlejandro Lucero sz = nfp_cpp_area_write(area, offset, &value, sizeof(value)); 729ff627b74SChaoyong He if (sz != sizeof(value)) 730ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 731c7e9729dSAlejandro Lucero 732ff627b74SChaoyong He return 0; 733c7e9729dSAlejandro Lucero } 734c7e9729dSAlejandro Lucero 7356d03aa61SChaoyong He /** 7366d03aa61SChaoyong He * Read a uint32_t value from a CPP location 7376d03aa61SChaoyong He * 7386d03aa61SChaoyong He * @param cpp 7396d03aa61SChaoyong He * CPP device handle 7406d03aa61SChaoyong He * @param cpp_id 7416d03aa61SChaoyong He * CPP ID for operation 7426d03aa61SChaoyong He * @param address 7436d03aa61SChaoyong He * Address for operation 7446d03aa61SChaoyong He * @param value 7456d03aa61SChaoyong He * Pointer to read buffer 7466d03aa61SChaoyong He * 7476d03aa61SChaoyong He * @return 7486d03aa61SChaoyong He * 0 on success, or -ERRNO 7496d03aa61SChaoyong He */ 750c7e9729dSAlejandro Lucero int 751d108b9e9SChaoyong He nfp_cpp_readl(struct nfp_cpp *cpp, 752d108b9e9SChaoyong He uint32_t cpp_id, 753c69debceSChaoyong He uint64_t address, 754c7e9729dSAlejandro Lucero uint32_t *value) 755c7e9729dSAlejandro Lucero { 756c7e9729dSAlejandro Lucero int sz; 757c7e9729dSAlejandro Lucero uint32_t tmp; 758c7e9729dSAlejandro Lucero 759c7e9729dSAlejandro Lucero sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp)); 760ff627b74SChaoyong He if (sz != sizeof(tmp)) 761ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 762ff627b74SChaoyong He 763c7e9729dSAlejandro Lucero *value = rte_le_to_cpu_32(tmp); 764c7e9729dSAlejandro Lucero 765ff627b74SChaoyong He return 0; 766c7e9729dSAlejandro Lucero } 767c7e9729dSAlejandro Lucero 7686d03aa61SChaoyong He /** 7696d03aa61SChaoyong He * Write a uint32_t value to a CPP location 7706d03aa61SChaoyong He * 7716d03aa61SChaoyong He * @param cpp 7726d03aa61SChaoyong He * CPP device handle 7736d03aa61SChaoyong He * @param cpp_id 7746d03aa61SChaoyong He * CPP ID for operation 7756d03aa61SChaoyong He * @param address 7766d03aa61SChaoyong He * Address for operation 7776d03aa61SChaoyong He * @param value 7786d03aa61SChaoyong He * Value to write 7796d03aa61SChaoyong He * 7806d03aa61SChaoyong He * @return 7816d03aa61SChaoyong He * 0 on success, or -ERRNO 7826d03aa61SChaoyong He */ 783c7e9729dSAlejandro Lucero int 784d108b9e9SChaoyong He nfp_cpp_writel(struct nfp_cpp *cpp, 785d108b9e9SChaoyong He uint32_t cpp_id, 786c69debceSChaoyong He uint64_t address, 787c7e9729dSAlejandro Lucero uint32_t value) 788c7e9729dSAlejandro Lucero { 789c7e9729dSAlejandro Lucero int sz; 790c7e9729dSAlejandro Lucero 791c7e9729dSAlejandro Lucero value = rte_cpu_to_le_32(value); 792c7e9729dSAlejandro Lucero sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value)); 793ff627b74SChaoyong He if (sz != sizeof(value)) 794ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 795c7e9729dSAlejandro Lucero 796ff627b74SChaoyong He return 0; 797c7e9729dSAlejandro Lucero } 798c7e9729dSAlejandro Lucero 7996d03aa61SChaoyong He /** 8006d03aa61SChaoyong He * Read a uint64_t value from a CPP location 8016d03aa61SChaoyong He * 8026d03aa61SChaoyong He * @param cpp 8036d03aa61SChaoyong He * CPP device handle 8046d03aa61SChaoyong He * @param cpp_id 8056d03aa61SChaoyong He * CPP ID for operation 8066d03aa61SChaoyong He * @param address 8076d03aa61SChaoyong He * Address for operation 8086d03aa61SChaoyong He * @param value 8096d03aa61SChaoyong He * Pointer to read buffer 8106d03aa61SChaoyong He * 8116d03aa61SChaoyong He * @return 8126d03aa61SChaoyong He * 0 on success, or -ERRNO 8136d03aa61SChaoyong He */ 814c7e9729dSAlejandro Lucero int 815d108b9e9SChaoyong He nfp_cpp_readq(struct nfp_cpp *cpp, 816d108b9e9SChaoyong He uint32_t cpp_id, 817c69debceSChaoyong He uint64_t address, 818c7e9729dSAlejandro Lucero uint64_t *value) 819c7e9729dSAlejandro Lucero { 820c7e9729dSAlejandro Lucero int sz; 821c7e9729dSAlejandro Lucero uint64_t tmp; 822c7e9729dSAlejandro Lucero 823c7e9729dSAlejandro Lucero sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp)); 824c7e9729dSAlejandro Lucero *value = rte_le_to_cpu_64(tmp); 825ff627b74SChaoyong He if (sz != sizeof(tmp)) 826ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 827c7e9729dSAlejandro Lucero 828ff627b74SChaoyong He return 0; 829c7e9729dSAlejandro Lucero } 830c7e9729dSAlejandro Lucero 8316d03aa61SChaoyong He /** 8326d03aa61SChaoyong He * Write a uint64_t value to a CPP location 8336d03aa61SChaoyong He * 8346d03aa61SChaoyong He * @param cpp 8356d03aa61SChaoyong He * CPP device handle 8366d03aa61SChaoyong He * @param cpp_id 8376d03aa61SChaoyong He * CPP ID for operation 8386d03aa61SChaoyong He * @param address 8396d03aa61SChaoyong He * Address for operation 8406d03aa61SChaoyong He * @param value 8416d03aa61SChaoyong He * Value to write 8426d03aa61SChaoyong He * 8436d03aa61SChaoyong He * @return 8446d03aa61SChaoyong He * 0 on success, or -ERRNO 8456d03aa61SChaoyong He */ 846c7e9729dSAlejandro Lucero int 847d108b9e9SChaoyong He nfp_cpp_writeq(struct nfp_cpp *cpp, 848d108b9e9SChaoyong He uint32_t cpp_id, 849c69debceSChaoyong He uint64_t address, 850c7e9729dSAlejandro Lucero uint64_t value) 851c7e9729dSAlejandro Lucero { 852c7e9729dSAlejandro Lucero int sz; 853c7e9729dSAlejandro Lucero 854c7e9729dSAlejandro Lucero value = rte_cpu_to_le_64(value); 855c7e9729dSAlejandro Lucero sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value)); 856ff627b74SChaoyong He if (sz != sizeof(value)) 857ff627b74SChaoyong He return sz < 0 ? sz : -EIO; 858c7e9729dSAlejandro Lucero 859ff627b74SChaoyong He return 0; 860c7e9729dSAlejandro Lucero } 861c7e9729dSAlejandro Lucero 8626d03aa61SChaoyong He /** 8636d03aa61SChaoyong He * Write a uint32_t word to a XPB location 8646d03aa61SChaoyong He * 8656d03aa61SChaoyong He * @param cpp 8666d03aa61SChaoyong He * CPP device handle 8676d03aa61SChaoyong He * @param xpb_addr 8686d03aa61SChaoyong He * XPB target and address 8696d03aa61SChaoyong He * @param value 8706d03aa61SChaoyong He * Value to write 8716d03aa61SChaoyong He * 8726d03aa61SChaoyong He * @return 8736d03aa61SChaoyong He * 0 on success, or -ERRNO 8746d03aa61SChaoyong He */ 875c7e9729dSAlejandro Lucero int 876d108b9e9SChaoyong He nfp_xpb_writel(struct nfp_cpp *cpp, 877d108b9e9SChaoyong He uint32_t xpb_addr, 878d108b9e9SChaoyong He uint32_t value) 879c7e9729dSAlejandro Lucero { 880c7e9729dSAlejandro Lucero uint32_t cpp_dest; 881c7e9729dSAlejandro Lucero 882c7e9729dSAlejandro Lucero cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr); 883c7e9729dSAlejandro Lucero 884c7e9729dSAlejandro Lucero return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value); 885c7e9729dSAlejandro Lucero } 886c7e9729dSAlejandro Lucero 8876d03aa61SChaoyong He /** 8886d03aa61SChaoyong He * Read a uint32_t value from a XPB location 8896d03aa61SChaoyong He * 8906d03aa61SChaoyong He * @param cpp 8916d03aa61SChaoyong He * CPP device handle 8926d03aa61SChaoyong He * @param xpb_addr 8936d03aa61SChaoyong He * XPB target and address 8946d03aa61SChaoyong He * @param value 8956d03aa61SChaoyong He * Pointer to read buffer 8966d03aa61SChaoyong He * 8976d03aa61SChaoyong He * @return 8986d03aa61SChaoyong He * 0 on success, or -ERRNO 8996d03aa61SChaoyong He */ 900c7e9729dSAlejandro Lucero int 901d108b9e9SChaoyong He nfp_xpb_readl(struct nfp_cpp *cpp, 902d108b9e9SChaoyong He uint32_t xpb_addr, 903d108b9e9SChaoyong He uint32_t *value) 904c7e9729dSAlejandro Lucero { 905c7e9729dSAlejandro Lucero uint32_t cpp_dest; 906c7e9729dSAlejandro Lucero 907c7e9729dSAlejandro Lucero cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr); 908c7e9729dSAlejandro Lucero 909c7e9729dSAlejandro Lucero return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value); 910c7e9729dSAlejandro Lucero } 911c7e9729dSAlejandro Lucero 912c7e9729dSAlejandro Lucero static struct nfp_cpp * 913796f1aecSChaoyong He nfp_cpp_alloc(struct rte_pci_device *pci_dev, 914796f1aecSChaoyong He void *priv, 915796f1aecSChaoyong He bool driver_lock_needed) 916c7e9729dSAlejandro Lucero { 917c7e9729dSAlejandro Lucero int err; 918796f1aecSChaoyong He size_t target; 919796f1aecSChaoyong He uint32_t xpb_addr; 920610bf14bSChaoyong He struct nfp_cpp *cpp; 921610bf14bSChaoyong He const struct nfp_cpp_operations *ops; 922c7e9729dSAlejandro Lucero 923c7e9729dSAlejandro Lucero ops = nfp_cpp_transport_operations(); 924cbcbfd73SJames Hershaw if (ops == NULL || ops->init == NULL) 925b29d5df4SChaoyong He return NULL; 926c7e9729dSAlejandro Lucero 927c7e9729dSAlejandro Lucero cpp = calloc(1, sizeof(*cpp)); 928cbcbfd73SJames Hershaw if (cpp == NULL) 929c7e9729dSAlejandro Lucero return NULL; 930c7e9729dSAlejandro Lucero 931c7e9729dSAlejandro Lucero cpp->op = ops; 932796f1aecSChaoyong He cpp->priv = priv; 9335f6ed2f4SAlejandro Lucero cpp->driver_lock_needed = driver_lock_needed; 934c7e9729dSAlejandro Lucero 935796f1aecSChaoyong He err = ops->get_interface(pci_dev, &cpp->interface); 936796f1aecSChaoyong He if (err != 0) { 937c7e9729dSAlejandro Lucero free(cpp); 938c7e9729dSAlejandro Lucero return NULL; 939c7e9729dSAlejandro Lucero } 940796f1aecSChaoyong He 941796f1aecSChaoyong He err = ops->get_serial(pci_dev, cpp->serial, NFP_SERIAL_LEN); 942796f1aecSChaoyong He if (err != 0) { 943796f1aecSChaoyong He free(cpp); 944796f1aecSChaoyong He return NULL; 945c7e9729dSAlejandro Lucero } 946c7e9729dSAlejandro Lucero 947796f1aecSChaoyong He /* 948796f1aecSChaoyong He * NOTE: cpp_lock is NOT locked for op->init, 949796f1aecSChaoyong He * since it may call NFP CPP API operations 950796f1aecSChaoyong He */ 9511fbe51cdSChaoyong He err = cpp->op->init(cpp); 952796f1aecSChaoyong He if (err < 0) { 953*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP interface initialization failed."); 954796f1aecSChaoyong He free(cpp); 955796f1aecSChaoyong He return NULL; 956796f1aecSChaoyong He } 957796f1aecSChaoyong He 958796f1aecSChaoyong He err = nfp_cpp_model_autodetect(cpp, &cpp->model); 959796f1aecSChaoyong He if (err < 0) { 960*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP model detection failed."); 961796f1aecSChaoyong He free(cpp); 962796f1aecSChaoyong He return NULL; 963796f1aecSChaoyong He } 964c7e9729dSAlejandro Lucero 965588c5b10SChaoyong He for (target = 0; target < RTE_DIM(cpp->imb_cat_table); target++) { 966c7e9729dSAlejandro Lucero /* Hardcoded XPB IMB Base, island 0 */ 967588c5b10SChaoyong He xpb_addr = 0x000a0000 + (target * 4); 968796f1aecSChaoyong He err = nfp_xpb_readl(cpp, xpb_addr, &cpp->imb_cat_table[target]); 969c7e9729dSAlejandro Lucero if (err < 0) { 970*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Can not read CPP mapping from device."); 971c7e9729dSAlejandro Lucero free(cpp); 972c7e9729dSAlejandro Lucero return NULL; 973c7e9729dSAlejandro Lucero } 974c7e9729dSAlejandro Lucero } 975c7e9729dSAlejandro Lucero 976925c27ecSChaoyong He err = nfp_cpp_set_mu_locality_lsb(cpp); 977925c27ecSChaoyong He if (err < 0) { 978*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Can not calculate MU locality bit offset."); 979925c27ecSChaoyong He free(cpp); 980925c27ecSChaoyong He return NULL; 981925c27ecSChaoyong He } 982925c27ecSChaoyong He 983c7e9729dSAlejandro Lucero return cpp; 984c7e9729dSAlejandro Lucero } 985c7e9729dSAlejandro Lucero 9866d03aa61SChaoyong He /** 9876d03aa61SChaoyong He * Free the CPP handle 9886d03aa61SChaoyong He * 9896d03aa61SChaoyong He * @param cpp 9906d03aa61SChaoyong He * CPP handle 991c7e9729dSAlejandro Lucero */ 992c7e9729dSAlejandro Lucero void 993c7e9729dSAlejandro Lucero nfp_cpp_free(struct nfp_cpp *cpp) 994c7e9729dSAlejandro Lucero { 9954aa75cadSChaoyong He if (cpp->op != NULL && cpp->op->free != NULL) 996c7e9729dSAlejandro Lucero cpp->op->free(cpp); 997c7e9729dSAlejandro Lucero 998c7e9729dSAlejandro Lucero free(cpp); 999c7e9729dSAlejandro Lucero } 1000c7e9729dSAlejandro Lucero 10016d03aa61SChaoyong He /** 10026d03aa61SChaoyong He * Create a NFP CPP handle from device 10036d03aa61SChaoyong He * 10046d03aa61SChaoyong He * @param dev 10056d03aa61SChaoyong He * PCI device 1006796f1aecSChaoyong He * @param priv 1007796f1aecSChaoyong He * Private data of low-level implementation 10086d03aa61SChaoyong He * @param driver_lock_needed 10096d03aa61SChaoyong He * Driver lock flag 10106d03aa61SChaoyong He * 10116d03aa61SChaoyong He * @return 10126d03aa61SChaoyong He * NFP CPP handle on success, NULL on failure 10136d03aa61SChaoyong He * 10146d03aa61SChaoyong He * NOTE: On failure, cpp_ops->free will be called! 10156d03aa61SChaoyong He */ 1016c7e9729dSAlejandro Lucero struct nfp_cpp * 1017d108b9e9SChaoyong He nfp_cpp_from_device_name(struct rte_pci_device *dev, 1018796f1aecSChaoyong He void *priv, 1019796f1aecSChaoyong He bool driver_lock_needed) 1020c7e9729dSAlejandro Lucero { 1021796f1aecSChaoyong He return nfp_cpp_alloc(dev, priv, driver_lock_needed); 1022c7e9729dSAlejandro Lucero } 1023c7e9729dSAlejandro Lucero 10246d03aa61SChaoyong He /** 10256d03aa61SChaoyong He * Read from CPP target 10266d03aa61SChaoyong He * 10276d03aa61SChaoyong He * @param cpp 10286d03aa61SChaoyong He * CPP handle 10296d03aa61SChaoyong He * @param destination 10306d03aa61SChaoyong He * CPP id 1031588c5b10SChaoyong He * @param offset 10326d03aa61SChaoyong He * Offset into CPP target 1033588c5b10SChaoyong He * @param address 10346d03aa61SChaoyong He * Buffer for result 10356d03aa61SChaoyong He * @param length 10366d03aa61SChaoyong He * Number of bytes to read 10376d03aa61SChaoyong He * 10386d03aa61SChaoyong He * @return 10396d03aa61SChaoyong He * Length of io, or -ERRNO 1040c7e9729dSAlejandro Lucero */ 1041c7e9729dSAlejandro Lucero int 1042d108b9e9SChaoyong He nfp_cpp_read(struct nfp_cpp *cpp, 1043d108b9e9SChaoyong He uint32_t destination, 1044588c5b10SChaoyong He uint64_t offset, 1045588c5b10SChaoyong He void *address, 1046d108b9e9SChaoyong He size_t length) 1047c7e9729dSAlejandro Lucero { 1048c7e9729dSAlejandro Lucero int err; 1049610bf14bSChaoyong He struct nfp_cpp_area *area; 1050c7e9729dSAlejandro Lucero 1051588c5b10SChaoyong He area = nfp_cpp_area_alloc_acquire(cpp, destination, offset, length); 1052cbcbfd73SJames Hershaw if (area == NULL) { 1053*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Area allocation/acquire failed for read."); 1054ff627b74SChaoyong He return -EACCES; 1055c7e9729dSAlejandro Lucero } 1056c7e9729dSAlejandro Lucero 1057588c5b10SChaoyong He err = nfp_cpp_area_read(area, 0, address, length); 1058c7e9729dSAlejandro Lucero 1059c7e9729dSAlejandro Lucero nfp_cpp_area_release_free(area); 1060c7e9729dSAlejandro Lucero return err; 1061c7e9729dSAlejandro Lucero } 1062c7e9729dSAlejandro Lucero 10636d03aa61SChaoyong He /** 10646d03aa61SChaoyong He * Write to CPP target 10656d03aa61SChaoyong He * 10666d03aa61SChaoyong He * @param cpp 10676d03aa61SChaoyong He * CPP handle 10686d03aa61SChaoyong He * @param destination 10696d03aa61SChaoyong He * CPP id 1070588c5b10SChaoyong He * @param offset 10716d03aa61SChaoyong He * Offset into CPP target 1072588c5b10SChaoyong He * @param address 10736d03aa61SChaoyong He * Buffer to read from 10746d03aa61SChaoyong He * @param length 10756d03aa61SChaoyong He * Number of bytes to write 10766d03aa61SChaoyong He * 10776d03aa61SChaoyong He * @return 10786d03aa61SChaoyong He * Length of io, or -ERRNO 1079c7e9729dSAlejandro Lucero */ 1080c7e9729dSAlejandro Lucero int 1081d108b9e9SChaoyong He nfp_cpp_write(struct nfp_cpp *cpp, 1082d108b9e9SChaoyong He uint32_t destination, 1083588c5b10SChaoyong He uint64_t offset, 1084588c5b10SChaoyong He const void *address, 1085c7e9729dSAlejandro Lucero size_t length) 1086c7e9729dSAlejandro Lucero { 1087c7e9729dSAlejandro Lucero int err; 1088610bf14bSChaoyong He struct nfp_cpp_area *area; 1089c7e9729dSAlejandro Lucero 1090588c5b10SChaoyong He area = nfp_cpp_area_alloc_acquire(cpp, destination, offset, length); 1091efa766e1SChaoyong He if (area == NULL) { 1092*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Area allocation/acquire failed for write."); 1093ff627b74SChaoyong He return -EACCES; 1094efa766e1SChaoyong He } 1095c7e9729dSAlejandro Lucero 1096588c5b10SChaoyong He err = nfp_cpp_area_write(area, 0, address, length); 1097c7e9729dSAlejandro Lucero 1098c7e9729dSAlejandro Lucero nfp_cpp_area_release_free(area); 1099c7e9729dSAlejandro Lucero return err; 1100c7e9729dSAlejandro Lucero } 1101c7e9729dSAlejandro Lucero 1102c7e9729dSAlejandro Lucero /* 1103c7e9729dSAlejandro Lucero * NOTE: This code should not use nfp_xpb_* functions, 1104c7e9729dSAlejandro Lucero * as those are model-specific 1105c7e9729dSAlejandro Lucero */ 1106c7e9729dSAlejandro Lucero uint32_t 1107588c5b10SChaoyong He nfp_cpp_model_autodetect(struct nfp_cpp *cpp, 1108d108b9e9SChaoyong He uint32_t *model) 1109c7e9729dSAlejandro Lucero { 1110c0a8b024SHeinrich Kuhn int err; 1111610bf14bSChaoyong He uint32_t reg; 1112c7e9729dSAlejandro Lucero 1113c0a8b024SHeinrich Kuhn err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID, 1114c0a8b024SHeinrich Kuhn ®); 1115c0a8b024SHeinrich Kuhn if (err < 0) 1116c0a8b024SHeinrich Kuhn return err; 1117c0a8b024SHeinrich Kuhn 1118c0a8b024SHeinrich Kuhn *model = reg & NFP_PL_DEVICE_MODEL_MASK; 1119ff627b74SChaoyong He /* Disambiguate the NFP4000/NFP5000/NFP6000 chips */ 1120ff627b74SChaoyong He if (FIELD_GET(NFP_PL_DEVICE_PART_MASK, reg) == 1121ff627b74SChaoyong He NFP_PL_DEVICE_PART_NFP6000) { 11224aa75cadSChaoyong He if ((*model & NFP_PL_DEVICE_ID_MASK) != 0) 1123c0a8b024SHeinrich Kuhn *model -= 0x10; 1124ff627b74SChaoyong He } 1125c0a8b024SHeinrich Kuhn 11260fec453dSAlejandro Lucero return 0; 1127c7e9729dSAlejandro Lucero } 1128c7e9729dSAlejandro Lucero 11296d03aa61SChaoyong He /** 11306d03aa61SChaoyong He * Map an area of IOMEM access. 11316d03aa61SChaoyong He * To undo the effect of this function call @nfp_cpp_area_release_free(*area). 1132c7e9729dSAlejandro Lucero * 11336d03aa61SChaoyong He * @param cpp 11346d03aa61SChaoyong He * NFP CPP handler 11356d03aa61SChaoyong He * @param cpp_id 11366d03aa61SChaoyong He * CPP id 11376d03aa61SChaoyong He * @param addr 11386d03aa61SChaoyong He * CPP address 11396d03aa61SChaoyong He * @param size 11406d03aa61SChaoyong He * Size of the area 11416d03aa61SChaoyong He * @param area 11426d03aa61SChaoyong He * Area handle (output) 1143c7e9729dSAlejandro Lucero * 11446d03aa61SChaoyong He * @return 11456d03aa61SChaoyong He * Pointer to memory mapped area or NULL 1146c7e9729dSAlejandro Lucero */ 1147c7e9729dSAlejandro Lucero uint8_t * 1148d108b9e9SChaoyong He nfp_cpp_map_area(struct nfp_cpp *cpp, 1149d108b9e9SChaoyong He uint32_t cpp_id, 1150d108b9e9SChaoyong He uint64_t addr, 1151c69debceSChaoyong He uint32_t size, 1152d108b9e9SChaoyong He struct nfp_cpp_area **area) 1153c7e9729dSAlejandro Lucero { 1154c7e9729dSAlejandro Lucero uint8_t *res; 1155c7e9729dSAlejandro Lucero 1156925c27ecSChaoyong He *area = nfp_cpp_area_alloc_acquire(cpp, cpp_id, addr, size); 1157efa766e1SChaoyong He if (*area == NULL) { 1158*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Area allocation/acquire failed for map."); 1159c7e9729dSAlejandro Lucero goto err_eio; 1160efa766e1SChaoyong He } 1161c7e9729dSAlejandro Lucero 1162c7e9729dSAlejandro Lucero res = nfp_cpp_area_iomem(*area); 1163cbcbfd73SJames Hershaw if (res == NULL) 1164c7e9729dSAlejandro Lucero goto err_release_free; 1165c7e9729dSAlejandro Lucero 1166c7e9729dSAlejandro Lucero return res; 1167c7e9729dSAlejandro Lucero 1168c7e9729dSAlejandro Lucero err_release_free: 1169c7e9729dSAlejandro Lucero nfp_cpp_area_release_free(*area); 1170c7e9729dSAlejandro Lucero err_eio: 1171c7e9729dSAlejandro Lucero return NULL; 1172c7e9729dSAlejandro Lucero } 1173