>From 7601e0cca43dbbd02d5d7e33d3bc858d8acaf384 Mon Sep 17 00:00:00 2001
From: liuxue <liu...@liuxue-laptop.(none)>
Date: Sun, 18 Jul 2010 20:24:24 +0800
Subject: [PATCH] ieee802154/cc2420:Add new functions and etc

* Add cc2420 ram access function
* Add cc2420_ed() and cc2420_set_hw_addr_filt()
* Add sysfs support for debug
* Delete useless comments
* Update my profile
---
 drivers/ieee802154/cc2420.c |  248 +++++++++++++++++++++++++++++++++++++------
 include/linux/spi/cc2420.h  |    2 +-
 2 files changed, 218 insertions(+), 32 deletions(-)

diff --git a/drivers/ieee802154/cc2420.c b/drivers/ieee802154/cc2420.c
index 7839ddb..8a6d9fb 100644
--- a/drivers/ieee802154/cc2420.c
+++ b/drivers/ieee802154/cc2420.c
@@ -14,7 +14,7 @@
  *
  * Author:     Jonathan Cameron <[email protected]>
  *
- * Modified 2010:      liuxue <[email protected]>
+ * Modified 2010:      xue liu <[email protected]>
  */

 #include <linux/kernel.h>
@@ -34,22 +34,45 @@

 #define CC2420_WRITEREG(x) (x)
 #define CC2420_READREG(x) (0x40 | x)
+#define CC2420_RAMADDR(x) ((x & 0x7F) | 0x80)
+#define CC2420_RAMBANK(x) ((x >> 1) & 0xc0)
+#define CC2420_WRITERAM(x) (x)
+#define CC2420_READRAM(x) (0x20 | x)

 #define CC2420_FREQ_MASK               0x3FF
 #define CC2420_ADR_DECODE_MASK 0x0B00
 #define CC2420_FIFOP_THR_MASK  0x003F
 #define CC2420_CRC_MASK                        0x80
+#define CC2420_RSSI_MASK               0x7F
+#define CC2420_FSMSTATE_MASK   0x2F

 #define CC2420_MANFIDLOW       0x233D
 #define CC2420_MANFIDHIGH      0x3000 /* my chip appears to version 3 -
broaden this with testing */

+#define RSSI_OFFSET 45
+
 #define STATE_PDOWN 0
 #define STATE_IDLE  1
-#define STATE_RX_CALIB 2
-#define STATE_RX_CALIB2 40
+#define STATE_RX_CALIBRATE             2
+#define STATE_RX_CALIBRATE2    40

 #define STATE_RX_SFD_SEARCH_MIN 3
 #define STATE_RX_SFD_SEARCH_MAX 6
+#define STATE_RX_FRAME                 16
+#define STATE_RX_FRAME2                        40      /* Same with 
STATE_RX_CALIB2 ? */
+#define STATE_RX_WAIT                  14
+#define STATE_RX_OVERFLOW              17
+#define STATE_TX_ACK_CALIBRATE 48
+#define STATE_TX_ACK_PREAMBLE_MIN      49
+#define STATE_TX_ACK_PREAMBLE_MAX      51
+#define STATE_TX_ACK_MIN                       52
+#define STATE_TX_ACK_MAX                       54
+#define STATE_TX_CALIBRATE                     32
+#define STATE_TX_PREAMBLE_MIN          34
+#define STATE_TX_PREAMBLE_MAX          36
+#define STATE_TX_FRAME_MIN                     37
+#define STATE_TX_FRAME_MAX                     39
+#define STATE_TX_UNDERFLOW                     56

 struct cc2420_local {
        struct cc2420_platform_data *pdata;
@@ -168,10 +191,6 @@ static int cc2420_write_16_bit_reg_partial(struct
cc2420_local *lp,

        lp->buf[0] = CC2420_WRITEREG(addr);

-       //dev_vdbg(&lp->spi->dev, "test: ~(mask >> 8) | (data >> 8) = %x\n",
~(mask >> 8) | (data >> 8));
-       //dev_vdbg(&lp->spi->dev, "test: ~(mask & 0xFF) | (data & 0xFF) =
%x\n", ~(mask & 0xFF) | (data & 0xFF));
-       //lp->buf[1] &= ~(mask >> 8) | (data >> 8);
-       //lp->buf[2] &= ~(mask & 0xFF) | (data & 0xFF);
        lp->buf[1] &= ~(mask >> 8);
        lp->buf[2] &= ~(mask & 0xFF);
        lp->buf[1] |= (mask >> 8) & (data >> 8);
@@ -191,8 +210,7 @@ err_ret:
        return ret;
 }

-static int
-cc2420_channel(struct ieee802154_dev *dev, int channel)
+static int cc2420_channel(struct ieee802154_dev *dev, int channel)
 {
        struct cc2420_local *lp = dev->priv;
        int ret;
@@ -209,8 +227,77 @@ cc2420_channel(struct ieee802154_dev *dev, int channel)
        return ret;
 }

-static int
-cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
+static int cc2420_read_ram(struct cc2420_local *lp, u16 addr, u8 len, u8 *data)
+{
+       int status;
+       struct spi_message msg;
+       struct spi_transfer xfer_head = {
+               .len            = 2,
+               .tx_buf         = lp->buf,
+               .rx_buf         = lp->buf,
+       };
+       struct spi_transfer xfer_buf = {
+               .len            = len,
+               .rx_buf         = data,
+       };
+
+       mutex_lock(&lp->bmux);
+       lp->buf[0] = CC2420_RAMADDR(addr);
+       lp->buf[1] = CC2420_READRAM(CC2420_RAMBANK(addr));
+       dev_dbg(&lp->spi->dev, "read ram addr buf[0] = %02x\n", lp->buf[0]);
+       dev_dbg(&lp->spi->dev, "mem bank buf[1] = %02x\n", lp->buf[1]);
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer_head, &msg);
+       spi_message_add_tail(&xfer_buf, &msg);
+
+       status = spi_sync(lp->spi, &msg);
+       dev_dbg(&lp->spi->dev, "spi status = %d\n", status);
+       if (msg.status)
+               status = msg.status;
+       dev_dbg(&lp->spi->dev, "return cc2420 status buf[0] = %02x\n", 
lp->buf[0]);
+       dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
+
+       mutex_unlock(&lp->bmux);
+
+       return status;
+}
+
+static int cc2420_write_ram(struct cc2420_local *lp, u16 addr, u8
len, u8 *data)
+{
+       int status;
+       struct spi_message msg;
+       struct spi_transfer xfer_head = {
+               .len            = 2,
+               .tx_buf         = lp->buf,
+               .rx_buf         = lp->buf,
+       };
+       struct spi_transfer xfer_buf = {
+               .len            = len,
+               .tx_buf         = data,
+       };
+
+       mutex_lock(&lp->bmux);
+       lp->buf[0] = CC2420_RAMADDR(addr);
+       lp->buf[1] = CC2420_WRITERAM(CC2420_RAMBANK(addr));
+       dev_dbg(&lp->spi->dev, "write ram addr buf[0] = %02x\n", lp->buf[0]);
+       dev_dbg(&lp->spi->dev, "ram bank buf[1] = %02x\n", lp->buf[1]);
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer_head, &msg);
+       spi_message_add_tail(&xfer_buf, &msg);
+
+       status = spi_sync(lp->spi, &msg);
+       dev_dbg(&lp->spi->dev, "spi status = %d\n", status);
+       if (msg.status)
+               status = msg.status;
+       dev_dbg(&lp->spi->dev, "cc2420 status = %02x\n", lp->buf[0]);
+       dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
+
+       mutex_unlock(&lp->bmux);
+       return status;
+}
+
+static int cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
 {
        int status;
        /* Length byte must include FCS even if calculated in hardware */
@@ -250,8 +337,7 @@ cc2420_write_txfifo(struct cc2420_local *lp, u8
*data, u8 len)
        return status;
 }

-static int
-cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8 *len, u8 *lqi)
+static int cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8
*len, u8 *lqi)
 {
        int status;
        struct spi_message msg;
@@ -291,8 +377,7 @@ cc2420_read_rxfifo(struct cc2420_local *lp, u8
*data, u8 *len, u8 *lqi)
 }


-static int
-cc2420_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
+static int cc2420_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
        struct cc2420_local *lp = dev->priv;
        int rc;
@@ -378,23 +463,72 @@ static int cc2420_rx(struct cc2420_local *lp)
        return 0;
 }

-static int
-cc2420_ed(struct ieee802154_dev *dev, u8 *level)
+static int cc2420_set_hw_addr_filt(struct ieee802154_dev *dev,
+                                   struct  ieee802154_hw_addr_filt *filt,
+                                   unsigned long changed)
+{
+       struct cc2420_local *lp = dev->priv;
+       u16 reg;
+
+       might_sleep();
+       
+          dev_dbg(&lp->spi->dev, "cc2420_set_hw_addr_filt\n");
+
+       if (changed & IEEE802515_IEEEADDR_CHANGED) {
+                  cc2420_write_ram(lp, CC2420_RAM_IEEEADR,
+                                                       IEEE802154_ADDR_LEN, 
filt->ieee_addr);
+       }
+
+       if (changed & IEEE802515_SADDR_CHANGED) {
+                  u8 short_addr[2];
+                  short_addr[0] = filt->short_addr & 0xff; /* LSB */
+                  short_addr[1] = filt->short_addr >> 8;       /* MSB */
+                  cc2420_write_ram(lp, CC2420_RAM_SHORTADR, 2, short_addr);
+       }
+
+       if (changed & IEEE802515_PANID_CHANGED) {
+                  u8 panid[2];
+                  panid[0] = filt->pan_id & 0xff;      /* LSB */
+                  panid[1] = filt->pan_id >> 8;        /* MSB */
+                  cc2420_write_ram(lp, CC2420_RAM_PANID, 2, panid);
+       }
+
+       if (changed & IEEE802515_PANC_CHANGED) {
+                  cc2420_read_16_bit_reg(lp, CC2420_MDMCTRL0, &reg);
+                  if (filt->pan_coord)
+                          reg |= 1 << CC2420_MDMCTRL0_PANCRD;
+                  else
+                          reg &= ~(1 << CC2420_MDMCTRL0_PANCRD);
+                  cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
+                                                                               
   reg, 1 << CC2420_MDMCTRL0_PANCRD);
+       }
+
+       return 0;
+}
+
+static int cc2420_ed(struct ieee802154_dev *dev, u8 *level)
 {
        struct cc2420_local *lp = dev->priv;
+       u16 rssi;
+       int ret;
        dev_dbg(&lp->spi->dev, "ed called\n");
-       *level = 0xbe;
-       return 0;
+
+       /* You should know *data present a signed number */     
+       ret = cc2420_read_16_bit_reg(lp, CC2420_RSSI, &rssi);
+       if (ret)
+               return ret;
+       
+       /* P = RSSI_VAL + RSSI_OFFSET[dBm] */
+       *level = (rssi & CC2420_RSSI_MASK) + RSSI_OFFSET;
+       return ret;
 }

-static int
-cc2420_start(struct ieee802154_dev *dev)
+static int cc2420_start(struct ieee802154_dev *dev)
 {
        return cc2420_cmd_strobe(dev->priv, CC2420_SRXON);
 }

-static void
-cc2420_stop(struct ieee802154_dev *dev)
+static void cc2420_stop(struct ieee802154_dev *dev)
 {
        cc2420_cmd_strobe(dev->priv, CC2420_SRFOFF);
 }
@@ -406,6 +540,45 @@ static struct ieee802154_ops cc2420_ops = {
        .start          = cc2420_start,
        .stop           = cc2420_stop,
        .set_channel = cc2420_channel,
+       .set_hw_addr_filt = cc2420_set_hw_addr_filt,
+};
+
+static ssize_t cc2420_show(struct device *dev,
+                           struct device_attribute *devattr,
+                           char *buf)
+{
+    struct cc2420_local *lp = dev_get_drvdata(dev);
+    u16 stat;
+
+    cc2420_read_16_bit_reg(lp, CC2420_FSMSTATE, &stat);
+       stat &= CC2420_FSMSTATE_MASK;
+
+    return sprintf(buf, "Radio Control States =
%X:\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", stat,
+                   stat == STATE_PDOWN ? "POWER DOWN" : "",
+                                  stat == STATE_IDLE ? "IDLE" : "",
+                                  stat == STATE_RX_CALIBRATE ? "RX_CALIBRATE" 
: "",
+                                  stat == STATE_RX_WAIT ? "RX_WAIT" : "",
+                                  stat == STATE_RX_OVERFLOW ? "RX_OVERFLOW" : 
"",
+                                  stat <= STATE_RX_SFD_SEARCH_MAX && stat >=
STATE_RX_SFD_SEARCH_MIN ? "RX_SFD_SEARCH" : "",
+                                  stat <= STATE_TX_ACK_MAX && stat >= 
STATE_TX_ACK_MIN ? "TX_ACK" : "",
+                                  stat <= STATE_TX_ACK_PREAMBLE_MAX && stat >=
STATE_TX_ACK_PREAMBLE_MIN ? "TX_ACK_PREAMBLE" : "",
+                                  stat <= STATE_TX_PREAMBLE_MAX && stat >= 
STATE_TX_PREAMBLE_MIN
? "TX_PREAMBLE" : "",
+                                  stat <= STATE_TX_FRAME_MAX && stat >= 
STATE_TX_FRAME_MIN ?
"TX_FRAME" : "",
+                                  stat == STATE_RX_FRAME ? "RX_FRAME" : "",
+                                  stat == STATE_TX_ACK_CALIBRATE ? 
"TX_ACK_CALIBRATE" : "",
+                                  stat == STATE_TX_CALIBRATE ? "TX_CALIBRATE" 
: "",
+                                  stat == STATE_TX_UNDERFLOW ? "TX_UNDERFLOW" 
: "");
+}
+
+static DEVICE_ATTR(cc2420_fs, 0664, cc2420_show, NULL);
+
+static struct attribute *cc2420_attributes[] = {
+       &dev_attr_cc2420_fs.attr,
+       NULL,
+};
+
+static const struct attribute_group cc2420_attr_group = {
+       .attrs = cc2420_attributes,
 };

 static int cc2420_register(struct cc2420_local *lp)
@@ -431,6 +604,7 @@ static int cc2420_register(struct cc2420_local *lp)
        ret = ieee802154_register_device(lp->dev);
        if (ret)
                goto err_free_device;
+
        return 0;
 err_free_device:
        ieee802154_free_device(lp->dev);
@@ -456,7 +630,6 @@ static irqreturn_t cc2420_isr(int irq, void *data)
        }
        spin_unlock(&lp->lock);

-       /* pin or value? */
        if (irq == lp->sfd_irq)
                schedule_work(&lp->sfd_irqwork);

@@ -678,20 +851,31 @@ static int __devinit cc2420_probe(struct spi_device *spi)
                goto err_free_sfd_irq;
        }

-       dev_dbg(&lp->spi->dev, "Disable hardware address decoding\n");
-       cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
-                                       0, 1 << CC2420_MDMCTRL0_ADRDECODE);
+       /* We have cc2420_set_hw_addr_filt. */
+#if 0
+    dev_dbg(&lp->spi->dev, "Disable hardware address decoding\n");
+    cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
+                                    0, 1 << CC2420_MDMCTRL0_ADRDECODE);
+#endif         
        dev_info(&lp->spi->dev, "Set fifo threshold to 127\n");
        cc2420_write_16_bit_reg_partial(lp, CC2420_IOCFG0, 127,
CC2420_FIFOP_THR_MASK);
        ret = cc2420_register(lp);
        if (ret)
                goto err_free_sfd_irq;

+       dev_set_drvdata(&spi->dev, lp);
+
+       ret = sysfs_create_group(&spi->dev.kobj, &cc2420_attr_group);
+       if (ret) {
+               dev_err(&spi->dev, "sysfs_create_group failed!\n");
+               goto err_free_sfd_irq;
+       }
+
        return 0;
 err_free_sfd_irq:
-       free_irq(gpio_to_irq(lp->pdata->sfd), lp);
+       free_irq(lp->sfd_irq, lp);
 err_free_fifop_irq:
-       free_irq(gpio_to_irq(lp->pdata->fifop), lp);
+       free_irq(lp->fifop_irq, lp);
 err_disable_vreg:
        gpio_set_value(lp->pdata->vreg, 0);
 err_free_gpio_vreg:
@@ -719,8 +903,10 @@ static int __devexit cc2420_remove(struct spi_device *spi)
        struct cc2420_local *lp = spi_get_drvdata(spi);

        cc2420_unregister(lp);
-       free_irq(gpio_to_irq(lp->pdata->fifop), lp);
-       free_irq(gpio_to_irq(lp->pdata->sfd), lp);
+       free_irq(lp->fifop_irq, lp);
+       free_irq(lp->sfd_irq, lp);
+       flush_work(&lp->fifop_irqwork);
+       flush_work(&lp->sfd_irqwork);
        gpio_free(lp->pdata->vreg);
        gpio_free(lp->pdata->reset);
        gpio_free(lp->pdata->sfd);
diff --git a/include/linux/spi/cc2420.h b/include/linux/spi/cc2420.h
index 79b699d..5db3d58 100644
--- a/include/linux/spi/cc2420.h
+++ b/include/linux/spi/cc2420.h
@@ -14,7 +14,7 @@
  *
  * Author:     Jonathan Cameron <[email protected]>
  *
- * Modified 2010:      liuxue <[email protected]>
+ * Modified 2010:      xue liu <[email protected]>
  */

 #ifndef __CC2420_H
-- 
1.7.0.4
From 7601e0cca43dbbd02d5d7e33d3bc858d8acaf384 Mon Sep 17 00:00:00 2001
From: liuxue <liu...@liuxue-laptop.(none)>
Date: Sun, 18 Jul 2010 20:24:24 +0800
Subject: [PATCH] ieee802154/cc2420:Add new functions and etc

* Add cc2420 ram access function
* Add cc2420_ed() and cc2420_set_hw_addr_filt()
* Add sysfs support for debug
* Delete useless comments
* Update my profile
---
 drivers/ieee802154/cc2420.c |  248 +++++++++++++++++++++++++++++++++++++------
 include/linux/spi/cc2420.h  |    2 +-
 2 files changed, 218 insertions(+), 32 deletions(-)

diff --git a/drivers/ieee802154/cc2420.c b/drivers/ieee802154/cc2420.c
index 7839ddb..8a6d9fb 100644
--- a/drivers/ieee802154/cc2420.c
+++ b/drivers/ieee802154/cc2420.c
@@ -14,7 +14,7 @@
  *
  * Author:	Jonathan Cameron <[email protected]>
  *
- * Modified 2010:	liuxue <[email protected]>
+ * Modified 2010:	xue liu <[email protected]>
  */
 
 #include <linux/kernel.h>
@@ -34,22 +34,45 @@
 
 #define CC2420_WRITEREG(x) (x)
 #define CC2420_READREG(x) (0x40 | x)
+#define CC2420_RAMADDR(x) ((x & 0x7F) | 0x80)
+#define CC2420_RAMBANK(x) ((x >> 1) & 0xc0)
+#define CC2420_WRITERAM(x) (x)
+#define CC2420_READRAM(x) (0x20 | x)
 
 #define CC2420_FREQ_MASK 		0x3FF
 #define CC2420_ADR_DECODE_MASK	0x0B00
 #define CC2420_FIFOP_THR_MASK	0x003F
 #define CC2420_CRC_MASK			0x80
+#define CC2420_RSSI_MASK		0x7F
+#define CC2420_FSMSTATE_MASK	0x2F
 
 #define CC2420_MANFIDLOW 	0x233D
 #define CC2420_MANFIDHIGH 	0x3000 /* my chip appears to version 3 - broaden this with testing */
 
+#define RSSI_OFFSET 45
+
 #define STATE_PDOWN 0
 #define STATE_IDLE  1
-#define STATE_RX_CALIB 2
-#define STATE_RX_CALIB2 40
+#define STATE_RX_CALIBRATE 		2
+#define STATE_RX_CALIBRATE2 	40
 
 #define STATE_RX_SFD_SEARCH_MIN 3
 #define STATE_RX_SFD_SEARCH_MAX 6
+#define STATE_RX_FRAME			16
+#define STATE_RX_FRAME2			40	/* Same with STATE_RX_CALIB2 ? */
+#define STATE_RX_WAIT			14
+#define STATE_RX_OVERFLOW		17
+#define STATE_TX_ACK_CALIBRATE	48
+#define STATE_TX_ACK_PREAMBLE_MIN	49
+#define STATE_TX_ACK_PREAMBLE_MAX	51
+#define STATE_TX_ACK_MIN			52
+#define STATE_TX_ACK_MAX			54
+#define STATE_TX_CALIBRATE			32
+#define STATE_TX_PREAMBLE_MIN		34
+#define STATE_TX_PREAMBLE_MAX		36
+#define STATE_TX_FRAME_MIN			37
+#define STATE_TX_FRAME_MAX			39
+#define STATE_TX_UNDERFLOW			56
 
 struct cc2420_local {
 	struct cc2420_platform_data *pdata;
@@ -168,10 +191,6 @@ static int cc2420_write_16_bit_reg_partial(struct cc2420_local *lp,
 
 	lp->buf[0] = CC2420_WRITEREG(addr);
 
-	//dev_vdbg(&lp->spi->dev, "test: ~(mask >> 8) | (data >> 8) = %x\n", ~(mask >> 8) | (data >> 8));
-	//dev_vdbg(&lp->spi->dev, "test: ~(mask & 0xFF) | (data & 0xFF) = %x\n", ~(mask & 0xFF) | (data & 0xFF));
-	//lp->buf[1] &= ~(mask >> 8) | (data >> 8);
-	//lp->buf[2] &= ~(mask & 0xFF) | (data & 0xFF);
 	lp->buf[1] &= ~(mask >> 8);
 	lp->buf[2] &= ~(mask & 0xFF);
 	lp->buf[1] |= (mask >> 8) & (data >> 8);
@@ -191,8 +210,7 @@ err_ret:
 	return ret;
 }
 
-static int
-cc2420_channel(struct ieee802154_dev *dev, int channel)
+static int cc2420_channel(struct ieee802154_dev *dev, int channel)
 {
 	struct cc2420_local *lp = dev->priv;
 	int ret;
@@ -209,8 +227,77 @@ cc2420_channel(struct ieee802154_dev *dev, int channel)
 	return ret;
 }
 
-static int
-cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
+static int cc2420_read_ram(struct cc2420_local *lp, u16 addr, u8 len, u8 *data)
+{
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer_head = {
+		.len		= 2,
+		.tx_buf		= lp->buf,
+		.rx_buf		= lp->buf,
+	};
+	struct spi_transfer xfer_buf = {
+		.len		= len,
+		.rx_buf		= data,
+	};
+
+	mutex_lock(&lp->bmux);
+	lp->buf[0] = CC2420_RAMADDR(addr);
+	lp->buf[1] = CC2420_READRAM(CC2420_RAMBANK(addr));
+	dev_dbg(&lp->spi->dev, "read ram addr buf[0] = %02x\n", lp->buf[0]);
+	dev_dbg(&lp->spi->dev, "mem bank buf[1] = %02x\n", lp->buf[1]);
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer_head, &msg);
+	spi_message_add_tail(&xfer_buf, &msg);
+
+	status = spi_sync(lp->spi, &msg);
+	dev_dbg(&lp->spi->dev, "spi status = %d\n", status);
+	if (msg.status)
+		status = msg.status;
+	dev_dbg(&lp->spi->dev, "return cc2420 status buf[0] = %02x\n", lp->buf[0]);
+	dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
+
+	mutex_unlock(&lp->bmux);
+
+	return status;
+}
+
+static int cc2420_write_ram(struct cc2420_local *lp, u16 addr, u8 len, u8 *data)
+{
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer_head = {
+		.len		= 2,
+		.tx_buf		= lp->buf,
+		.rx_buf		= lp->buf,
+	};
+	struct spi_transfer xfer_buf = {
+		.len		= len,
+		.tx_buf		= data,
+	};
+
+	mutex_lock(&lp->bmux);
+	lp->buf[0] = CC2420_RAMADDR(addr);
+	lp->buf[1] = CC2420_WRITERAM(CC2420_RAMBANK(addr));
+	dev_dbg(&lp->spi->dev, "write ram addr buf[0] = %02x\n", lp->buf[0]);
+	dev_dbg(&lp->spi->dev, "ram bank buf[1] = %02x\n", lp->buf[1]);
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer_head, &msg);
+	spi_message_add_tail(&xfer_buf, &msg);
+
+	status = spi_sync(lp->spi, &msg);
+	dev_dbg(&lp->spi->dev, "spi status = %d\n", status);
+	if (msg.status)
+		status = msg.status;
+	dev_dbg(&lp->spi->dev, "cc2420 status = %02x\n", lp->buf[0]);
+	dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
+
+	mutex_unlock(&lp->bmux);
+	return status;
+}
+
+static int cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
 {
 	int status;
 	/* Length byte must include FCS even if calculated in hardware */
@@ -250,8 +337,7 @@ cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
 	return status;
 }
 
-static int
-cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8 *len, u8 *lqi)
+static int cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8 *len, u8 *lqi)
 {
 	int status;
 	struct spi_message msg;
@@ -291,8 +377,7 @@ cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8 *len, u8 *lqi)
 }
 
 
-static int
-cc2420_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
+static int cc2420_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
 	struct cc2420_local *lp = dev->priv;
 	int rc;
@@ -378,23 +463,72 @@ static int cc2420_rx(struct cc2420_local *lp)
 	return 0;
 }
 
-static int
-cc2420_ed(struct ieee802154_dev *dev, u8 *level)
+static int cc2420_set_hw_addr_filt(struct ieee802154_dev *dev,
+                                   struct  ieee802154_hw_addr_filt *filt,
+                                   unsigned long changed)
+{
+       struct cc2420_local *lp = dev->priv;
+       u16 reg;
+
+       might_sleep();
+	   
+	   dev_dbg(&lp->spi->dev, "cc2420_set_hw_addr_filt\n");
+
+       if (changed & IEEE802515_IEEEADDR_CHANGED) {
+		   cc2420_write_ram(lp, CC2420_RAM_IEEEADR,
+							IEEE802154_ADDR_LEN, filt->ieee_addr);
+       }
+
+       if (changed & IEEE802515_SADDR_CHANGED) {
+		   u8 short_addr[2];
+		   short_addr[0] = filt->short_addr & 0xff; /* LSB */
+		   short_addr[1] = filt->short_addr >> 8;	/* MSB */
+		   cc2420_write_ram(lp, CC2420_RAM_SHORTADR, 2, short_addr);
+       }
+
+       if (changed & IEEE802515_PANID_CHANGED) {
+		   u8 panid[2];
+		   panid[0] = filt->pan_id & 0xff;	/* LSB */
+		   panid[1] = filt->pan_id >> 8;	/* MSB */
+		   cc2420_write_ram(lp, CC2420_RAM_PANID, 2, panid);
+       }
+
+       if (changed & IEEE802515_PANC_CHANGED) {
+		   cc2420_read_16_bit_reg(lp, CC2420_MDMCTRL0, &reg);
+		   if (filt->pan_coord)
+			   reg |= 1 << CC2420_MDMCTRL0_PANCRD;
+		   else
+			   reg &= ~(1 << CC2420_MDMCTRL0_PANCRD);
+		   cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
+										   reg, 1 << CC2420_MDMCTRL0_PANCRD);
+       }
+
+       return 0;
+}
+
+static int cc2420_ed(struct ieee802154_dev *dev, u8 *level)
 {
 	struct cc2420_local *lp = dev->priv;
+	u16 rssi;
+	int ret;
 	dev_dbg(&lp->spi->dev, "ed called\n");
-	*level = 0xbe;
-	return 0;
+
+	/* You should know *data present a signed number */	
+	ret = cc2420_read_16_bit_reg(lp, CC2420_RSSI, &rssi);
+	if (ret)
+		return ret;
+	
+	/* P = RSSI_VAL + RSSI_OFFSET[dBm] */
+	*level = (rssi & CC2420_RSSI_MASK) + RSSI_OFFSET;
+	return ret;
 }
 
-static int
-cc2420_start(struct ieee802154_dev *dev)
+static int cc2420_start(struct ieee802154_dev *dev)
 {
 	return cc2420_cmd_strobe(dev->priv, CC2420_SRXON);
 }
 
-static void
-cc2420_stop(struct ieee802154_dev *dev)
+static void cc2420_stop(struct ieee802154_dev *dev)
 {
 	cc2420_cmd_strobe(dev->priv, CC2420_SRFOFF);
 }
@@ -406,6 +540,45 @@ static struct ieee802154_ops cc2420_ops = {
 	.start 		= cc2420_start,
 	.stop 		= cc2420_stop,
 	.set_channel = cc2420_channel,
+	.set_hw_addr_filt = cc2420_set_hw_addr_filt,
+};
+
+static ssize_t cc2420_show(struct device *dev,
+                           struct device_attribute *devattr,
+                           char *buf)
+{
+    struct cc2420_local *lp = dev_get_drvdata(dev);
+    u16 stat;
+
+    cc2420_read_16_bit_reg(lp, CC2420_FSMSTATE, &stat);
+	stat &= CC2420_FSMSTATE_MASK;
+
+    return sprintf(buf, "Radio Control States = %X:\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", stat,
+                   stat == STATE_PDOWN ? "POWER DOWN" : "",
+				   stat == STATE_IDLE ? "IDLE" : "",
+				   stat == STATE_RX_CALIBRATE ? "RX_CALIBRATE" : "",
+				   stat == STATE_RX_WAIT ? "RX_WAIT" : "",
+				   stat == STATE_RX_OVERFLOW ? "RX_OVERFLOW" : "",
+				   stat <= STATE_RX_SFD_SEARCH_MAX && stat >= STATE_RX_SFD_SEARCH_MIN ? "RX_SFD_SEARCH" : "",
+				   stat <= STATE_TX_ACK_MAX && stat >= STATE_TX_ACK_MIN ? "TX_ACK" : "",
+				   stat <= STATE_TX_ACK_PREAMBLE_MAX && stat >= STATE_TX_ACK_PREAMBLE_MIN ? "TX_ACK_PREAMBLE" : "",
+				   stat <= STATE_TX_PREAMBLE_MAX && stat >= STATE_TX_PREAMBLE_MIN ? "TX_PREAMBLE" : "",
+				   stat <= STATE_TX_FRAME_MAX && stat >= STATE_TX_FRAME_MIN ? "TX_FRAME" : "",
+				   stat == STATE_RX_FRAME ? "RX_FRAME" : "",
+				   stat == STATE_TX_ACK_CALIBRATE ? "TX_ACK_CALIBRATE" : "",
+				   stat == STATE_TX_CALIBRATE ? "TX_CALIBRATE" : "",
+				   stat == STATE_TX_UNDERFLOW ? "TX_UNDERFLOW" : "");
+}
+
+static DEVICE_ATTR(cc2420_fs, 0664, cc2420_show, NULL);
+
+static struct attribute *cc2420_attributes[] = {
+	&dev_attr_cc2420_fs.attr,
+	NULL,
+};
+
+static const struct attribute_group cc2420_attr_group = {
+	.attrs = cc2420_attributes,
 };
 
 static int cc2420_register(struct cc2420_local *lp)
@@ -431,6 +604,7 @@ static int cc2420_register(struct cc2420_local *lp)
 	ret = ieee802154_register_device(lp->dev);
 	if (ret)
 		goto err_free_device;
+
 	return 0;
 err_free_device:
 	ieee802154_free_device(lp->dev);
@@ -456,7 +630,6 @@ static irqreturn_t cc2420_isr(int irq, void *data)
 	}
 	spin_unlock(&lp->lock);
 
-	/* pin or value? */
 	if (irq == lp->sfd_irq)
 		schedule_work(&lp->sfd_irqwork);
 
@@ -678,20 +851,31 @@ static int __devinit cc2420_probe(struct spi_device *spi)
 		goto err_free_sfd_irq;
 	}
 
-	dev_dbg(&lp->spi->dev, "Disable hardware address decoding\n");
-	cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
-					0, 1 << CC2420_MDMCTRL0_ADRDECODE);
+	/* We have cc2420_set_hw_addr_filt. */
+#if 0
+    dev_dbg(&lp->spi->dev, "Disable hardware address decoding\n");
+    cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
+                                    0, 1 << CC2420_MDMCTRL0_ADRDECODE);
+#endif		
 	dev_info(&lp->spi->dev, "Set fifo threshold to 127\n");
 	cc2420_write_16_bit_reg_partial(lp, CC2420_IOCFG0, 127, CC2420_FIFOP_THR_MASK);
 	ret = cc2420_register(lp);
 	if (ret)
 		goto err_free_sfd_irq;
 
+	dev_set_drvdata(&spi->dev, lp);
+
+	ret = sysfs_create_group(&spi->dev.kobj, &cc2420_attr_group);
+	if (ret) {
+		dev_err(&spi->dev, "sysfs_create_group failed!\n");
+		goto err_free_sfd_irq;
+	}
+
 	return 0;
 err_free_sfd_irq:
-	free_irq(gpio_to_irq(lp->pdata->sfd), lp);
+	free_irq(lp->sfd_irq, lp);
 err_free_fifop_irq:
-	free_irq(gpio_to_irq(lp->pdata->fifop), lp);
+	free_irq(lp->fifop_irq, lp);
 err_disable_vreg:
 	gpio_set_value(lp->pdata->vreg, 0);
 err_free_gpio_vreg:
@@ -719,8 +903,10 @@ static int __devexit cc2420_remove(struct spi_device *spi)
 	struct cc2420_local *lp = spi_get_drvdata(spi);
 
 	cc2420_unregister(lp);
-	free_irq(gpio_to_irq(lp->pdata->fifop), lp);
-	free_irq(gpio_to_irq(lp->pdata->sfd), lp);
+	free_irq(lp->fifop_irq, lp);
+	free_irq(lp->sfd_irq, lp);
+	flush_work(&lp->fifop_irqwork);
+	flush_work(&lp->sfd_irqwork);
 	gpio_free(lp->pdata->vreg);
 	gpio_free(lp->pdata->reset);
 	gpio_free(lp->pdata->sfd);
diff --git a/include/linux/spi/cc2420.h b/include/linux/spi/cc2420.h
index 79b699d..5db3d58 100644
--- a/include/linux/spi/cc2420.h
+++ b/include/linux/spi/cc2420.h
@@ -14,7 +14,7 @@
  *
  * Author:	Jonathan Cameron <[email protected]>
  *
- * Modified 2010:	liuxue <[email protected]>
+ * Modified 2010:	xue liu <[email protected]>
  */
 
 #ifndef __CC2420_H
-- 
1.7.0.4

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
Linux-zigbee-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to