All of lore.kernel.org
 help / color / mirror / Atom feed
From: thesven73@gmail.com
To: svendev@arcx.com, robh+dt@kernel.org, linus.walleij@linaro.org
Cc: lee.jones@linaro.org, mark.rutland@arm.com, afaerber@suse.de,
	treding@nvidia.com, david@lechnology.com, noralf@tronnes.org,
	johan@kernel.org, monstr@monstr.eu, michal.vokac@ysoft.com,
	arnd@arndb.de, gregkh@linuxfoundation.org, john.garry@huawei.com,
	geert+renesas@glider.be, robin.murphy@arm.com,
	paul.gortmaker@windriver.com,
	sebastien.bourdelin@savoirfairelinux.com, icenowy@aosc.io,
	stuyoder@gmail.com, maxime.ripard@bootlin.com,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
Subject: [PATCH anybus v4 7/7] fieldbus_dev: support HMS Profinet IRT industrial controller
Date: Wed, 21 Nov 2018 10:07:09 -0500	[thread overview]
Message-ID: <20181121150709.6030-8-TheSven73@googlemail.com> (raw)
In-Reply-To: <20181121150709.6030-1-TheSven73@googlemail.com>

The Anybus-S PROFINET IRT communication module provides instant integration
to any Ethernet based LAN via SMTP, FTP, HTTP as well as PROFINET and
Modbus-TCP. Additional protocols can be implemented on top of TCP/IP
or UDP using the transparent socket interface.

Official documentation:
https://www.anybus.com/docs/librariesprovider7/default-document-library
/manuals-design-guides/hms-hmsi-168-52.pdf

This implementation is an Anybus-S client driver, designed to be
instantiated by the Anybus-S bus driver when it discovers the Profinet
card.

If loaded successfully, the driver registers itself as a fieldbus_dev,
and userspace can access it through the fieldbus_dev interface.

Signed-off-by: Sven Van Asbroeck <svendev@arcx.com>
---
 drivers/fieldbus/Kconfig        |  17 +++
 drivers/fieldbus/Makefile       |   1 +
 drivers/fieldbus/hms-profinet.c | 223 ++++++++++++++++++++++++++++++++
 3 files changed, 241 insertions(+)
 create mode 100644 drivers/fieldbus/hms-profinet.c

diff --git a/drivers/fieldbus/Kconfig b/drivers/fieldbus/Kconfig
index 00a163a2cbe6..12b0fef591fb 100644
--- a/drivers/fieldbus/Kconfig
+++ b/drivers/fieldbus/Kconfig
@@ -36,4 +36,21 @@ config HMS_ANYBUSS_HOST
 	  typically provide fieldbus and industrial ethernet
 	  functionality.
 
+config HMS_PROFINET
+	tristate "HMS Profinet IRT Controller (Anybus-S)"
+	depends on FIELDBUS_DEV
+	select HMS_ANYBUSS_HOST
+	help
+	 If you say yes here you get support for the HMS Industrial
+	 Networks Profinet IRT Controller.
+
+	 It will be registered with the kernel as a fieldbus_dev,
+	 so userspace can interact with it via the fieldbus_dev userspace
+	 interface(s).
+
+	 This driver can also be built as a module. If so, the module
+	 will be called hms-profinet.
+
+	 If unsure, say N.
+
 endif
diff --git a/drivers/fieldbus/Makefile b/drivers/fieldbus/Makefile
index c47a4bd416f6..c3161c5ce0f1 100644
--- a/drivers/fieldbus/Makefile
+++ b/drivers/fieldbus/Makefile
@@ -9,3 +9,4 @@ fieldbus_dev_core-y		:= dev_core.o
 # Devices
 obj-$(CONFIG_ARCX_ANYBUS_BRIDGE) += anybus-bridge.o
 obj-$(CONFIG_HMS_ANYBUSS_HOST)	+= anybuss-host.o
+obj-$(CONFIG_HMS_PROFINET)	+= hms-profinet.o
diff --git a/drivers/fieldbus/hms-profinet.c b/drivers/fieldbus/hms-profinet.c
new file mode 100644
index 000000000000..434437829339
--- /dev/null
+++ b/drivers/fieldbus/hms-profinet.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * HMS Profinet Client Driver
+ *
+ * Copyright (C) 2018 Arcx Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fieldbus_dev.h>
+#include <linux/anybuss-client.h>
+
+#define PROFI_DPRAM_SIZE	512
+
+/*
+ * ---------------------------------------------------------------
+ * Anybus Profinet mailbox messages - definitions
+ * ---------------------------------------------------------------
+ * note that we're depending on the layout of these structures being
+ * exactly as advertised.
+ */
+
+struct msgMacAddr {
+	u8 addr[6];
+};
+
+struct profi_priv {
+	struct fieldbus_dev fbdev;
+	struct anybuss_client *client;
+	struct mutex enable_lock;
+	bool power_on;
+};
+
+static ssize_t
+profi_read_area(struct fieldbus_dev *fbdev, char __user *buf, size_t size,
+			loff_t *offset)
+{
+	struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
+
+	return anybuss_read_output(priv->client, buf, size, offset);
+}
+
+static ssize_t
+profi_write_area(struct fieldbus_dev *fbdev, const char __user *buf,
+			size_t size, loff_t *offset)
+{
+	struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
+
+	return anybuss_write_input(priv->client, buf, size, offset);
+}
+
+static int profi_id_get(struct fieldbus_dev *fbdev, char *buf,
+				size_t max_size)
+{
+	struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
+	struct msgMacAddr response;
+	int ret;
+
+	ret = anybuss_recv_msg(priv->client, 0x0010, &response,
+						sizeof(response));
+	if (ret < 0)
+		return ret;
+	return snprintf(buf, max_size, "%02X:%02X:%02X:%02X:%02X:%02X\n",
+		response.addr[0], response.addr[1],
+		response.addr[2], response.addr[3],
+		response.addr[4], response.addr[5]);
+}
+
+static bool profi_enable_get(struct fieldbus_dev *fbdev)
+{
+	struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
+	bool power_on;
+
+	mutex_lock(&priv->enable_lock);
+	power_on = priv->power_on;
+	mutex_unlock(&priv->enable_lock);
+
+	return power_on;
+}
+
+static int __profi_enable(struct profi_priv *priv)
+{
+	int ret;
+	struct anybuss_client *client = priv->client;
+	/* Initialization Sequence, Generic Anybus Mode */
+	const struct anybuss_memcfg mem_cfg = {
+		.input_io = 220,
+		.input_dpram = PROFI_DPRAM_SIZE,
+		.input_total = PROFI_DPRAM_SIZE,
+		.output_io = 220,
+		.output_dpram = PROFI_DPRAM_SIZE,
+		.output_total = PROFI_DPRAM_SIZE,
+		.offl_mode = AB_OFFL_MODE_CLEAR,
+	};
+
+	/*
+	 * switch anybus off then on, this ensures we can do a complete
+	 * configuration cycle in case anybus was already on.
+	 */
+	anybuss_set_power(client, false);
+	ret = anybuss_set_power(client, true);
+	if (ret)
+		goto err;
+	ret = anybuss_start_init(client, &mem_cfg);
+	if (ret)
+		goto err;
+	ret = anybuss_finish_init(client);
+	if (ret)
+		goto err;
+	priv->power_on = true;
+	return 0;
+
+err:
+	anybuss_set_power(client, false);
+	priv->power_on = false;
+	return ret;
+}
+
+static int __profi_disable(struct profi_priv *priv)
+{
+	struct anybuss_client *client = priv->client;
+
+	anybuss_set_power(client, false);
+	priv->power_on = false;
+	return 0;
+}
+
+static int profi_simple_enable(struct fieldbus_dev *fbdev, bool enable)
+{
+	int ret;
+	struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
+
+	mutex_lock(&priv->enable_lock);
+	if (enable)
+		ret = __profi_enable(priv);
+	else
+		ret = __profi_disable(priv);
+	mutex_unlock(&priv->enable_lock);
+
+	return ret;
+}
+
+static void profi_on_area_updated(struct anybuss_client *client)
+{
+	struct profi_priv *priv = anybuss_get_drvdata(client);
+
+	fieldbus_dev_area_updated(&priv->fbdev);
+}
+
+static void profi_on_online_changed(struct anybuss_client *client, bool online)
+{
+	struct profi_priv *priv = anybuss_get_drvdata(client);
+
+	fieldbus_dev_online_changed(&priv->fbdev, online);
+}
+
+static int profinet_probe(struct anybuss_client *client)
+{
+	struct profi_priv *priv;
+	struct device *dev = &client->dev;
+	int err;
+
+	client->on_area_updated = profi_on_area_updated;
+	client->on_online_changed = profi_on_online_changed;
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	mutex_init(&priv->enable_lock);
+	priv->client = client;
+	priv->fbdev.read_area_sz = priv->fbdev.write_area_sz = PROFI_DPRAM_SIZE;
+	priv->fbdev.card_name = "HMS Profinet IRT (Anybus-S)";
+	priv->fbdev.fieldbus_type = FIELDBUS_DEV_TYPE_PROFINET;
+	priv->fbdev.read_area = profi_read_area;
+	priv->fbdev.write_area = profi_write_area;
+	priv->fbdev.fieldbus_id_get = profi_id_get;
+	priv->fbdev.enable_get = profi_enable_get;
+	priv->fbdev.simple_enable_set = profi_simple_enable;
+	priv->fbdev.parent = dev;
+	err = fieldbus_dev_register(&priv->fbdev);
+	if (err < 0)
+		return err;
+	dev_info(dev, "card detected, registered as %s",
+				dev_name(priv->fbdev.dev));
+	anybuss_set_drvdata(client, priv);
+
+	return 0;
+}
+
+static int profinet_remove(struct anybuss_client *client)
+{
+	struct profi_priv *priv = anybuss_get_drvdata(client);
+
+	fieldbus_dev_unregister(&priv->fbdev);
+	return 0;
+}
+
+static struct anybuss_client_driver profinet_driver = {
+	.probe = profinet_probe,
+	.remove = profinet_remove,
+	.driver		= {
+		.name   = "hms-profinet",
+		.owner	= THIS_MODULE,
+	},
+	.fieldbus_type = 0x0089,
+};
+
+static int __init profinet_init(void)
+{
+	return anybuss_client_driver_register(&profinet_driver);
+}
+module_init(profinet_init);
+
+static void __exit profinet_exit(void)
+{
+	return anybuss_client_driver_unregister(&profinet_driver);
+}
+module_exit(profinet_exit);
+
+MODULE_AUTHOR("Sven Van Asbroeck <svendev@arcx.com>");
+MODULE_DESCRIPTION("HMS Profinet IRT Driver (Anybus-S)");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


      parent reply	other threads:[~2018-11-21 15:07 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-21 15:07 [PATCH anybus v4 0/7] Add Fieldbus subsystem + support HMS Profinet card thesven73
2018-11-21 15:07 ` [PATCH anybus v4 1/7] fieldbus_dev: add Fieldbus Device subsystem thesven73
2018-11-27  7:47   ` Greg KH
2018-11-27  7:47   ` Greg KH
2018-11-27  7:54   ` Greg KH
2018-11-28 15:39     ` Sven Van Asbroeck
2018-11-28 17:42       ` Greg KH
2018-11-28 18:19         ` Sven Van Asbroeck
2018-11-28 18:36           ` Greg KH
2018-11-28 19:39             ` Sven Van Asbroeck
2018-11-21 15:07 ` [PATCH anybus v4 2/7] fieldbus: support the Arcx anybus bridge thesven73
2018-11-21 15:07 ` [PATCH anybus v4 3/7] dt-bindings: Add vendor prefix for arcx / Archronix thesven73
2018-11-21 15:07 ` [PATCH anybus v4 4/7] dt-bindings: anybus-bridge: document devicetree binding thesven73
2018-11-21 15:07 ` [PATCH anybus v4 5/7] fieldbus: support HMS Anybus-S bus thesven73
2018-11-21 15:07 ` [PATCH anybus v4 6/7] dt-bindings: anybuss-host: document devicetree binding thesven73
2018-11-26 22:08   ` Rob Herring
2018-11-28 15:38     ` Sven Van Asbroeck
2018-11-28 16:36       ` Rob Herring
2018-11-28 16:36         ` Rob Herring
2018-11-29 20:59         ` Sven Van Asbroeck
2018-11-30  1:39           ` Rob Herring
2018-11-30  1:39             ` Rob Herring
2018-11-21 15:07 ` thesven73 [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181121150709.6030-8-TheSven73@googlemail.com \
    --to=thesven73@gmail.com \
    --cc=afaerber@suse.de \
    --cc=arnd@arndb.de \
    --cc=david@lechnology.com \
    --cc=devicetree@vger.kernel.org \
    --cc=geert+renesas@glider.be \
    --cc=gregkh@linuxfoundation.org \
    --cc=icenowy@aosc.io \
    --cc=johan@kernel.org \
    --cc=john.garry@huawei.com \
    --cc=lee.jones@linaro.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=maxime.ripard@bootlin.com \
    --cc=michal.vokac@ysoft.com \
    --cc=monstr@monstr.eu \
    --cc=noralf@tronnes.org \
    --cc=paul.gortmaker@windriver.com \
    --cc=robh+dt@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=sebastien.bourdelin@savoirfairelinux.com \
    --cc=stuyoder@gmail.com \
    --cc=svendev@arcx.com \
    --cc=treding@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.