aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/cavium/include/bdk/libbdk-hal/device/bdk-device.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/cavium/include/bdk/libbdk-hal/device/bdk-device.h')
-rw-r--r--src/vendorcode/cavium/include/bdk/libbdk-hal/device/bdk-device.h259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/vendorcode/cavium/include/bdk/libbdk-hal/device/bdk-device.h b/src/vendorcode/cavium/include/bdk/libbdk-hal/device/bdk-device.h
new file mode 100644
index 0000000000..3ca3f00710
--- /dev/null
+++ b/src/vendorcode/cavium/include/bdk/libbdk-hal/device/bdk-device.h
@@ -0,0 +1,259 @@
+/***********************license start***********************************
+* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
+* reserved.
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+*
+* * Neither the name of Cavium Inc. nor the names of
+* its contributors may be used to endorse or promote products
+* derived from this software without specific prior written
+* permission.
+*
+* This Software, including technical data, may be subject to U.S. export
+* control laws, including the U.S. Export Administration Act and its
+* associated regulations, and may be subject to export or import
+* regulations in other countries.
+*
+* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
+* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
+* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
+* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
+* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
+* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
+* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
+* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
+* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * bdk_device_t represents devices connected using ECAMs. This
+ * are discover by scanning the ECAMs and instantiating devices
+ * for what is found.
+ *
+ * The discovery process for a device is: Scan all ECAMs:
+ * 1) Device found on an ECAM that doesn't have a bdk_device_t
+ * 2) bdk_device_t created, put in
+ * BDK_DEVICE_STATE_NOT_PROBED state
+ * For all devices in state BDK_DEVICE_STATE_NOT_PROBED:
+ * 1) Lookup driver probe() function. If not found, skip
+ * 2) Call probe() 3) Based on probe(), transition to
+ * either BDK_DEVICE_STATE_PROBED or
+ * BDK_DEVICE_STATE_PROBE_FAIL
+ * For all devices in state BDK_DEVICE_STATE_PROBED:
+ * 1) Lookup driver init() function. If not found, skip
+ * 2) Call init() 3) Based on init(), transition to either
+ * BDK_DEVICE_STATE_READY or BDK_DEVICE_STATE_INIT_FAIL
+ * In general all devices should transition to
+ * BDK_DEVICE_STATE_PROBED before any init() functions are
+ * called. This can be used for synchronization. For example,
+ * the FPA should be functional after a probe() so PKI/PKO can
+ * succeed when calling alloc in init().
+ *
+ * @defgroup device ECAM Attached Devices
+ * @addtogroup device
+ * @{
+ */
+
+/**
+ * Possible states of a device
+ */
+typedef enum
+{
+ BDK_DEVICE_STATE_NOT_PROBED, /* Device is known and offline. We haven't probed it */
+ BDK_DEVICE_STATE_PROBE_FAIL, /* Device failed probing and is offline */
+ BDK_DEVICE_STATE_PROBED, /* Device succeeded probing, about to go online */
+ BDK_DEVICE_STATE_INIT_FAIL, /* Device init call failed, offline */
+ BDK_DEVICE_STATE_READY, /* Device init call success, online */
+} bdk_device_state_t;
+
+/**
+ * The structure of a ECAM BAR entry inside if a device
+ */
+typedef struct
+{
+ uint64_t address; /* Base physical address */
+ uint32_t size2; /* Size in bytes as 2^size */
+ uint32_t flags; /* Type flags for the BAR */
+} bdk_device_bar_t;
+
+/**
+ * Defines the BDK's representation of a ECAM connected device
+ */
+typedef struct
+{
+ char name[16]; /* Name of the device */
+ bdk_device_bar_t bar[4]; /* Device BARs, first for better alignment */
+ bdk_device_state_t state : 8; /* Current state of bdk_device_t */
+ bdk_node_t node : 3; /* Node the device is on */
+ uint8_t ecam : 5; /* ECAM for the device */
+ uint8_t bus; /* ECAM bus number (0-255) */
+ uint8_t dev : 5; /* ECAM device (0-31) */
+ uint8_t func : 3; /* ECAM deivce function (0-7) */
+ uint32_t id; /* ECAM device ID */
+ uint16_t instance; /* Cavium internal instance number */
+} bdk_device_t;
+#define BDK_NO_DEVICE_INSTANCE 0xffffu
+
+/**
+ * Defines the main entry points for a device driver. Full
+ * definition is in bdk-device.h
+ */
+struct bdk_driver_s;
+
+/**
+ * Called to register a new driver with the bdk-device system. Drivers are probed
+ * and initialized as device are found for them. If devices have already been
+ * added before the driver was registered, the driver will be probed and
+ * initialized before this function returns.
+ *
+ * @param driver Driver functions
+ *
+ * @return Zero on success, negative on failure
+ */
+extern int bdk_device_add_driver(struct bdk_driver_s *driver);
+
+/**
+ * Called by the ECAM code whan a new device is detected in the system
+ *
+ * @param node Node the ECAM is on
+ * @param ecam ECAM the device is on
+ * @param bus Bus number for the device
+ * @param dev Device number
+ * @param func Function number
+ *
+ * @return Zero on success, negative on failure
+ */
+extern int bdk_device_add(bdk_node_t node, int ecam, int bus, int dev, int func);
+
+/**
+ * Rename a device. Called by driver to give devices friendly names
+ *
+ * @param device Device to rename
+ * @param format Printf style format string
+ */
+extern void bdk_device_rename(bdk_device_t *device, const char *format, ...) __attribute__ ((format(printf, 2, 3)));
+
+/**
+ * Called by the ECAM code once all devices have been added
+ *
+ * @return Zero on success, negative on failure
+ */
+extern int bdk_device_init(void);
+
+/**
+ * Lookup a device by ECAM ID and internal instance number. This can be used by
+ * one device to find a handle to an associated device. For example, PKI would
+ * use this function to get a handle to the FPA.
+ *
+ * @param node Node to lookup for
+ * @param id ECAM ID
+ * @param instance Cavium internal instance number
+ *
+ * @return Device pointer, or NULL if the device isn't found
+ */
+extern const bdk_device_t *bdk_device_lookup(bdk_node_t node, uint32_t id, int instance);
+
+/**
+ * Read from a device BAR
+ *
+ * @param device Device to read from
+ * @param bar Which BAR to read from (0-3)
+ * @param size Size of the read
+ * @param offset Offset into the BAR
+ *
+ * @return Value read
+ */
+extern uint64_t bdk_bar_read(const bdk_device_t *device, int bar, int size, uint64_t offset);
+
+/**
+ * Write to a device BAR
+ *
+ * @param device Device to write to
+ * @param bar Which BAR to read from (0-3)
+ * @param size Size of the write
+ * @param offset Offset into the BAR
+ * @param value Value to write
+ */
+extern void bdk_bar_write(const bdk_device_t *device, int bar, int size, uint64_t offset, uint64_t value);
+
+/**
+ * This macro makes it easy to define a variable of the correct
+ * type for a BAR.
+ */
+#define BDK_BAR_DEFINE(name, REG) typedef_##REG name
+
+/**
+ * This macro makes it easy to define a variable and initialize it
+ * with a BAR.
+ */
+#define BDK_BAR_INIT(name, device, REG) typedef_##REG name = {.u = bdk_bar_read(device, device_bar_##REG, sizeof(typedef_##REG), REG)}
+
+/**
+ * Macro to read a BAR
+ */
+#define BDK_BAR_READ(device, REG) bdk_bar_read(device, device_bar_##REG, sizeof(typedef_##REG), REG)
+
+/**
+ * Macro to write a BAR
+ */
+#define BDK_BAR_WRITE(device, REG, value) bdk_bar_write(device, device_bar_##REG, sizeof(typedef_##REG), REG, value)
+
+/**
+ * Macro to make a read, modify, and write sequence easy. The "code_block"
+ * should be replaced with a C code block or a comma separated list of
+ * "name.s.field = value", without the quotes.
+ */
+#define BDK_BAR_MODIFY(name, device, REG, code_block) do { \
+ uint64_t _tmp_address = REG; \
+ typedef_##REG name = {.u = bdk_bar_read(device, device_bar_##REG, sizeof(typedef_##REG), _tmp_address)}; \
+ code_block; \
+ bdk_bar_write(device, device_bar_##REG, sizeof(typedef_##REG), _tmp_address, name.u); \
+ } while (0)
+
+/**
+ * This macro spins on a field waiting for it to reach a value. It
+ * is common in code to need to wait for a specific field in a
+ * REG to match a specific value. Conceptually this macro
+ * expands to:
+ *
+ * 1) read REG
+ * 2) Check if ("type".s."field" "op" "value")
+ * 3) If #2 isn't true loop to #1 unless too much time has passed.
+ */
+#define BDK_BAR_WAIT_FOR_FIELD(device, REG, field, op, value, timeout_usec) \
+ ({int result; \
+ do { \
+ uint64_t done = bdk_clock_get_count(BDK_CLOCK_TIME) + (uint64_t)timeout_usec * \
+ bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) / 1000000; \
+ typedef_##REG c; \
+ uint64_t _tmp_address = REG; \
+ while (1) \
+ { \
+ c.u = bdk_bar_read(device, device_bar_##REG, sizeof(typedef_##REG), _tmp_address); \
+ if ((c.s.field) op (value)) { \
+ result = 0; \
+ break; \
+ } else if (bdk_clock_get_count(BDK_CLOCK_TIME) > done) { \
+ result = -1; \
+ break; \
+ } else \
+ bdk_thread_yield(); \
+ } \
+ } while (0); \
+ result;})
+
+/** @} */