0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/init.h>
0011 #include <linux/slab.h>
0012
0013
0014 #include "../fieldbus_dev.h"
0015
0016
0017 #include "anybuss-client.h"
0018
0019 #define PROFI_DPRAM_SIZE 512
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 struct msg_mac_addr {
0030 u8 addr[6];
0031 };
0032
0033 struct profi_priv {
0034 struct fieldbus_dev fbdev;
0035 struct anybuss_client *client;
0036 struct mutex enable_lock;
0037 bool power_on;
0038 };
0039
0040 static ssize_t
0041 profi_read_area(struct fieldbus_dev *fbdev, char __user *buf, size_t size,
0042 loff_t *offset)
0043 {
0044 struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
0045
0046 return anybuss_read_output(priv->client, buf, size, offset);
0047 }
0048
0049 static ssize_t
0050 profi_write_area(struct fieldbus_dev *fbdev, const char __user *buf,
0051 size_t size, loff_t *offset)
0052 {
0053 struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
0054
0055 return anybuss_write_input(priv->client, buf, size, offset);
0056 }
0057
0058 static int profi_id_get(struct fieldbus_dev *fbdev, char *buf,
0059 size_t max_size)
0060 {
0061 struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
0062 struct msg_mac_addr response;
0063 int ret;
0064
0065 ret = anybuss_recv_msg(priv->client, 0x0010, &response,
0066 sizeof(response));
0067 if (ret < 0)
0068 return ret;
0069 return snprintf(buf, max_size, "%pM\n", response.addr);
0070 }
0071
0072 static bool profi_enable_get(struct fieldbus_dev *fbdev)
0073 {
0074 struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
0075 bool power_on;
0076
0077 mutex_lock(&priv->enable_lock);
0078 power_on = priv->power_on;
0079 mutex_unlock(&priv->enable_lock);
0080
0081 return power_on;
0082 }
0083
0084 static int __profi_enable(struct profi_priv *priv)
0085 {
0086 int ret;
0087 struct anybuss_client *client = priv->client;
0088
0089 const struct anybuss_memcfg mem_cfg = {
0090 .input_io = 220,
0091 .input_dpram = PROFI_DPRAM_SIZE,
0092 .input_total = PROFI_DPRAM_SIZE,
0093 .output_io = 220,
0094 .output_dpram = PROFI_DPRAM_SIZE,
0095 .output_total = PROFI_DPRAM_SIZE,
0096 .offl_mode = FIELDBUS_DEV_OFFL_MODE_CLEAR,
0097 };
0098
0099
0100
0101
0102
0103 anybuss_set_power(client, false);
0104 ret = anybuss_set_power(client, true);
0105 if (ret)
0106 goto err;
0107 ret = anybuss_start_init(client, &mem_cfg);
0108 if (ret)
0109 goto err;
0110 ret = anybuss_finish_init(client);
0111 if (ret)
0112 goto err;
0113 priv->power_on = true;
0114 return 0;
0115
0116 err:
0117 anybuss_set_power(client, false);
0118 priv->power_on = false;
0119 return ret;
0120 }
0121
0122 static int __profi_disable(struct profi_priv *priv)
0123 {
0124 struct anybuss_client *client = priv->client;
0125
0126 anybuss_set_power(client, false);
0127 priv->power_on = false;
0128 return 0;
0129 }
0130
0131 static int profi_simple_enable(struct fieldbus_dev *fbdev, bool enable)
0132 {
0133 int ret;
0134 struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
0135
0136 mutex_lock(&priv->enable_lock);
0137 if (enable)
0138 ret = __profi_enable(priv);
0139 else
0140 ret = __profi_disable(priv);
0141 mutex_unlock(&priv->enable_lock);
0142
0143 return ret;
0144 }
0145
0146 static void profi_on_area_updated(struct anybuss_client *client)
0147 {
0148 struct profi_priv *priv = anybuss_get_drvdata(client);
0149
0150 fieldbus_dev_area_updated(&priv->fbdev);
0151 }
0152
0153 static void profi_on_online_changed(struct anybuss_client *client, bool online)
0154 {
0155 struct profi_priv *priv = anybuss_get_drvdata(client);
0156
0157 fieldbus_dev_online_changed(&priv->fbdev, online);
0158 }
0159
0160 static int profinet_probe(struct anybuss_client *client)
0161 {
0162 struct profi_priv *priv;
0163 struct device *dev = &client->dev;
0164 int err;
0165
0166 client->on_area_updated = profi_on_area_updated;
0167 client->on_online_changed = profi_on_online_changed;
0168 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0169 if (!priv)
0170 return -ENOMEM;
0171 mutex_init(&priv->enable_lock);
0172 priv->client = client;
0173 priv->fbdev.read_area_sz = PROFI_DPRAM_SIZE;
0174 priv->fbdev.write_area_sz = PROFI_DPRAM_SIZE;
0175 priv->fbdev.card_name = "HMS Profinet IRT (Anybus-S)";
0176 priv->fbdev.fieldbus_type = FIELDBUS_DEV_TYPE_PROFINET;
0177 priv->fbdev.read_area = profi_read_area;
0178 priv->fbdev.write_area = profi_write_area;
0179 priv->fbdev.fieldbus_id_get = profi_id_get;
0180 priv->fbdev.enable_get = profi_enable_get;
0181 priv->fbdev.simple_enable_set = profi_simple_enable;
0182 priv->fbdev.parent = dev;
0183 err = fieldbus_dev_register(&priv->fbdev);
0184 if (err < 0)
0185 return err;
0186 dev_info(dev, "card detected, registered as %s",
0187 dev_name(priv->fbdev.dev));
0188 anybuss_set_drvdata(client, priv);
0189
0190 return 0;
0191 }
0192
0193 static void profinet_remove(struct anybuss_client *client)
0194 {
0195 struct profi_priv *priv = anybuss_get_drvdata(client);
0196
0197 fieldbus_dev_unregister(&priv->fbdev);
0198 }
0199
0200 static struct anybuss_client_driver profinet_driver = {
0201 .probe = profinet_probe,
0202 .remove = profinet_remove,
0203 .driver = {
0204 .name = "hms-profinet",
0205 .owner = THIS_MODULE,
0206 },
0207 .anybus_id = 0x0089,
0208 };
0209
0210 static int __init profinet_init(void)
0211 {
0212 return anybuss_client_driver_register(&profinet_driver);
0213 }
0214 module_init(profinet_init);
0215
0216 static void __exit profinet_exit(void)
0217 {
0218 return anybuss_client_driver_unregister(&profinet_driver);
0219 }
0220 module_exit(profinet_exit);
0221
0222 MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
0223 MODULE_DESCRIPTION("HMS Profinet IRT Driver (Anybus-S)");
0224 MODULE_LICENSE("GPL v2");