0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/device.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/nfc.h>
0015 #include <linux/netdevice.h>
0016 #include <linux/of.h>
0017 #include <linux/serdev.h>
0018 #include <linux/gpio.h>
0019 #include <linux/of_gpio.h>
0020
0021 #include "phy_common.h"
0022
0023 #define S3FWRN82_NCI_HEADER 3
0024 #define S3FWRN82_NCI_IDX 2
0025 #define NCI_SKB_BUFF_LEN 258
0026
0027 struct s3fwrn82_uart_phy {
0028 struct phy_common common;
0029 struct serdev_device *ser_dev;
0030 struct sk_buff *recv_skb;
0031 };
0032
0033 static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
0034 {
0035 struct s3fwrn82_uart_phy *phy = phy_id;
0036 int err;
0037
0038 err = serdev_device_write(phy->ser_dev,
0039 out->data, out->len,
0040 MAX_SCHEDULE_TIMEOUT);
0041 if (err < 0)
0042 return err;
0043
0044 return 0;
0045 }
0046
0047 static const struct s3fwrn5_phy_ops uart_phy_ops = {
0048 .set_wake = s3fwrn5_phy_set_wake,
0049 .set_mode = s3fwrn5_phy_set_mode,
0050 .get_mode = s3fwrn5_phy_get_mode,
0051 .write = s3fwrn82_uart_write,
0052 };
0053
0054 static int s3fwrn82_uart_read(struct serdev_device *serdev,
0055 const unsigned char *data,
0056 size_t count)
0057 {
0058 struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
0059 size_t i;
0060
0061 for (i = 0; i < count; i++) {
0062 skb_put_u8(phy->recv_skb, *data++);
0063
0064 if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
0065 continue;
0066
0067 if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
0068 < phy->recv_skb->data[S3FWRN82_NCI_IDX])
0069 continue;
0070
0071 s3fwrn5_recv_frame(phy->common.ndev, phy->recv_skb,
0072 phy->common.mode);
0073 phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
0074 if (!phy->recv_skb)
0075 return 0;
0076 }
0077
0078 return i;
0079 }
0080
0081 static const struct serdev_device_ops s3fwrn82_serdev_ops = {
0082 .receive_buf = s3fwrn82_uart_read,
0083 .write_wakeup = serdev_device_write_wakeup,
0084 };
0085
0086 static const struct of_device_id s3fwrn82_uart_of_match[] = {
0087 { .compatible = "samsung,s3fwrn82", },
0088 {},
0089 };
0090 MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
0091
0092 static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
0093 {
0094 struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
0095 struct device_node *np = serdev->dev.of_node;
0096
0097 if (!np)
0098 return -ENODEV;
0099
0100 phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
0101 if (!gpio_is_valid(phy->common.gpio_en))
0102 return -ENODEV;
0103
0104 phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
0105 if (!gpio_is_valid(phy->common.gpio_fw_wake))
0106 return -ENODEV;
0107
0108 return 0;
0109 }
0110
0111 static int s3fwrn82_uart_probe(struct serdev_device *serdev)
0112 {
0113 struct s3fwrn82_uart_phy *phy;
0114 int ret = -ENOMEM;
0115
0116 phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
0117 if (!phy)
0118 goto err_exit;
0119
0120 phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
0121 if (!phy->recv_skb)
0122 goto err_exit;
0123
0124 mutex_init(&phy->common.mutex);
0125 phy->common.mode = S3FWRN5_MODE_COLD;
0126
0127 phy->ser_dev = serdev;
0128 serdev_device_set_drvdata(serdev, phy);
0129 serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
0130 ret = serdev_device_open(serdev);
0131 if (ret) {
0132 dev_err(&serdev->dev, "Unable to open device\n");
0133 goto err_skb;
0134 }
0135
0136 ret = serdev_device_set_baudrate(serdev, 115200);
0137 if (ret != 115200) {
0138 ret = -EINVAL;
0139 goto err_serdev;
0140 }
0141
0142 serdev_device_set_flow_control(serdev, false);
0143
0144 ret = s3fwrn82_uart_parse_dt(serdev);
0145 if (ret < 0)
0146 goto err_serdev;
0147
0148 ret = devm_gpio_request_one(&phy->ser_dev->dev, phy->common.gpio_en,
0149 GPIOF_OUT_INIT_HIGH, "s3fwrn82_en");
0150 if (ret < 0)
0151 goto err_serdev;
0152
0153 ret = devm_gpio_request_one(&phy->ser_dev->dev,
0154 phy->common.gpio_fw_wake,
0155 GPIOF_OUT_INIT_LOW, "s3fwrn82_fw_wake");
0156 if (ret < 0)
0157 goto err_serdev;
0158
0159 ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->ser_dev->dev,
0160 &uart_phy_ops);
0161 if (ret < 0)
0162 goto err_serdev;
0163
0164 return ret;
0165
0166 err_serdev:
0167 serdev_device_close(serdev);
0168 err_skb:
0169 kfree_skb(phy->recv_skb);
0170 err_exit:
0171 return ret;
0172 }
0173
0174 static void s3fwrn82_uart_remove(struct serdev_device *serdev)
0175 {
0176 struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
0177
0178 s3fwrn5_remove(phy->common.ndev);
0179 serdev_device_close(serdev);
0180 kfree_skb(phy->recv_skb);
0181 }
0182
0183 static struct serdev_device_driver s3fwrn82_uart_driver = {
0184 .probe = s3fwrn82_uart_probe,
0185 .remove = s3fwrn82_uart_remove,
0186 .driver = {
0187 .name = "s3fwrn82_uart",
0188 .of_match_table = s3fwrn82_uart_of_match,
0189 },
0190 };
0191
0192 module_serdev_device_driver(s3fwrn82_uart_driver);
0193
0194 MODULE_LICENSE("GPL");
0195 MODULE_DESCRIPTION("UART driver for Samsung NFC");
0196 MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");