Merge tag 'for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[cascardo/linux.git] / drivers / nfc / pn533.c
index 806ab3d..d606f52 100644 (file)
 #define SCM_VENDOR_ID 0x4E6
 #define SCL3711_PRODUCT_ID 0x5591
 
+#define SONY_VENDOR_ID         0x054c
+#define PASORI_PRODUCT_ID      0x02e1
+
+#define PN533_QUIRKS_TYPE_A          BIT(0)
+#define PN533_QUIRKS_TYPE_F          BIT(1)
+#define PN533_QUIRKS_DEP             BIT(2)
+#define PN533_QUIRKS_RAW_EXCHANGE    BIT(3)
+
+#define PN533_DEVICE_STD    0x1
+#define PN533_DEVICE_PASORI 0x2
+
+#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
+                            NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
+                            NFC_PROTO_NFC_DEP_MASK |\
+                            NFC_PROTO_ISO14443_B_MASK)
+
+#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
+                                  NFC_PROTO_MIFARE_MASK | \
+                                  NFC_PROTO_FELICA_MASK | \
+                                  NFC_PROTO_ISO14443_MASK | \
+                                  NFC_PROTO_NFC_DEP_MASK)
+
 static const struct usb_device_id pn533_table[] = {
-       { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) },
-       { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) },
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE,
+         .idVendor             = PN533_VENDOR_ID,
+         .idProduct            = PN533_PRODUCT_ID,
+         .driver_info          = PN533_DEVICE_STD,
+       },
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE,
+         .idVendor             = SCM_VENDOR_ID,
+         .idProduct            = SCL3711_PRODUCT_ID,
+         .driver_info          = PN533_DEVICE_STD,
+       },
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE,
+         .idVendor             = SONY_VENDOR_ID,
+         .idProduct            = PASORI_PRODUCT_ID,
+         .driver_info          = PN533_DEVICE_PASORI,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(usb, pn533_table);
 
+/* How much time we spend listening for initiators */
+#define PN533_LISTEN_TIME 2
+
 /* frame definitions */
 #define PN533_FRAME_TAIL_SIZE 2
 #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
@@ -69,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 #define PN533_CMD_GET_FIRMWARE_VERSION 0x02
 #define PN533_CMD_RF_CONFIGURATION 0x32
 #define PN533_CMD_IN_DATA_EXCHANGE 0x40
+#define PN533_CMD_IN_COMM_THRU     0x42
 #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
 #define PN533_CMD_IN_ATR 0x50
 #define PN533_CMD_IN_RELEASE 0x52
@@ -106,6 +145,7 @@ struct pn533_fw_version {
 /* PN533_CMD_RF_CONFIGURATION */
 #define PN533_CFGITEM_TIMING 0x02
 #define PN533_CFGITEM_MAX_RETRIES 0x05
+#define PN533_CFGITEM_PASORI 0x82
 
 #define PN533_CONFIG_TIMING_102 0xb
 #define PN533_CONFIG_TIMING_204 0xc
@@ -163,6 +203,7 @@ enum {
        PN533_POLL_MOD_424KBPS_FELICA,
        PN533_POLL_MOD_106KBPS_JEWEL,
        PN533_POLL_MOD_847KBPS_B,
+       PN533_LISTEN_MOD,
 
        __PN533_POLL_MOD_AFTER_LAST,
 };
@@ -230,6 +271,9 @@ const struct pn533_poll_modulations poll_mod[] = {
                },
                .len = 3,
        },
+       [PN533_LISTEN_MOD] = {
+               .len = 0,
+       },
 };
 
 /* PN533_CMD_IN_ATR */
@@ -312,23 +356,33 @@ struct pn533 {
 
        struct workqueue_struct *wq;
        struct work_struct cmd_work;
+       struct work_struct poll_work;
        struct work_struct mi_work;
        struct work_struct tg_work;
+       struct timer_list listen_timer;
        struct pn533_frame *wq_in_frame;
        int wq_in_error;
+       int cancel_listen;
 
        pn533_cmd_complete_t cmd_complete;
        void *cmd_complete_arg;
-       struct semaphore cmd_lock;
+       struct mutex cmd_lock;
        u8 cmd;
 
        struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
        u8 poll_mod_count;
        u8 poll_mod_curr;
        u32 poll_protocols;
+       u32 listen_protocols;
+
+       u8 *gb;
+       size_t gb_len;
 
        u8 tgt_available_prots;
        u8 tgt_active_prot;
+       u8 tgt_mode;
+
+       u32 device_type;
 };
 
 struct pn533_frame {
@@ -448,7 +502,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
                                        PN533_FRAME_CMD_PARAMS_LEN(in_frame));
 
        if (rc != -EINPROGRESS)
-               up(&dev->cmd_lock);
+               mutex_unlock(&dev->cmd_lock);
 }
 
 static void pn533_recv_response(struct urb *urb)
@@ -626,7 +680,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
 
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-       if (down_trylock(&dev->cmd_lock))
+       if (!mutex_trylock(&dev->cmd_lock))
                return -EBUSY;
 
        rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
@@ -636,7 +690,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
 
        return 0;
 error:
-       up(&dev->cmd_lock);
+       mutex_unlock(&dev->cmd_lock);
        return rc;
 }
 
@@ -935,7 +989,7 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
        if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
                return -EPROTO;
 
-       nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
+       nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
 
        return 0;
 }
@@ -1006,6 +1060,11 @@ static int pn533_target_found(struct pn533 *dev,
        return 0;
 }
 
+static inline void pn533_poll_next_mod(struct pn533 *dev)
+{
+       dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
+}
+
 static void pn533_poll_reset_mod_list(struct pn533 *dev)
 {
        dev->poll_mod_count = 0;
@@ -1018,107 +1077,52 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
        dev->poll_mod_count++;
 }
 
-static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols)
+static void pn533_poll_create_mod_list(struct pn533 *dev,
+                                      u32 im_protocols, u32 tm_protocols)
 {
        pn533_poll_reset_mod_list(dev);
 
-       if (protocols & NFC_PROTO_MIFARE_MASK
-                                       || protocols & NFC_PROTO_ISO14443_MASK
-                                       || protocols & NFC_PROTO_NFC_DEP_MASK)
+       if (im_protocols & NFC_PROTO_MIFARE_MASK
+           || im_protocols & NFC_PROTO_ISO14443_MASK
+           || im_protocols & NFC_PROTO_NFC_DEP_MASK)
                pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
 
-       if (protocols & NFC_PROTO_FELICA_MASK
-                                       || protocols & NFC_PROTO_NFC_DEP_MASK) {
+       if (im_protocols & NFC_PROTO_FELICA_MASK
+           || im_protocols & NFC_PROTO_NFC_DEP_MASK) {
                pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
                pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
        }
 
-       if (protocols & NFC_PROTO_JEWEL_MASK)
+       if (im_protocols & NFC_PROTO_JEWEL_MASK)
                pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
 
-       if (protocols & NFC_PROTO_ISO14443_MASK)
+       if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
                pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
-}
-
-static void pn533_start_poll_frame(struct pn533_frame *frame,
-                                       struct pn533_poll_modulations *mod)
-{
-
-       pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
 
-       memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
-       frame->datalen += mod->len;
-
-       pn533_tx_frame_finish(frame);
+       if (tm_protocols)
+               pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
 }
 
 static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
-                                               u8 *params, int params_len)
+                                    u8 *params, int params_len)
 {
        struct pn533_poll_response *resp;
-       struct pn533_poll_modulations *next_mod;
        int rc;
 
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-       if (params_len == -ENOENT) {
-               nfc_dev_dbg(&dev->interface->dev, "Polling operation has been"
-                                                               " stopped");
-               goto stop_poll;
-       }
-
-       if (params_len < 0) {
-               nfc_dev_err(&dev->interface->dev, "Error %d when running poll",
-                                                               params_len);
-               goto stop_poll;
-       }
-
        resp = (struct pn533_poll_response *) params;
        if (resp->nbtg) {
                rc = pn533_target_found(dev, resp, params_len);
 
                /* We must stop the poll after a valid target found */
-               if (rc == 0)
-                       goto stop_poll;
-
-               if (rc != -EAGAIN)
-                       nfc_dev_err(&dev->interface->dev, "The target found is"
-                                       " not valid - continuing to poll");
-       }
-
-       dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
-
-       next_mod = dev->poll_mod_active[dev->poll_mod_curr];
-
-       nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)",
-                                                       dev->poll_mod_curr);
-
-       pn533_start_poll_frame(dev->out_frame, next_mod);
-
-       /* Don't need to down the semaphore again */
-       rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
-                               dev->in_maxlen, pn533_start_poll_complete,
-                               NULL, GFP_ATOMIC);
-
-       if (rc == -EPERM) {
-               nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation"
-                                       " because poll has been stopped");
-               goto stop_poll;
-       }
-
-       if (rc) {
-               nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll"
-                                                       " next modulation", rc);
-               goto stop_poll;
+               if (rc == 0) {
+                       pn533_poll_reset_mod_list(dev);
+                       return 0;
+               }
        }
 
-       /* Inform caller function to do not up the semaphore */
-       return -EINPROGRESS;
-
-stop_poll:
-       pn533_poll_reset_mod_list(dev);
-       dev->poll_protocols = 0;
-       return 0;
+       return -EAGAIN;
 }
 
 static int pn533_init_target_frame(struct pn533_frame *frame,
@@ -1126,6 +1130,13 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
 {
        struct pn533_cmd_init_target *cmd;
        size_t cmd_len;
+       u8 felica_params[18] = {0x1, 0xfe, /* DEP */
+                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */
+                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                               0xff, 0xff}; /* System code */
+       u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */
+                              0x0, 0x0, 0x0,
+                              0x40}; /* SEL_RES for DEP */
 
        cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1;
        cmd = kzalloc(cmd_len, GFP_KERNEL);
@@ -1136,17 +1147,33 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
 
        /* DEP support only */
        cmd->mode |= PN533_INIT_TARGET_DEP;
-       get_random_bytes(cmd->nfcid3, 10);
+
+       /* Felica params */
+       memcpy(cmd->felica, felica_params, 18);
+       get_random_bytes(cmd->felica + 2, 6);
+
+       /* NFCID3 */
+       memset(cmd->nfcid3, 0, 10);
+       memcpy(cmd->nfcid3, cmd->felica, 8);
+
+       /* MIFARE params */
+       memcpy(cmd->mifare, mifare_params, 6);
+
+       /* General bytes */
        cmd->gb_len = gb_len;
        memcpy(cmd->gb, gb, gb_len);
+
        /* Len Tk */
        cmd->gb[gb_len] = 0;
 
        memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len);
+
        frame->datalen += cmd_len;
 
        pn533_tx_frame_finish(frame);
 
+       kfree(cmd);
+
        return 0;
 }
 
@@ -1171,6 +1198,8 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
        if (params_len > 0 && params[0] != 0) {
                nfc_tm_deactivated(dev->nfc_dev);
 
+               dev->tgt_mode = 0;
+
                kfree_skb(skb_resp);
                return 0;
        }
@@ -1258,88 +1287,143 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
                return rc;
        }
 
+       dev->tgt_mode = 1;
+
        queue_work(dev->wq, &dev->tg_work);
 
        return 0;
 }
 
-static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
+static void pn533_listen_mode_timer(unsigned long data)
 {
-       struct pn533 *dev = nfc_get_drvdata(nfc_dev);
-       u8 *gb;
-       size_t gb_len;
+       struct pn533 *dev = (struct pn533 *) data;
+
+       nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout");
+
+       /* An ack will cancel the last issued command (poll) */
+       pn533_send_ack(dev, GFP_ATOMIC);
+
+       dev->cancel_listen = 1;
+
+       mutex_unlock(&dev->cmd_lock);
+
+       pn533_poll_next_mod(dev);
+
+       queue_work(dev->wq, &dev->poll_work);
+}
+
+static int pn533_poll_complete(struct pn533 *dev, void *arg,
+                              u8 *params, int params_len)
+{
+       struct pn533_poll_modulations *cur_mod;
        int rc;
 
-       pn533_poll_reset_mod_list(dev);
+       nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-       gb = nfc_get_local_general_bytes(nfc_dev, &gb_len);
-       if (gb == NULL)
-               return -ENOMEM;
+       if (params_len == -ENOENT) {
+               if (dev->poll_mod_count != 0)
+                       return 0;
 
-       rc = pn533_init_target_frame(dev->out_frame, gb, gb_len);
-       if (rc < 0)
-               return rc;
+               nfc_dev_err(&dev->interface->dev,
+                           "Polling operation has been stopped");
 
-       rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
-                                       dev->in_maxlen,
-                                       pn533_init_target_complete,
-                                       NULL, GFP_KERNEL);
+               goto stop_poll;
+       }
 
-       if (rc)
+       if (params_len < 0) {
                nfc_dev_err(&dev->interface->dev,
-                           "Error %d when trying to initiate as a target", rc);
+                           "Error %d when running poll", params_len);
 
-       dev->poll_mod_count++;
+               goto stop_poll;
+       }
 
-       return rc;
+       cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+       if (cur_mod->len == 0) {
+               del_timer(&dev->listen_timer);
+
+               return pn533_init_target_complete(dev, arg, params, params_len);
+       } else {
+               rc = pn533_start_poll_complete(dev, arg, params, params_len);
+               if (!rc)
+                       return rc;
+       }
+
+       pn533_poll_next_mod(dev);
+
+       queue_work(dev->wq, &dev->poll_work);
+
+       return 0;
+
+stop_poll:
+       pn533_poll_reset_mod_list(dev);
+       dev->poll_protocols = 0;
+       return 0;
 }
 
-static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols)
+static void pn533_build_poll_frame(struct pn533 *dev,
+                                  struct pn533_frame *frame,
+                                  struct pn533_poll_modulations *mod)
 {
-       struct pn533 *dev = nfc_get_drvdata(nfc_dev);
-       struct pn533_poll_modulations *start_mod;
-       int rc;
+       nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len);
 
-       if (dev->poll_mod_count) {
-               nfc_dev_err(&dev->interface->dev, "Polling operation already"
-                                                               " active");
-               return -EBUSY;
-       }
+       if (mod->len == 0) {
+               /* Listen mode */
+               pn533_init_target_frame(frame, dev->gb, dev->gb_len);
+       } else {
+               /* Polling mode */
+               pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
 
-       pn533_poll_create_mod_list(dev, protocols);
+               memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
+               frame->datalen += mod->len;
 
-       if (!dev->poll_mod_count) {
-               nfc_dev_err(&dev->interface->dev, "No valid protocols"
-                                                               " specified");
-               rc = -EINVAL;
-               goto error;
+               pn533_tx_frame_finish(frame);
        }
+}
 
-       nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types",
-                                                       dev->poll_mod_count);
+static int pn533_send_poll_frame(struct pn533 *dev)
+{
+       struct pn533_poll_modulations *cur_mod;
+       int rc;
 
-       dev->poll_mod_curr = 0;
-       start_mod = dev->poll_mod_active[dev->poll_mod_curr];
+       cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
 
-       pn533_start_poll_frame(dev->out_frame, start_mod);
+       pn533_build_poll_frame(dev, dev->out_frame, cur_mod);
 
        rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
-                               dev->in_maxlen, pn533_start_poll_complete,
+                               dev->in_maxlen, pn533_poll_complete,
                                NULL, GFP_KERNEL);
+       if (rc)
+               nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc);
 
-       if (rc) {
-               nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
-                                                       " start poll", rc);
-               goto error;
+       return rc;
+}
+
+static void pn533_wq_poll(struct work_struct *work)
+{
+       struct pn533 *dev = container_of(work, struct pn533, poll_work);
+       struct pn533_poll_modulations *cur_mod;
+       int rc;
+
+       cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+       nfc_dev_dbg(&dev->interface->dev,
+                   "%s cancel_listen %d modulation len %d",
+                   __func__, dev->cancel_listen, cur_mod->len);
+
+       if (dev->cancel_listen == 1) {
+               dev->cancel_listen = 0;
+               usb_kill_urb(dev->in_urb);
        }
 
-       dev->poll_protocols = protocols;
+       rc = pn533_send_poll_frame(dev);
+       if (rc)
+               return;
 
-       return 0;
+       if (cur_mod->len == 0 && dev->poll_mod_count > 1)
+               mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);
 
-error:
-       pn533_poll_reset_mod_list(dev);
-       return rc;
+       return;
 }
 
 static int pn533_start_poll(struct nfc_dev *nfc_dev,
@@ -1357,13 +1441,24 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
                return -EBUSY;
        }
 
-       if (im_protocols)
-               return pn533_start_im_poll(nfc_dev, im_protocols);
+       if (dev->tgt_mode) {
+               nfc_dev_err(&dev->interface->dev,
+                           "Cannot poll while already being activated");
+               return -EBUSY;
+       }
+
+       if (tm_protocols) {
+               dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
+               if (dev->gb == NULL)
+                       tm_protocols = 0;
+       }
 
-       if (tm_protocols)
-               return pn533_init_target(nfc_dev, tm_protocols);
+       dev->poll_mod_curr = 0;
+       pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
+       dev->poll_protocols = im_protocols;
+       dev->listen_protocols = tm_protocols;
 
-       return -EINVAL;
+       return pn533_send_poll_frame(dev);
 }
 
 static void pn533_stop_poll(struct nfc_dev *nfc_dev)
@@ -1372,6 +1467,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
 
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
+       del_timer(&dev->listen_timer);
+
        if (!dev->poll_mod_count) {
                nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
                                                                " running");
@@ -1582,6 +1679,20 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        return 0;
 }
 
+static int pn533_mod_to_baud(struct pn533 *dev)
+{
+       switch (dev->poll_mod_curr) {
+       case PN533_POLL_MOD_106KBPS_A:
+               return 0;
+       case PN533_POLL_MOD_212KBPS_FELICA:
+               return 1;
+       case PN533_POLL_MOD_424KBPS_FELICA:
+               return 2;
+       default:
+               return -EINVAL;
+       }
+}
+
 #define PASSIVE_DATA_LEN 5
 static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
                             u8 comm_mode, u8* gb, size_t gb_len)
@@ -1590,7 +1701,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
        struct pn533_cmd_jump_dep *cmd;
        u8 cmd_len, *data_ptr;
        u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
-       int rc;
+       int rc, baud;
 
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
@@ -1606,6 +1717,13 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
                return -EBUSY;
        }
 
+       baud = pn533_mod_to_baud(dev);
+       if (baud < 0) {
+               nfc_dev_err(&dev->interface->dev,
+                           "Invalid curr modulation %d", dev->poll_mod_curr);
+               return baud;
+       }
+
        cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
        if (comm_mode == NFC_COMM_PASSIVE)
                cmd_len += PASSIVE_DATA_LEN;
@@ -1618,7 +1736,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 
        cmd->active = !comm_mode;
        cmd->next = 0;
-       cmd->baud = 2;
+       cmd->baud = baud;
        data_ptr = cmd->data;
        if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) {
                memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN);
@@ -1653,7 +1771,19 @@ out:
 
 static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
 {
-       pn533_deactivate_target(nfc_dev, 0);
+       struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+
+       pn533_poll_reset_mod_list(dev);
+
+       if (dev->tgt_mode || dev->tgt_active_prot) {
+               pn533_send_ack(dev, GFP_KERNEL);
+               usb_kill_urb(dev->in_urb);
+       }
+
+       dev->tgt_active_prot = 0;
+       dev->tgt_mode = 0;
+
+       skb_queue_purge(&dev->resp_q);
 
        return 0;
 }
@@ -1677,13 +1807,30 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
        }
 
        if (target == true) {
-               skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
-               out_frame = (struct pn533_frame *) skb->data;
+               switch (dev->device_type) {
+               case PN533_DEVICE_PASORI:
+                       if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
+                               skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
+                               out_frame = (struct pn533_frame *) skb->data;
+                               pn533_tx_frame_init(out_frame,
+                                                   PN533_CMD_IN_COMM_THRU);
+
+                               break;
+                       }
+
+               default:
+                       skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
+                       out_frame = (struct pn533_frame *) skb->data;
+                       pn533_tx_frame_init(out_frame,
+                                           PN533_CMD_IN_DATA_EXCHANGE);
+                       tg = 1;
+                       memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame),
+                              &tg, sizeof(u8));
+                       out_frame->datalen += sizeof(u8);
+
+                       break;
+               }
 
-               pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
-               tg = 1;
-               memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
-               out_frame->datalen += sizeof(u8);
        } else {
                skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
                out_frame = (struct pn533_frame *) skb->data;
@@ -1884,6 +2031,8 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
        if (params_len > 0 && params[0] != 0) {
                nfc_tm_deactivated(dev->nfc_dev);
 
+               dev->tgt_mode = 0;
+
                return 0;
        }
 
@@ -1982,7 +2131,7 @@ error_cmd:
 
        kfree(arg);
 
-       up(&dev->cmd_lock);
+       mutex_unlock(&dev->cmd_lock);
 }
 
 static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
@@ -2008,7 +2157,28 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
        return rc;
 }
 
-struct nfc_ops pn533_nfc_ops = {
+static int pn533_fw_reset(struct pn533 *dev)
+{
+       int rc;
+       u8 *params;
+
+       nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+       pn533_tx_frame_init(dev->out_frame, 0x18);
+
+       params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame);
+       params[0] = 0x1;
+       dev->out_frame->datalen += 1;
+
+       pn533_tx_frame_finish(dev->out_frame);
+
+       rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+                                      dev->in_maxlen);
+
+       return rc;
+}
+
+static struct nfc_ops pn533_nfc_ops = {
        .dev_up = NULL,
        .dev_down = NULL,
        .dep_link_up = pn533_dep_link_up,
@@ -2021,6 +2191,84 @@ struct nfc_ops pn533_nfc_ops = {
        .tm_send = pn533_tm_send,
 };
 
+static int pn533_setup(struct pn533 *dev)
+{
+       struct pn533_config_max_retries max_retries;
+       struct pn533_config_timing timing;
+       u8 pasori_cfg[3] = {0x08, 0x01, 0x08};
+       int rc;
+
+       switch (dev->device_type) {
+       case PN533_DEVICE_STD:
+               max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
+               max_retries.mx_rty_psl = 2;
+               max_retries.mx_rty_passive_act =
+                       PN533_CONFIG_MAX_RETRIES_NO_RETRY;
+
+               timing.rfu = PN533_CONFIG_TIMING_102;
+               timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
+               timing.dep_timeout = PN533_CONFIG_TIMING_409;
+
+               break;
+
+       case PN533_DEVICE_PASORI:
+               max_retries.mx_rty_atr = 0x2;
+               max_retries.mx_rty_psl = 0x1;
+               max_retries.mx_rty_passive_act =
+                       PN533_CONFIG_MAX_RETRIES_NO_RETRY;
+
+               timing.rfu = PN533_CONFIG_TIMING_102;
+               timing.atr_res_timeout = PN533_CONFIG_TIMING_102;
+               timing.dep_timeout = PN533_CONFIG_TIMING_204;
+
+               break;
+
+       default:
+               nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
+                           dev->device_type);
+               return -EINVAL;
+       }
+
+       rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
+                                    (u8 *)&max_retries, sizeof(max_retries));
+       if (rc) {
+               nfc_dev_err(&dev->interface->dev,
+                           "Error on setting MAX_RETRIES config");
+               return rc;
+       }
+
+
+       rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
+                                    (u8 *)&timing, sizeof(timing));
+       if (rc) {
+               nfc_dev_err(&dev->interface->dev,
+                           "Error on setting RF timings");
+               return rc;
+       }
+
+       switch (dev->device_type) {
+       case PN533_DEVICE_STD:
+               break;
+
+       case PN533_DEVICE_PASORI:
+               pn533_fw_reset(dev);
+
+               rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
+                                            pasori_cfg, 3);
+               if (rc) {
+                       nfc_dev_err(&dev->interface->dev,
+                                   "Error while settings PASORI config");
+                       return rc;
+               }
+
+               pn533_fw_reset(dev);
+
+               break;
+       }
+
+       return 0;
+}
+
 static int pn533_probe(struct usb_interface *interface,
                        const struct usb_device_id *id)
 {
@@ -2028,8 +2276,6 @@ static int pn533_probe(struct usb_interface *interface,
        struct pn533 *dev;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
-       struct pn533_config_max_retries max_retries;
-       struct pn533_config_timing timing;
        int in_endpoint = 0;
        int out_endpoint = 0;
        int rc = -ENOMEM;
@@ -2042,7 +2288,7 @@ static int pn533_probe(struct usb_interface *interface,
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
-       sema_init(&dev->cmd_lock, 1);
+       mutex_init(&dev->cmd_lock);
 
        iface_desc = interface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
@@ -2087,12 +2333,17 @@ static int pn533_probe(struct usb_interface *interface,
        INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
        INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
        INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
+       INIT_WORK(&dev->poll_work, pn533_wq_poll);
        dev->wq = alloc_workqueue("pn533",
                                  WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
                                  1);
        if (dev->wq == NULL)
                goto error;
 
+       init_timer(&dev->listen_timer);
+       dev->listen_timer.data = (unsigned long) dev;
+       dev->listen_timer.function = pn533_listen_mode_timer;
+
        skb_queue_head_init(&dev->resp_q);
 
        usb_set_intfdata(interface, dev);
@@ -2110,10 +2361,22 @@ static int pn533_probe(struct usb_interface *interface,
        nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now"
                                        " attached", fw_ver->ver, fw_ver->rev);
 
-       protocols = NFC_PROTO_JEWEL_MASK
-                       | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
-                       | NFC_PROTO_ISO14443_MASK
-                       | NFC_PROTO_NFC_DEP_MASK;
+       dev->device_type = id->driver_info;
+       switch (dev->device_type) {
+       case PN533_DEVICE_STD:
+               protocols = PN533_ALL_PROTOCOLS;
+               break;
+
+       case PN533_DEVICE_PASORI:
+               protocols = PN533_NO_TYPE_B_PROTOCOLS;
+               break;
+
+       default:
+               nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
+                           dev->device_type);
+               rc = -EINVAL;
+               goto destroy_wq;
+       }
 
        dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
                                           PN533_CMD_DATAEXCH_HEAD_LEN,
@@ -2128,30 +2391,9 @@ static int pn533_probe(struct usb_interface *interface,
        if (rc)
                goto free_nfc_dev;
 
-       max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
-       max_retries.mx_rty_psl = 2;
-       max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY;
-
-       rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
-                               (u8 *) &max_retries, sizeof(max_retries));
-
-       if (rc) {
-               nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
-                                                               " config");
-               goto unregister_nfc_dev;
-       }
-
-       timing.rfu = PN533_CONFIG_TIMING_102;
-       timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
-       timing.dep_timeout = PN533_CONFIG_TIMING_409;
-
-       rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
-                               (u8 *) &timing, sizeof(timing));
-       if (rc) {
-               nfc_dev_err(&dev->interface->dev,
-                           "Error on setting RF timings");
+       rc = pn533_setup(dev);
+       if (rc)
                goto unregister_nfc_dev;
-       }
 
        return 0;
 
@@ -2189,6 +2431,8 @@ static void pn533_disconnect(struct usb_interface *interface)
 
        skb_queue_purge(&dev->resp_q);
 
+       del_timer(&dev->listen_timer);
+
        kfree(dev->in_frame);
        usb_free_urb(dev->in_urb);
        kfree(dev->out_frame);