#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/types.h>
 
  * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag.
  * The caller should hold a reference to @node.
  *
+ * NOTE: This function does not parse properties the size of which is
+ * variable without a low fixed limit. Please use
+ * v4l2_of_alloc_parse_endpoint() in new drivers instead.
+ *
  * Return: 0.
  */
 int v4l2_of_parse_endpoint(const struct device_node *node,
 }
 EXPORT_SYMBOL(v4l2_of_parse_endpoint);
 
+/*
+ * v4l2_of_free_endpoint() - free the endpoint acquired by
+ * v4l2_of_alloc_parse_endpoint()
+ * @endpoint - the endpoint the resources of which are to be released
+ *
+ * It is safe to call this function with NULL argument or on an
+ * endpoint the parsing of which failed.
+ */
+void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint)
+{
+       if (IS_ERR_OR_NULL(endpoint))
+               return;
+
+       kfree(endpoint->link_frequencies);
+       kfree(endpoint);
+}
+EXPORT_SYMBOL(v4l2_of_free_endpoint);
+
+/**
+ * v4l2_of_alloc_parse_endpoint() - parse all endpoint node properties
+ * @node: pointer to endpoint device_node
+ *
+ * All properties are optional. If none are found, we don't set any flags.
+ * This means the port has a static configuration and no properties have
+ * to be specified explicitly.
+ * If any properties that identify the bus as parallel are found and
+ * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we recognise
+ * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the
+ * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag.
+ * The caller should hold a reference to @node.
+ *
+ * v4l2_of_alloc_parse_endpoint() has two important differences to
+ * v4l2_of_parse_endpoint():
+ *
+ * 1. It also parses variable size data and
+ *
+ * 2. The memory it has allocated to store the variable size data must
+ *    be freed using v4l2_of_free_endpoint() when no longer needed.
+ *
+ * Return: Pointer to v4l2_of_endpoint if successful, on error a
+ * negative error code.
+ */
+struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint(
+       const struct device_node *node)
+{
+       struct v4l2_of_endpoint *endpoint;
+       int len;
+       int rval;
+
+       endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
+       if (!endpoint)
+               return ERR_PTR(-ENOMEM);
+
+       rval = v4l2_of_parse_endpoint(node, endpoint);
+       if (rval < 0)
+               goto out_err;
+
+       if (of_get_property(node, "link-frequencies", &len)) {
+               endpoint->link_frequencies = kmalloc(len, GFP_KERNEL);
+               if (!endpoint->link_frequencies) {
+                       rval = -ENOMEM;
+                       goto out_err;
+               }
+
+               endpoint->nr_of_link_frequencies =
+                       len / sizeof(*endpoint->link_frequencies);
+
+               rval = of_property_read_u64_array(
+                       node, "link-frequencies", endpoint->link_frequencies,
+                       endpoint->nr_of_link_frequencies);
+               if (rval < 0)
+                       goto out_err;
+       }
+
+       return endpoint;
+
+out_err:
+       v4l2_of_free_endpoint(endpoint);
+       return ERR_PTR(rval);
+}
+EXPORT_SYMBOL(v4l2_of_alloc_parse_endpoint);
+
 /**
  * v4l2_of_parse_link() - parse a link between two endpoints
  * @node: pointer to the endpoint at the local end of the link
 
  * @base: struct of_endpoint containing port, id, and local of_node
  * @bus_type: bus type
  * @bus: bus configuration data structure
+ * @link_frequencies: array of supported link frequencies
+ * @nr_of_link_frequencies: number of elements in link_frequenccies array
  */
 struct v4l2_of_endpoint {
        struct of_endpoint base;
                struct v4l2_of_bus_parallel parallel;
                struct v4l2_of_bus_mipi_csi2 mipi_csi2;
        } bus;
+       u64 *link_frequencies;
+       unsigned int nr_of_link_frequencies;
 };
 
 /**
 #ifdef CONFIG_OF
 int v4l2_of_parse_endpoint(const struct device_node *node,
                           struct v4l2_of_endpoint *endpoint);
+struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint(
+       const struct device_node *node);
+void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint);
 int v4l2_of_parse_link(const struct device_node *node,
                       struct v4l2_of_link *link);
 void v4l2_of_put_link(struct v4l2_of_link *link);
        return -ENOSYS;
 }
 
+struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint(
+       const struct device_node *node)
+{
+       return NULL;
+}
+
+static void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint)
+{
+}
+
 static inline int v4l2_of_parse_link(const struct device_node *node,
                                     struct v4l2_of_link *link)
 {