New upstream version 18.05
[deb_dpdk.git] / drivers / raw / ifpga_rawdev / base / ifpga_port.c
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_port.c b/drivers/raw/ifpga_rawdev/base/ifpga_port.c
new file mode 100644 (file)
index 0000000..a962f5b
--- /dev/null
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "ifpga_feature_dev.h"
+
+int port_get_prop(struct ifpga_port_hw *port, struct feature_prop *prop)
+{
+       struct feature *feature;
+
+       if (!port)
+               return -ENOENT;
+
+       feature = get_port_feature_by_id(port, prop->feature_id);
+
+       if (feature && feature->ops && feature->ops->get_prop)
+               return feature->ops->get_prop(feature, prop);
+
+       return -ENOENT;
+}
+
+int port_set_prop(struct ifpga_port_hw *port, struct feature_prop *prop)
+{
+       struct feature *feature;
+
+       if (!port)
+               return -ENOENT;
+
+       feature = get_port_feature_by_id(port, prop->feature_id);
+
+       if (feature && feature->ops && feature->ops->set_prop)
+               return feature->ops->set_prop(feature, prop);
+
+       return -ENOENT;
+}
+
+int port_set_irq(struct ifpga_port_hw *port, u32 feature_id, void *irq_set)
+{
+       struct feature *feature;
+
+       if (!port)
+               return -ENOENT;
+
+       feature = get_port_feature_by_id(port, feature_id);
+
+       if (feature && feature->ops && feature->ops->set_irq)
+               return feature->ops->set_irq(feature, irq_set);
+
+       return -ENOENT;
+}
+
+static int port_get_revision(struct ifpga_port_hw *port, u64 *revision)
+{
+       struct feature_port_header *port_hdr
+               = get_port_feature_ioaddr_by_index(port,
+                                                  PORT_FEATURE_ID_HEADER);
+       struct feature_header header;
+
+       header.csr = readq(&port_hdr->header);
+
+       *revision = header.revision;
+
+       return 0;
+}
+
+static int port_get_portidx(struct ifpga_port_hw *port, u64 *idx)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_capability capability;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       capability.csr = readq(&port_hdr->capability);
+       *idx = capability.port_number;
+
+       return 0;
+}
+
+static int port_get_latency_tolerance(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_control control;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       control.csr = readq(&port_hdr->control);
+       *val = control.latency_tolerance;
+
+       return 0;
+}
+
+static int port_get_ap1_event(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_status status;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       status.csr = readq(&port_hdr->status);
+       spinlock_unlock(&port->lock);
+
+       *val = status.ap1_event;
+
+       return 0;
+}
+
+static int port_set_ap1_event(struct ifpga_port_hw *port, u64 val)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_status status;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       status.csr = readq(&port_hdr->status);
+       status.ap1_event = val;
+       writeq(status.csr, &port_hdr->status);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_get_ap2_event(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_status status;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       status.csr = readq(&port_hdr->status);
+       spinlock_unlock(&port->lock);
+
+       *val = status.ap2_event;
+
+       return 0;
+}
+
+static int port_set_ap2_event(struct ifpga_port_hw *port, u64 val)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_status status;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       status.csr = readq(&port_hdr->status);
+       status.ap2_event = val;
+       writeq(status.csr, &port_hdr->status);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_get_power_state(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+       struct feature_port_status status;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       status.csr = readq(&port_hdr->status);
+       spinlock_unlock(&port->lock);
+
+       *val = status.power_state;
+
+       return 0;
+}
+
+static int port_get_userclk_freqcmd(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       *val = readq(&port_hdr->user_clk_freq_cmd0);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_set_userclk_freqcmd(struct ifpga_port_hw *port, u64 val)
+{
+       struct feature_port_header *port_hdr;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       writeq(val, &port_hdr->user_clk_freq_cmd0);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_get_userclk_freqcntrcmd(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       *val = readq(&port_hdr->user_clk_freq_cmd1);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_set_userclk_freqcntrcmd(struct ifpga_port_hw *port, u64 val)
+{
+       struct feature_port_header *port_hdr;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       writeq(val, &port_hdr->user_clk_freq_cmd1);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_get_userclk_freqsts(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       *val = readq(&port_hdr->user_clk_freq_sts0);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_get_userclk_freqcntrsts(struct ifpga_port_hw *port, u64 *val)
+{
+       struct feature_port_header *port_hdr;
+
+       port_hdr = get_port_feature_ioaddr_by_index(port,
+                                                   PORT_FEATURE_ID_HEADER);
+
+       spinlock_lock(&port->lock);
+       *val = readq(&port_hdr->user_clk_freq_sts1);
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static int port_hdr_init(struct feature *feature)
+{
+       struct ifpga_port_hw *port = feature->parent;
+
+       dev_info(NULL, "port hdr Init.\n");
+
+       fpga_port_reset(port);
+
+       return 0;
+}
+
+static void port_hdr_uinit(struct feature *feature)
+{
+       UNUSED(feature);
+
+       dev_info(NULL, "port hdr uinit.\n");
+}
+
+static int port_hdr_get_prop(struct feature *feature, struct feature_prop *prop)
+{
+       struct ifpga_port_hw *port = feature->parent;
+
+       switch (prop->prop_id) {
+       case PORT_HDR_PROP_REVISION:
+               return port_get_revision(port, &prop->data);
+       case PORT_HDR_PROP_PORTIDX:
+               return port_get_portidx(port, &prop->data);
+       case PORT_HDR_PROP_LATENCY_TOLERANCE:
+               return port_get_latency_tolerance(port, &prop->data);
+       case PORT_HDR_PROP_AP1_EVENT:
+               return port_get_ap1_event(port, &prop->data);
+       case PORT_HDR_PROP_AP2_EVENT:
+               return port_get_ap2_event(port, &prop->data);
+       case PORT_HDR_PROP_POWER_STATE:
+               return port_get_power_state(port, &prop->data);
+       case PORT_HDR_PROP_USERCLK_FREQCMD:
+               return port_get_userclk_freqcmd(port, &prop->data);
+       case PORT_HDR_PROP_USERCLK_FREQCNTRCMD:
+               return port_get_userclk_freqcntrcmd(port, &prop->data);
+       case PORT_HDR_PROP_USERCLK_FREQSTS:
+               return port_get_userclk_freqsts(port, &prop->data);
+       case PORT_HDR_PROP_USERCLK_CNTRSTS:
+               return port_get_userclk_freqcntrsts(port, &prop->data);
+       }
+
+       return -ENOENT;
+}
+
+static int port_hdr_set_prop(struct feature *feature, struct feature_prop *prop)
+{
+       struct ifpga_port_hw *port = feature->parent;
+
+       switch (prop->prop_id) {
+       case PORT_HDR_PROP_AP1_EVENT:
+               return port_set_ap1_event(port, prop->data);
+       case PORT_HDR_PROP_AP2_EVENT:
+               return port_set_ap2_event(port, prop->data);
+       case PORT_HDR_PROP_USERCLK_FREQCMD:
+               return port_set_userclk_freqcmd(port, prop->data);
+       case PORT_HDR_PROP_USERCLK_FREQCNTRCMD:
+               return port_set_userclk_freqcntrcmd(port, prop->data);
+       }
+
+       return -ENOENT;
+}
+
+struct feature_ops port_hdr_ops = {
+       .init = port_hdr_init,
+       .uinit = port_hdr_uinit,
+       .get_prop = port_hdr_get_prop,
+       .set_prop = port_hdr_set_prop,
+};
+
+static int port_stp_init(struct feature *feature)
+{
+       struct ifpga_port_hw *port = feature->parent;
+
+       dev_info(NULL, "port stp Init.\n");
+
+       spinlock_lock(&port->lock);
+       port->stp_addr = feature->addr;
+       port->stp_size = feature->size;
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static void port_stp_uinit(struct feature *feature)
+{
+       UNUSED(feature);
+
+       dev_info(NULL, "port stp uinit.\n");
+}
+
+struct feature_ops port_stp_ops = {
+       .init = port_stp_init,
+       .uinit = port_stp_uinit,
+};
+
+static int port_uint_init(struct feature *feature)
+{
+       struct ifpga_port_hw *port = feature->parent;
+
+       dev_info(NULL, "PORT UINT Init.\n");
+
+       spinlock_lock(&port->lock);
+       if (feature->ctx_num) {
+               port->capability |= FPGA_PORT_CAP_UAFU_IRQ;
+               port->num_uafu_irqs = feature->ctx_num;
+       }
+       spinlock_unlock(&port->lock);
+
+       return 0;
+}
+
+static void port_uint_uinit(struct feature *feature)
+{
+       UNUSED(feature);
+
+       dev_info(NULL, "PORT UINT UInit.\n");
+}
+
+struct feature_ops port_uint_ops = {
+       .init = port_uint_init,
+       .uinit = port_uint_uinit,
+};