Stefan Schmidt wrote on 2010-04-12:
> Hello.
>
> As the patch is already applied this review may came a bit late but I
> think its
> worth mentioning anyway.
>
> On Mon, 2010-04-12 at 13:16, Hennerich, Michael wrote:
> > This patch adds support for the Analog Devices ADF7242 Low Power
> 2.4GHz IEEE802.15.4 Transceiver IC.
> > The ADF7242 features IEEE802.15.4 frame filtering, automatic ACK
> transmission and CSMA-CA with frame retry using an add-on firmware
> blob.
> > This approach allows future extensions to 802.15.4 Standard to be
> supported by simply updating the firmware file.
> > The driver was tested on a Blackfin Processor platform, but should
> work on any embedded platform running Linux.
> > More information as well as the firmware file can be found here:
> > http://docs.blackfin.uclinux.org/doku.php?id=linux-
> kernel:drivers:adf7242
>
> Please cut your commit messages after 72-80 characters. Makes it a lot
> more
> readable.

Thanks for the tip.

>
> > Resend -  since this mail got rejected due to size and failed to get
> list moderator approval afterwards.
> >
> > Signed-off-by: Michael Hennerich <[email protected]>
> >
> >  drivers/ieee802154/Kconfig   |    5 +
> >  drivers/ieee802154/Makefile  |    1 +
> >  drivers/ieee802154/adf7242.c | 1033
> ++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/spi/adf7242.h  |   53 +++
> >  4 files changed, 1092 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig
> > index 186d326..7fe6c2a 100644
> > --- a/drivers/ieee802154/Kconfig
> > +++ b/drivers/ieee802154/Kconfig
> > @@ -44,3 +44,8 @@ config IEEE802154_CC2420
> >         tristate "CC2420 driver"
> >         depends on SPI
> >         depends on  IEEE802154_DRIVERS
> > +
> > +config IEEE802154_ADF7242
> > +       tristate "ADF7242 transceiver driver"
> > +       depends on IEEE802154_DRIVERS && MAC802154
> > +       depends on SPI
> > diff --git a/drivers/ieee802154/Makefile
> b/drivers/ieee802154/Makefile
> > index b54a097..cb33815 100644
> > --- a/drivers/ieee802154/Makefile
> > +++ b/drivers/ieee802154/Makefile
> > @@ -3,5 +3,6 @@ obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
> >  obj-$(CONFIG_IEEE802154_SERIAL) += serial.o
> >  obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
> >  obj-$(CONFIG_IEEE802154_CC2420) += cc2420.o
> > +obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
> >
> >  EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD
> > diff --git a/drivers/ieee802154/adf7242.c
> b/drivers/ieee802154/adf7242.c
> > new file mode 100644
> > index 0000000..b034d9e
> > --- /dev/null
> > +++ b/drivers/ieee802154/adf7242.c
> > @@ -0,0 +1,1033 @@
> > +/*
> > + * Analog Devices ADF7242 Low-Power IEEE 802.15.4 Transceiver
> > + *
> > + * Copyright 2009-2010 Analog Devices Inc.
> > + *
> > + * Licensed under the GPL-2 or later.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/delay.h>
> > +#include <linux/mutex.h>
> > +#include <linux/workqueue.h>
> > +#include <linux/spinlock.h>
> > +#include <linux/firmware.h>
> > +#include <linux/spi/spi.h>
> > +#include <linux/spi/adf7242.h>
> > +
> > +#include <net/mac802154.h>
> > +#include <net/wpan-phy.h>
> > +
> > +/*
> > + * DEBUG LEVEL
> > + *     0       OFF
> > + *     1       INFO
> > + *     2       INFO + TRACE
> > + */
> > +
> > +#define ADF_DEBUG      0
> > +#define DBG(n, args...) do { if (ADF_DEBUG >= (n)) pr_debug(args); }
> while (0)
>
> Why do you need an extra layer over the standard debug macros?

It allows me to set different types of verbosity.
In addition and depending on the Debug Level - these statements get completely 
optimized away by gcc.

>
> You debug is also very chatty. Do you really need a statement everytime
> you
> enter a function? I normally have this for development, but it gets
> distracting
> once the driver starts working.

It appeared to be quite useful - and they are completely turned off by default.

>
> > +#define FIRMWARE       "adf7242_firmware.bin"
> > +#define MAX_POLL_LOOPS 10
> > +
> > +/* All Registers */
> > +
> > +#define REG_EXT_CTRL   0x100 /* RW External LNA/PA and internal PA
> control configuration bits */
> > +#define REG_TX_FSK_TEST 0x101 /* RW TX FSK test mode configuration
> */
> > +#define REG_CCA1       0x105 /* RW RSSI threshold for CCA */
> > +#define REG_CCA2       0x106 /* RW CCA mode configuration */
> > +#define REG_BUFFERCFG  0x107 /* RW RX_BUFFER overwrite control */
> > +#define REG_PKT_CFG    0x108 /* RW FCS evaluation configuration */
> > +#define REG_DELAYCFG0  0x109 /* RW RC_RX command to SFD or sync word
> search delay */
> > +#define REG_DELAYCFG1  0x10A /* RW RC_TX command to TX state */
> > +#define REG_DELAYCFG2  0x10B /* RW Mac delay extention */
> > +#define REG_SYNC_WORD0 0x10C /* RW sync word bits [7:0] of [23:0]
> */
> > +#define REG_SYNC_WORD1 0x10D /* RW sync word bits [15:8] of [23:0]
> */
> > +#define REG_SYNC_WORD2 0x10E /* RW sync word bits [23:16] of [23:0]
> */
> > +#define REG_SYNC_CONFIG        0x10F /* RW sync word configuration
> */
>
> Wrong indentation.

Well - looking at the source I made this patch from, the indention looks right.
This applies to all your highlighted indention problems.
I think the problem is caused by my outlook email client. Shame on me :-)


>
> > +#define REG_RC_CFG     0x13E /* RW RX / TX packet configuration */
> > +#define REG_RC_VAR44   0x13F /* RW RESERVED */
> > +#define REG_CH_FREQ0   0x300 /* RW Channel Frequency Settings - Low
> Byte */
> > +#define REG_CH_FREQ1   0x301 /* RW Channel Frequency Settings -
> Middle Byte */
> > +#define REG_CH_FREQ2   0x302 /* RW Channel Frequency Settings - 2
> MSBs */
> > +#define REG_TX_FD      0x304 /* RW TX Frequency Deviation Register
> */
> > +#define REG_DM_CFG0    0x305 /* RW RX Discriminator BW Register */
> > +#define REG_TX_M       0x306 /* RW TX Mode Register */
> > +#define REG_RX_M       0x307 /* RW RX Mode Register */
> > +#define REG_RRB                0x30C /* R RSSI Readback Register */
> > +#define REG_LRB                0x30D /* R Link Quality Readback
> Register */
> > +#define REG_DR0                0x30E /* RW bits [15:8] of [15:0] for
> data rate setting */
> > +#define REG_DR1                0x30F /* RW bits [7:0] of [15:0] for
> data rate setting */
>
> Also wrong indent.
>
> > +#define REG_PRAMPG     0x313 /* RW RESERVED */
> > +#define REG_TXPB       0x314 /* RW TX Packet Storage Base Address */
> > +#define REG_RXPB       0x315 /* RW RX Packet Storage Base Address */
> > +#define REG_TMR_CFG0   0x316 /* RW Wake up Timer Configuration
> Register - High Byte */
> > +#define REG_TMR_CFG1   0x317 /* RW Wake up Timer Configuration
> Register - Low Byte */
> > +#define REG_TMR_RLD0   0x318 /* RW Wake up Timer Value Register -
> High Byte */
> > +#define REG_TMR_RLD1   0x319 /* RW Wake up Timer Value Register -
> Low Byte */
> > +#define REG_TMR_CTRL   0x31A /* RW Wake up Timer Timeout flag */
> > +#define REG_PD_AUX     0x31E /* RW Battmon enable */
> > +#define REG_GP_CFG     0x32C /* RW GPIO Configuration */
> > +#define REG_GP_OUT     0x32D /* RW GPIO Configuration */
> > +#define REG_GP_IN      0x32E /* R GPIO Configuration */
> > +#define REG_SYNT       0x335 /* RW bandwidth calibration timers */
> > +#define REG_CAL_CFG    0x33D /* RW Calibration Settings */
> > +#define REG_SYNT_CAL   0x371 /* RW Oscillator and Doubler
> Configuration */
> > +#define REG_IIRF_CFG   0x389 /* RW BB Filter Decimation Rate */
> > +#define REG_CDR_CFG    0x38A /* RW CDR kVCO */
> > +#define REG_DM_CFG1    0x38B /* RW Postdemodulator Filter */
> > +#define REG_AGCSTAT    0x38E /* R RXBB Ref Osc Calibration Engine
> Readback */
> > +#define REG_RXCAL0     0x395 /* RW RX BB filter tuning, LSB */
> > +#define REG_RXCAL1     0x396 /* RW RX BB filter tuning, MSB */
> > +#define REG_RXFE_CFG   0x39B /* RW RXBB Ref Osc & RXFE Calibration
> */
> > +#define REG_PA_RR      0x3A7 /* RW Set PA ramp rate */
> > +#define REG_PA_CFG     0x3A8 /* RW PA enable */
> > +#define REG_EXTPA_CFG  0x3A9 /* RW External PA BIAS DAC */
> > +#define REG_EXTPA_MSC  0x3AA /* RW PA Bias Mode */
> > +#define REG_ADC_RBK    0x3AE /* R Readback temp */
> > +#define REG_AGC_CFG1   0x3B2 /* RW GC Parameters */
> > +#define REG_AGC_MAX    0x3B4 /* RW Slew rate  */
> > +#define REG_AGC_CFG2   0x3B6 /* RW RSSI Parameters */
> > +#define REG_AGC_CFG3   0x3B7 /* RW RSSI Parameters */
> > +#define REG_AGC_CFG4   0x3B8 /* RW RSSI Parameters */
> > +#define REG_AGC_CFG5   0x3B9 /* RW RSSI & NDEC Parameters */
> > +#define REG_AGC_CFG6   0x3BA /* RW NDEC Parameters */
> > +#define REG_OCL_CFG1   0x3C4 /* RW OCL System Parameters */
> > +#define REG_IRQ1_EN0   0x3C7 /* RW Interrupt Mask set bits  [7:0] of
> [15:0] for IRQ1 */
> > +#define REG_IRQ1_EN1   0x3C8 /* RW Interrupt Mask set bits  [15:8]
> of [15:0] for IRQ1 */
> > +#define REG_IRQ2_EN0   0x3C9 /* RW Interrupt Mask set bits  [7:0] of
> [15:0] for IRQ2 */
> > +#define REG_IRQ2_EN1   0x3CA /* RW Interrupt Mask set bits  [15:8]
> of [15:0] for IRQ2 */
> > +#define REG_IRQ1_SRC0  0x3CB /* RW Interrupt Source  bits  [7:0] of
> [15:0] for IRQ */
> > +#define REG_IRQ1_SRC1  0x3CC /* RW Interrupt Source bits  [15:8] of
> [15:0] for IRQ */
> > +#define REG_OCL_BW0    0x3D2 /* RW OCL System Parameters */
> > +#define REG_OCL_BW1    0x3D3 /* RW OCL System Parameters */
> > +#define REG_OCL_BW2    0x3D4 /* RW OCL System Parameters */
> > +#define REG_OCL_BW3    0x3D5 /* RW OCL System Parameters */
> > +#define REG_OCL_BW4    0x3D6 /* RW OCL System Parameters */
> > +#define REG_OCL_BWS    0x3D7 /* RW OCL System Parameters */
> > +#define REG_OCL_CFG13  0x3E0 /* RW OCL System Parameters */
> > +#define REG_GP_DRV     0x3E3 /* RW I/O pads Configuration and bg
> trim */
> > +#define REG_BM_CFG     0x3E6 /* RW Battery Monitor Threshold Voltage
> setting */
> > +#define REG_SFD_15_4   0x3F4 /* RW Option to set non standard SFD */
> > +#define REG_AFC_CFG    0x3F7 /* RW AFC mode and polarity */
> > +#define REG_AFC_KI_KP  0x3F8 /* RW AFC ki and kp */
> > +#define REG_AFC_RANGE  0x3F9 /* RW AFC range */
> > +#define REG_AFC_READ   0x3FA /* RW Readback frequency error */
> > +
> > +#define REG_PAN_ID0            0x112
> > +#define REG_PAN_ID1            0x113
> > +#define REG_SHORT_ADDR_0       0x114
> > +#define REG_SHORT_ADDR_1       0x115
> > +#define REG_IEEE_ADDR_0                0x116
> > +#define REG_IEEE_ADDR_1                0x117
> > +#define REG_IEEE_ADDR_2                0x118
> > +#define REG_IEEE_ADDR_3                0x119
> > +#define REG_IEEE_ADDR_4                0x11A
> > +#define REG_IEEE_ADDR_5                0x11B
> > +#define REG_IEEE_ADDR_6                0x11C
> > +#define REG_IEEE_ADDR_7                0x11D
>
> indent
>
> > +#define REG_FFILT_CFG          0x11E
> > +#define REG_AUTO_CFG           0x11F
> > +#define REG_AUTO_TX1           0x120
> > +#define REG_AUTO_TX2           0x121
> > +#define REG_AUTO_STATUS                0x122
>
> indent
>
> > +
> > +/* REG_FFILT_CFG */
> > +#define ACCEPT_BEACON_FRAMES   (1 << 0)
> > +#define ACCEPT_DATA_FRAMES     (1 << 1)
> > +#define ACCEPT_ACK_FRAMES      (1 << 2)
> > +#define ACCEPT_MACCMD_FRAMES   (1 << 3)
> > +#define ACCEPT_RESERVED_FRAMES (1 << 4)
> > +#define ACCEPT_ALL_ADDRESS     (1 << 5)
> > +
> > +/* REG_AUTO_CFG */
> > +#define AUTO_ACK_FRAMEPEND     (1 << 0)
> > +#define IS_PANCOORD            (1 << 1)
> > +#define RX_AUTO_ACK_EN         (1 << 3)
> > +#define CSMA_CA_RX_TURNAROUND  (1 << 4)
> > +
> > +/* REG_AUTO_TX1 */
> > +#define MAX_FRAME_RETRIES(x)   ((x) & 0xF)
> > +#define MAX_CCA_RETRIES(x)     (((x) & 0x7) << 4)
> > +
> > +/* REG_AUTO_TX2 */
> > +#define CSMA_MAX_BE(x)         ((x) & 0xF)
> > +#define CSMA_MIN_BE(x)         (((x) & 0xF) << 4)
> > +
> > +#define CMD_SPI_NOP            0xFF /* No operation. Use for dummy
> writes */
> > +#define CMD_SPI_PKT_WR         0x10 /* Write telegram to the Packet
> RAM starting from the TX packet base address pointer tx_packet_base */
> > +#define CMD_SPI_PKT_RD         0x30 /* Read telegram from the Packet
> RAM starting from RX packet base address pointer rxpb.rx_packet_base */
> > +#define CMD_SPI_MEM_WR(x)      (0x18 + (x >> 8)) /* Write data to
> MCR or Packet RAM sequentially */
> > +#define CMD_SPI_MEM_RD(x)      (0x38 + (x >> 8)) /* Read data from
> MCR or Packet RAM sequentially */
> > +#define CMD_SPI_MEMR_WR(x)     (0x08 + (x >> 8)) /* Write data to
> MCR or Packet RAM as random block */
> > +#define CMD_SPI_MEMR_RD(x)     (0x28 + (x >> 8)) /* Read data from
> MCR or Packet RAM as random block */
> > +#define CMD_SPI_PRAM_WR                0x1E /* Write data
> sequentially to current PRAM page selected */
>
> Even more below. Please check all your defines.
>
> > +#define CMD_RC_SLEEP           0xB1 /* Invoke transition of radio
> controller into SLEEP state */
> > +#define CMD_RC_IDLE            0xB2 /* Invoke transition of radio
> controller into IDLE state */
> > +#define CMD_RC_PHY_RDY         0xB3 /* Invoke transition of radio
> controller into PHY_RDY state */
> > +#define CMD_RC_RX              0xB4 /* Invoke transition of radio
> controller into RX state */
> > +#define CMD_RC_TX              0xB5 /* Invoke transition of radio
> controller into TX state */
> > +#define CMD_RC_MEAS            0xB6 /* Invoke transition of radio
> controller into MEAS state */
> > +#define CMD_RC_CCA             0xB7 /* Invoke Clear channel
> assessment */
> > +#define CMD_RC_CSMACA          0xC1 /* initiates CSMA-CA channel
> access sequence and frame transmission */
> > +
> > +/* STATUS */
> > +
> > +#define STAT_SPI_READY         (1 << 7)
> > +#define STAT_IRQ_STATUS                (1 << 6)
> > +#define STAT_RC_READY          (1 << 5)
> > +#define STAT_CCA_RESULT                (1 << 4)
> > +#define RC_STATUS_IDLE         1
> > +#define RC_STATUS_MEAS         2
> > +#define RC_STATUS_PHY_RDY      3
> > +#define RC_STATUS_RX           4
> > +#define RC_STATUS_TX           5
> > +#define RC_STATUS_MASK         0xF
> > +
> > +/* AUTO_STATUS */
> > +
> > +#define SUCCESS                        0
> > +#define SUCCESS_DATPEND                1
> > +#define FAILURE_CSMACA         2
> > +#define FAILURE_NOACK          3
> > +#define AUTO_STATUS_MASK       0x3
> > +
> > +#define PRAM_PAGESIZE          256
> > +
> > +/* IRQ1 */
> > +
> > +#define IRQ_CCA_COMPLETE       (1 << 0)
> > +#define IRQ_SFD_RX             (1 << 1)
> > +#define IRQ_SFD_TX             (1 << 2)
> > +#define IRQ_RX_PKT_RCVD                (1 << 3)
> > +#define IRQ_TX_PKT_SENT                (1 << 4)
> > +#define IRQ_FRAME_VALID                (1 << 5)
> > +#define IRQ_ADDRESS_VALID      (1 << 6)
> > +#define IRQ_CSMA_CA            (1 << 7)
> > +
> > +#define AUTO_TX_TURNAROUND     (1 << 3)
> > +#define ADDON_EN               (1 << 4)
> > +
> > +struct adf7242_local {
> > +       struct spi_device *spi;
> > +       struct adf7242_platform_data *pdata;
> > +       struct work_struct irqwork;
> > +       struct completion tx_complete;
> > +       struct ieee802154_dev *dev;
> > +       struct mutex bmux;
> > +       spinlock_t lock;
> > +       unsigned irq_disabled:1; /* P: lock */
> > +       unsigned is_tx:1; /* P: lock */
> > +       unsigned mode;
> > +       unsigned tx_irq;
> > +       int tx_stat;
> > +       u8 buf[3];
> > +};
> > +
> > +static int adf7242_status(struct adf7242_local *lp, u8 *stat)
> > +{
> > +       int status;
> > +       struct spi_message msg;
> > +       u8 buf_tx[1], buf_rx[1];
> > +
> > +       struct spi_transfer xfer = {
> > +               .len    = 1,
> > +               .tx_buf = buf_tx,
> > +               .rx_buf = buf_rx,
> > +       };
> > +
> > +       buf_tx[0] = CMD_SPI_NOP;
> > +
> > +       spi_message_init(&msg);
> > +       spi_message_add_tail(&xfer, &msg);
> > +
> > +       mutex_lock(&lp->bmux);
> > +       status = spi_sync(lp->spi, &msg);
> > +       mutex_unlock(&lp->bmux);
> > +
> > +       *stat = buf_rx[0];
> > +
> > +       return status;
> > +}
> > +
> > +static int adf7242_wait_ready(struct adf7242_local *lp)
> > +{
> > +       u8 stat;
> > +       int cnt = 0;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       do {
> > +               adf7242_status(lp, &stat);
> > +               cnt++;
> > +       } while (!(stat & STAT_RC_READY) && (cnt < MAX_POLL_LOOPS));
> > +
> > +       DBG(2, "%s :Exit loops=%d\n", __func__, cnt);
> > +
> > +       return 0;
> > +}
> > +
> > +static int adf7242_wait_status(struct adf7242_local *lp, int status)
> > +{
> > +       u8 stat;
> > +       int cnt = 0;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       do {
> > +               adf7242_status(lp, &stat);
> > +               stat &= RC_STATUS_MASK;
> > +               cnt++;
> > +       } while ((stat != status) && (cnt < MAX_POLL_LOOPS));
> > +
> > +       DBG(2, "%s :Exit loops=%d\n", __func__, cnt);
> > +
> > +       return 0;
> > +}
> > +
> > +static int adf7242_write_fbuf(struct adf7242_local *lp, u8 *data, u8
> len)
> > +{
> > +       u8 *buf = lp->buf;
> > +       int status;
> > +       struct spi_message msg;
> > +       struct spi_transfer xfer_head = {
> > +               .len    = 2,
> > +               .tx_buf = buf,
> > +
> > +       };
> > +       struct spi_transfer xfer_buf = {
> > +               .len    = len,
> > +               .tx_buf = data,
> > +       };
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       adf7242_wait_ready(lp);
> > +
> > +       buf[0] = CMD_SPI_PKT_WR;
> > +       buf[1] = len + 2;
> > +
> > +       spi_message_init(&msg);
> > +       spi_message_add_tail(&xfer_head, &msg);
> > +       spi_message_add_tail(&xfer_buf, &msg);
> > +
> > +       mutex_lock(&lp->bmux);
> > +       status = spi_sync(lp->spi, &msg);
> > +       mutex_unlock(&lp->bmux);
> > +
> > +       DBG(2, "%s :Exit\n", __func__);
> > +       return status;
> > +}
> > +
> > +static int adf7242_read_fbuf(struct adf7242_local *lp,
> > +                            u8 *data, u8 *len, u8 *lqi)
> > +{
> > +       u8 *buf = lp->buf;
> > +       int status;
> > +       struct spi_message msg;
> > +       struct spi_transfer xfer_head = {
> > +               .len    = 3,
> > +               .tx_buf = buf,
> > +               .rx_buf = buf,
> > +
> > +       };
> > +       struct spi_transfer xfer_buf = {
> > +               .len    = *len,
> > +               .rx_buf = data,
> > +       };
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       adf7242_wait_ready(lp);
> > +
> > +       mutex_lock(&lp->bmux);
>
> Move this mutex around spi_sync as in the other functions?

This mutex is supposed to also protect lp->buf.

>
> > +       buf[0] = CMD_SPI_PKT_RD;
> > +       buf[1] = CMD_SPI_NOP;
> > +       buf[2] = 0;             /* PHR */
> > +
> > +       spi_message_init(&msg);
> > +       spi_message_add_tail(&xfer_head, &msg);
> > +       spi_message_add_tail(&xfer_buf, &msg);
> > +
> > +       status = spi_sync(lp->spi, &msg);
> > +
> > +       if (!status) {
> > +               *lqi = data[buf[2] - 1];
> > +               *len = buf[2];  /* PHR */
> > +       }
> > +
> > +       mutex_unlock(&lp->bmux);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +       return status;
> > +}
> > +
> > +static int adf7242_read_reg(struct adf7242_local *lp,
> > +                           u16 addr, u8 *data)
> > +{
> > +       int status;
> > +       struct spi_message msg;
> > +       u8 buf_tx[4], buf_rx[4];
> > +
> > +       struct spi_transfer xfer = {
> > +               .len    = 4,
> > +               .tx_buf = buf_tx,
> > +               .rx_buf = buf_rx,
> > +       };
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       adf7242_wait_ready(lp);
> > +
> > +       mutex_lock(&lp->bmux);
>
> Same for this mutex.
>
> > +       buf_tx[0] = CMD_SPI_MEM_RD(addr);
> > +       buf_tx[1] = addr;
> > +       buf_tx[2] = CMD_SPI_NOP;
> > +       buf_tx[3] = CMD_SPI_NOP;
> > +
> > +       spi_message_init(&msg);
> > +       spi_message_add_tail(&xfer, &msg);
> > +
> > +       status = spi_sync(lp->spi, &msg);
> > +       if (msg.status)
> > +               status = msg.status;
> > +
> > +       if (!status)
> > +               *data = buf_rx[3];
> > +
> > +       mutex_unlock(&lp->bmux);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return status;
> > +}
> > +
> > +static int adf7242_write_reg(struct adf7242_local *lp,
> > +                            u16 addr, u8 data)
> > +{
> > +       int status;
> > +       struct spi_message msg;
> > +       u8 buf_tx[4];
> > +
> > +       struct spi_transfer xfer = {
> > +               .len    = 3,
> > +               .tx_buf = buf_tx,
> > +       };
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       adf7242_wait_ready(lp);
> > +
> > +       buf_tx[0] = CMD_SPI_MEM_WR(addr);
> > +       buf_tx[1] = addr;
> > +       buf_tx[2] = data;
> > +
> > +       spi_message_init(&msg);
> > +       spi_message_add_tail(&xfer, &msg);
> > +
> > +       mutex_lock(&lp->bmux);
> > +       status = spi_sync(lp->spi, &msg);
> > +       mutex_unlock(&lp->bmux);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return status;
> > +}
> > +
> > +static int adf7242_cmd(struct adf7242_local *lp, u8 cmd)
> > +{
> > +       int status;
> > +       struct spi_message msg;
> > +       u8 buf_tx[1];
> > +
> > +       struct spi_transfer xfer = {
> > +               .len    = 1,
> > +               .tx_buf = buf_tx,
> > +       };
> > +
> > +       DBG(2, "%s :Enter CMD=0x%X\n", __func__, cmd);
> > +       adf7242_wait_ready(lp);
> > +
> > +       buf_tx[0] = cmd;
> > +       spi_message_init(&msg);
> > +       spi_message_add_tail(&xfer, &msg);
> > +
> > +       mutex_lock(&lp->bmux);
> > +       status = spi_sync(lp->spi, &msg);
> > +       mutex_unlock(&lp->bmux);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return status;
> > +}
> > +
> > +static int adf7242_upload_firmware(struct adf7242_local *lp,
> > +                                  u8 *data, u16 len)
> > +{
> > +       int status, i, page = 0;
> > +       struct spi_message msg;
> > +       struct spi_transfer xfer_buf = {};
> > +       u8 buf[2];
> > +
> > +       struct spi_transfer xfer_head = {
> > +               .len    = 2,
> > +               .tx_buf = buf,
> > +       };
> > +
> > +       buf[0] = CMD_SPI_PRAM_WR;
> > +       buf[1] = 0;
> > +
> > +       for (i = len; i >= 0 ; i -= PRAM_PAGESIZE) {
> > +               adf7242_write_reg(lp, REG_PRAMPG, page);
> > +
> > +               xfer_buf.len = i >= PRAM_PAGESIZE ? PRAM_PAGESIZE :
> i,
> > +               xfer_buf.tx_buf = &data[page * PRAM_PAGESIZE],
> > +
> > +               spi_message_init(&msg);
> > +               spi_message_add_tail(&xfer_head, &msg);
> > +               spi_message_add_tail(&xfer_buf, &msg);
> > +
> > +               mutex_lock(&lp->bmux);
> > +               status = spi_sync(lp->spi, &msg);
> > +               mutex_unlock(&lp->bmux);
> > +               page++;
> > +       }
> > +
> > +       return status;
> > +}
> > +
> > +static int adf7242_ed(struct ieee802154_dev *dev, u8 *level)
> > +{
> > +       struct adf7242_local *lp = dev->priv;
> > +       int ret;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +#if 0
> > +       adf7242_cmd(lp, CMD_RC_PHY_RDY);
> > +       adf7242_cmd(lp, CMD_RC_CCA);
> > +       adf7242_wait_status(lp, RC_STATUS_PHY_RDY);
> > +#else
>
> Dead code.

I'm not yet 100% decided which one to use.
I'll clean that up some day.

>
> > +       udelay(128);
> > +#endif
> > +       ret = adf7242_read_reg(lp, REG_RRB, level);
> > +       adf7242_cmd(lp, CMD_RC_RX);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return ret;
> > +}
> > +
> > +static int adf7242_start(struct ieee802154_dev *dev)
> > +{
> > +       struct adf7242_local *lp = dev->priv;
> > +       int ret;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       ret = adf7242_cmd(lp, CMD_RC_RX);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return ret;
> > +}
> > +
> > +static void adf7242_stop(struct ieee802154_dev *dev)
> > +{
> > +       struct adf7242_local *lp = dev->priv;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       adf7242_cmd(lp, CMD_RC_PHY_RDY);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +}
> > +
> > +static int adf7242_channel(struct ieee802154_dev *dev, int channel)
> > +{
> > +       struct adf7242_local *lp = dev->priv;
> > +       unsigned long freq;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       DBG(1, "%s :Channel=%d\n", __func__, channel);
> > +
> > +       might_sleep();
> > +
> > +       BUG_ON(channel < 11);
> > +       BUG_ON(channel > 26);
> > +
> > +       freq = (2405 + 5 * (channel - 11)) * 100;
> > +
> > +       adf7242_cmd(lp, CMD_RC_PHY_RDY);
> > +
> > +       adf7242_write_reg(lp, REG_CH_FREQ0, freq);
> > +       adf7242_write_reg(lp, REG_CH_FREQ1, freq >> 8);
> > +       adf7242_write_reg(lp, REG_CH_FREQ2, freq >> 16);
> > +
> > +       adf7242_cmd(lp, CMD_RC_RX);
> > +
> > +       dev->phy->current_channel = channel;
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return 0;
>
> Could be made a void return value as we never return anything useful.

Well - this is a common mac8021511 function!
If you think this function should be better return void - feel free to propose 
an API change.

>
> > +}
> > +
> > +static int adf7242_set_hw_addr_filt(struct ieee802154_dev *dev,
> > +                                   struct ieee802154_hw_addr_filt
> *filt,
> > +                                   unsigned long changed)
> > +{
> > +       struct adf7242_local *lp = dev->priv;
> > +       u8 reg;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +       DBG(1, "%s :Changed=0x%lX\n", __func__, changed);
> > +
> > +       might_sleep();
> > +
> > +       if (changed & IEEE802515_IEEEADDR_CHANGED) {
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_0, filt-
> >ieee_addr[7]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_1, filt-
> >ieee_addr[6]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_2, filt-
> >ieee_addr[5]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_3, filt-
> >ieee_addr[4]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_4, filt-
> >ieee_addr[3]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_5, filt-
> >ieee_addr[2]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_6, filt-
> >ieee_addr[1]);
> > +               adf7242_write_reg(lp, REG_IEEE_ADDR_7, filt-
> >ieee_addr[0]);
> > +       }
> > +
> > +       if (changed & IEEE802515_SADDR_CHANGED) {
> > +               adf7242_write_reg(lp, REG_SHORT_ADDR_0, filt-
> >short_addr);
> > +               adf7242_write_reg(lp, REG_SHORT_ADDR_1, filt-
> >short_addr >> 8);
> > +       }
> > +
> > +       if (changed & IEEE802515_PANID_CHANGED) {
> > +               adf7242_write_reg(lp, REG_PAN_ID0, filt->pan_id);
> > +               adf7242_write_reg(lp, REG_PAN_ID1, filt->pan_id >>
> 8);
> > +       }
> > +
> > +       if (changed & IEEE802515_PANC_CHANGED) {
> > +               adf7242_read_reg(lp, REG_AUTO_CFG, &reg);
> > +               if (filt->pan_coord)
> > +                       reg |= IS_PANCOORD;
> > +               else
> > +                       reg &= ~IS_PANCOORD;
> > +               adf7242_write_reg(lp, REG_AUTO_CFG, reg);
> > +       }
> > +
> > +       DBG(2, "%s :Exit\n", __func__);
> > +       return 0;
>
> Again a candidate for void.

Again - mac802154 convention.


>
> > +}
> > +
> > +static int adf7242_xmit(struct ieee802154_dev *dev, struct sk_buff
> *skb)
> > +{
> > +       struct adf7242_local *lp = dev->priv;
> > +       int ret;
> > +       unsigned long flags;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       spin_lock_irqsave(&lp->lock, flags);
> > +       BUG_ON(lp->is_tx);
> > +       lp->is_tx = 1;
> > +       spin_unlock_irqrestore(&lp->lock, flags);
> > +
> > +       ret = adf7242_write_fbuf(lp, skb->data, skb->len);
> > +       if (ret)
> > +               goto err_rx;
> > +
> > +       if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA) {
> > +               ret = adf7242_cmd(lp, CMD_RC_PHY_RDY);
> > +               ret |= adf7242_cmd(lp, CMD_RC_CSMACA);
> > +       } else {
> > +               ret = adf7242_cmd(lp, CMD_RC_TX);
> > +       }
> > +
> > +       if (ret)
> > +               goto err_rx;
> > +
> > +       ret = wait_for_completion_interruptible(&lp->tx_complete);
> > +
> > +       if (ret < 0)
> > +               goto err_rx;
> > +
> > +       DBG(2, "%s :Exit\n", __func__);
> > +       return ret;
> > +
> > +err_rx:
> > +       spin_lock_irqsave(&lp->lock, flags);
> > +       lp->is_tx = 0;
> > +       spin_unlock_irqrestore(&lp->lock, flags);
> > +       return ret;
> > +}
> > +
> > +static int adf7242_rx(struct adf7242_local *lp)
> > +{
> > +       u8 len = 128;
> > +       u8 lqi = 0;
> > +       int ret;
> > +       struct sk_buff *skb;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       skb = alloc_skb(len, GFP_KERNEL);
> > +       if (!skb)
> > +               return -ENOMEM;
> > +
> > +       ret = adf7242_read_fbuf(lp, skb_put(skb, len), &len, &lqi);
> > +
> > +       adf7242_cmd(lp, CMD_RC_RX);
> > +
> > +       skb_trim(skb, len - 2); /* We do not put RSSI/LQI or CRC into
> the frame */
> > +
> > +       if (len < 2) {
> > +               kfree_skb(skb);
> > +               return -EINVAL;
> > +       }
> > +
> > +       ieee802154_rx_irqsafe(lp->dev, skb, lqi);
> > +
> > +       DBG(1, "%s: %d %d %x\n", __func__, ret, len, lqi);
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return 0;
> > +}
> > +
> > +static struct ieee802154_ops adf7242_ops = {
> > +       .owner = THIS_MODULE,
> > +       .xmit = adf7242_xmit,
> > +       .ed = adf7242_ed,
> > +       .set_channel = adf7242_channel,
> > +       .set_hw_addr_filt = adf7242_set_hw_addr_filt,
> > +       .start = adf7242_start,
> > +       .stop = adf7242_stop,
> > +};
> > +
> > +static void adf7242_irqwork(struct work_struct *work)
> > +{
> > +       struct adf7242_local *lp =
> > +               container_of(work, struct adf7242_local, irqwork);
> > +       u8 irq1, auto_stat = 0, stat = 0;
> > +       int ret;
> > +       unsigned long flags;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       ret = adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
> > +
> > +       DBG(1, "%s IRQ1 = %X:\n%s%s%s%s%s%s%s%s\n", __func__, irq1,
> > +               irq1 & IRQ_CCA_COMPLETE ? "IRQ_CCA_COMPLETE\n" : "",
> > +               irq1 & IRQ_SFD_RX ? "IRQ_SFD_RX\n" : "",
> > +               irq1 & IRQ_SFD_TX ? "IRQ_SFD_TX\n" : "",
> > +               irq1 & IRQ_RX_PKT_RCVD ? "IRQ_RX_PKT_RCVD\n" : "",
> > +               irq1 & IRQ_TX_PKT_SENT ? "IRQ_TX_PKT_SENT\n" : "",
> > +               irq1 & IRQ_CSMA_CA ? "IRQ_CSMA_CA\n" : "",
> > +               irq1 & IRQ_FRAME_VALID ? "IRQ_FRAME_VALID\n" : "",
> > +               irq1 & IRQ_ADDRESS_VALID ? "IRQ_ADDRESS_VALID\n" :
> "");
> > +
> > +       adf7242_status(lp, &stat);
> > +
> > +       DBG(1, "%s STATUS = %X:\n%s\n%s%s%s%s%s\n", __func__, stat,
> > +               stat & STAT_RC_READY ? "RC_READY" : "RC_BUSY",
> > +               (stat & 0xf) == RC_STATUS_IDLE ? "RC_STATUS_IDLE" :
> "",
> > +               (stat & 0xf) == RC_STATUS_MEAS ? "RC_STATUS_MEAS" :
> "",
> > +               (stat & 0xf) == RC_STATUS_PHY_RDY ?
> "RC_STATUS_PHY_RDY" : "",
> > +               (stat & 0xf) == RC_STATUS_RX ? "RC_STATUS_RX" : "",
> > +               (stat & 0xf) == RC_STATUS_TX ? "RC_STATUS_TX" : "");
> > +
> > +       adf7242_write_reg(lp, REG_IRQ1_SRC1, irq1);
> > +
> > +       if (irq1 & IRQ_RX_PKT_RCVD) {
> > +
> > +               /* Wait until ACK is processed */
> > +               if ((lp->mode & ADF_IEEE802154_HW_AACK) &&
> > +                       ((stat & RC_STATUS_MASK) !=
> RC_STATUS_PHY_RDY))
> > +                       adf7242_wait_status(lp, RC_STATUS_PHY_RDY);
> > +
> > +               adf7242_rx(lp);
> > +       }
> > +
> > +       if (irq1 & lp->tx_irq) {
> > +
> > +               if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA) {
> > +                       adf7242_read_reg(lp, REG_AUTO_STATUS,
> &auto_stat);
> > +                       auto_stat &= AUTO_STATUS_MASK;
> > +
> > +                       DBG(1, "%s AUTO_STATUS = %X:\n%s%s%s%s\n",
> > +                        __func__, auto_stat,
> > +                       auto_stat == SUCCESS ? "SUCCESS" : "",
> > +                       auto_stat == SUCCESS_DATPEND ?
> "SUCCESS_DATPEND" : "",
> > +                       auto_stat == FAILURE_CSMACA ?
> "FAILURE_CSMACA" : "",
> > +                       auto_stat == FAILURE_NOACK ? "FAILURE_NOACK"
> : "");
> > +
> > +                       /* save CSMA-CA completion status */
> > +                       lp->tx_stat = auto_stat;
> > +               }
> > +               spin_lock_irqsave(&lp->lock, flags);
> > +               if (lp->is_tx) {
> > +                       lp->is_tx = 0;
> > +                       complete(&lp->tx_complete);
> > +               }
> > +               spin_unlock_irqrestore(&lp->lock, flags);
> > +
> > +               /* in case we just received a frame we are already in
> PHY_RX */
> > +
> > +               if (!(irq1 & IRQ_RX_PKT_RCVD))
> > +                       adf7242_cmd(lp, CMD_RC_RX);
> > +       }
> > +
> > +       spin_lock_irqsave(&lp->lock, flags);
> > +       if (lp->irq_disabled) {
> > +               lp->irq_disabled = 0;
> > +               enable_irq(lp->spi->irq);
> > +       }
> > +       spin_unlock_irqrestore(&lp->lock, flags);
> > +
> > +       DBG(2, "%s :Exit\n", __func__);
> > +}
> > +
> > +static irqreturn_t adf7242_isr(int irq, void *data)
> > +{
> > +       struct adf7242_local *lp = data;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       spin_lock(&lp->lock);
> > +       if (!lp->irq_disabled) {
> > +               disable_irq_nosync(irq);
> > +               lp->irq_disabled = 1;
> > +       }
> > +       spin_unlock(&lp->lock);
> > +
> > +       schedule_work(&lp->irqwork);
> > +
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return IRQ_HANDLED;
> > +}
> > +
> > +
> > +static int adf7242_hw_init(struct adf7242_local *lp)
> > +{
> > +       int ret;
> > +       const struct firmware *fw;
> > +
> > +       DBG(2, "%s :Enter\n", __func__);
> > +
> > +       adf7242_cmd(lp, CMD_RC_IDLE);
> > +
> > +       if (lp->mode) {
> > +               /* get ADF7242 addon firmware
> > +                * build this driver as module
> > +                * and place under /lib/firmware/adf7242_firmware.bin
> > +                */
> > +               ret = request_firmware(&fw, FIRMWARE, &lp->spi->dev);
> > +               if (ret) {
> > +                       dev_err(&lp->spi->dev,
> > +                               "request_firmware() failed with
> %i\n", ret);
> > +                       return ret;
> > +               }
> > +
> > +               adf7242_upload_firmware(lp, (u8 *) fw->data, fw-
> >size);
> > +               release_firmware(fw);
> > +
> > +               adf7242_write_reg(lp, REG_FFILT_CFG,
> > +                       ACCEPT_BEACON_FRAMES |
> > +                       ACCEPT_DATA_FRAMES |
> > +                       ACCEPT_ACK_FRAMES |
> > +                       ACCEPT_MACCMD_FRAMES |
> > +                       (lp->mode & ADF_IEEE802154_PROMISCUOUS_MODE ?
> > +                       ACCEPT_ALL_ADDRESS : 0) |
> > +                       ACCEPT_RESERVED_FRAMES);
> > +
> > +               adf7242_write_reg(lp, REG_AUTO_TX1,
> > +                       MAX_FRAME_RETRIES(lp->pdata-
> >max_frame_retries) |
> > +                       MAX_CCA_RETRIES(lp->pdata->max_cca_retries));
> > +
> > +               adf7242_write_reg(lp, REG_AUTO_TX2,
> > +                       CSMA_MAX_BE(lp->pdata->max_csma_be) |
> > +                       CSMA_MIN_BE(lp->pdata->min_csma_be));
> > +
> > +               adf7242_write_reg(lp, REG_AUTO_CFG,
> > +                       (lp->mode & ADF_IEEE802154_HW_AACK ?
> > +                       RX_AUTO_ACK_EN : 0));
> > +       }
> > +
> > +       adf7242_write_reg(lp, REG_PKT_CFG, lp->mode ? ADDON_EN : 0);
> > +
> > +       adf7242_write_reg(lp, REG_EXTPA_MSC, 0xF1);
> > +       adf7242_write_reg(lp, REG_RXFE_CFG, 0x1D);
> > +       adf7242_write_reg(lp, REG_IRQ1_EN0, 0);
> > +
> > +       adf7242_write_reg(lp, REG_IRQ1_EN1, IRQ_RX_PKT_RCVD | lp-
> >tx_irq);
> > +
> > +       adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
> > +       adf7242_write_reg(lp, REG_IRQ1_SRC0, 0xFF);
> > +
> > +       adf7242_cmd(lp, CMD_RC_PHY_RDY);
> > +
> > +       DBG(2, "%s :Exit\n", __func__);
> > +
> > +       return 0;
> > +}
> > +
> > +static int adf7242_suspend(struct spi_device *spi, pm_message_t
> message)
> > +{
> > +       return 0;
> > +}
> > +
> > +static int adf7242_resume(struct spi_device *spi)
> > +{
> > +       return 0;
> > +}
>
> If you don't implement PM you could just leave it out. At least be
> prepared to
> compile without CONFIG_PM set.

I consider this as reminder to implement suspend/resume.
These functions will be implemented soon.

>
> > +static ssize_t adf7242_show(struct device *dev,
> > +                           struct device_attribute *devattr,
> > +                           char *buf)
> > +{
> > +       struct adf7242_local *lp = dev_get_drvdata(dev);
> > +       u8 stat;
> > +
> > +       adf7242_status(lp, &stat);
> > +
> > +       return sprintf(buf, "STATUS = %X:\n%s\n%s%s%s%s%s\n", stat,
> > +               stat & STAT_RC_READY ? "RC_READY" : "RC_BUSY",
> > +               (stat & 0xf) == RC_STATUS_IDLE ? "RC_STATUS_IDLE" :
> "",
> > +               (stat & 0xf) == RC_STATUS_MEAS ? "RC_STATUS_MEAS" :
> "",
> > +               (stat & 0xf) == RC_STATUS_PHY_RDY ?
> "RC_STATUS_PHY_RDY" : "",
> > +               (stat & 0xf) == RC_STATUS_RX ? "RC_STATUS_RX" : "",
> > +               (stat & 0xf) == RC_STATUS_TX ? "RC_STATUS_TX" : "");
> > +
> > +}
> > +static DEVICE_ATTR(status, 0664, adf7242_show, NULL);
>
> This needs to be dosumented as sysfs ABI. Hard to remove later. Are you
> sure
> that you actually need it?

No - this was just for debug purposes.

>
> > +static struct attribute *adf7242_attributes[] = {
> > +       &dev_attr_status.attr,
> > +       NULL
> > +};
> > +
> > +static const struct attribute_group adf7242_attr_group = {
> > +       .attrs = adf7242_attributes,
> > +};
> > +
> > +static int __devinit adf7242_probe(struct spi_device *spi)
> > +{
> > +       struct adf7242_platform_data *pdata = spi->dev.platform_data;
> > +       struct ieee802154_dev *dev;
> > +       struct adf7242_local *lp;
> > +       int ret;
> > +
> > +       if (!spi->irq) {
> > +               dev_err(&spi->dev, "no IRQ specified\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       if (!pdata) {
> > +               dev_err(&spi->dev, "no platform data?\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       dev = ieee802154_alloc_device(sizeof(*lp), &adf7242_ops);
> > +       if (!dev)
> > +               return -ENOMEM;
> > +
> > +       lp = dev->priv;
> > +       lp->dev = dev;
> > +       lp->spi = spi;
> > +       lp->pdata = pdata;
> > +       lp->mode = pdata->mode;
> > +
> > +       dev->priv = lp;
> > +       dev->parent = &spi->dev;
> > +       dev->extra_tx_headroom = 0;
> > +       /* We do support only 2.4 Ghz */
> > +
> > +       dev->phy->channels_supported[0] = 0x7FFF800;
> > +
> > +       if (!lp->mode) {
> > +               adf7242_ops.set_hw_addr_filt = NULL;
> > +               lp->tx_irq = IRQ_TX_PKT_SENT;
> > +       } else {
> > +               if ((lp->mode & ADF_IEEE802154_PROMISCUOUS_MODE) &&
> > +                       (lp->mode & ADF_IEEE802154_HW_AACK))
> > +                       lp->mode &= ~ADF_IEEE802154_HW_AACK;
> > +
> > +               if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA)
> > +                       lp->tx_irq = IRQ_CSMA_CA;
> > +               else
> > +                       lp->tx_irq = IRQ_TX_PKT_SENT;
> > +       }
> > +
> > +       dev->flags = IEEE802154_HW_OMIT_CKSUM |
> > +                       (lp->mode & ADF_IEEE802154_HW_AACK ?
> > +                       IEEE802154_HW_AACK : 0);
> > +
> > +       mutex_init(&lp->bmux);
> > +       INIT_WORK(&lp->irqwork, adf7242_irqwork);
> > +       spin_lock_init(&lp->lock);
> > +       init_completion(&lp->tx_complete);
> > +
> > +       spi_set_drvdata(spi, lp);
> > +
> > +       ret = adf7242_hw_init(lp);
> > +       if (ret)
> > +               goto err_hw_init;
> > +
> > +       ret = request_irq(spi->irq, adf7242_isr, IRQF_TRIGGER_HIGH,
> > +                       dev_name(&spi->dev), lp);
> > +       if (ret)
> > +               goto err_hw_init;
> > +
> > +       ret = ieee802154_register_device(lp->dev);
> > +       if (ret)
> > +               goto err_irq;
> > +
> > +       dev_set_drvdata(&spi->dev, lp);
> > +
> > +       ret = sysfs_create_group(&spi->dev.kobj,
> &adf7242_attr_group);
> > +       if (ret)
> > +               goto out;
> > +
> > +       dev_info(&spi->dev, "mac802154 IRQ-%d registered\n", spi-
> >irq);
> > +
> > +       return ret;
> > +
> > +out:
> > +       ieee802154_unregister_device(lp->dev);
> > +err_irq:
> > +       free_irq(spi->irq, lp);
> > +       flush_work(&lp->irqwork);
> > +err_hw_init:
> > +       spi_set_drvdata(spi, NULL);
> > +       mutex_destroy(&lp->bmux);
> > +       ieee802154_free_device(lp->dev);
> > +       return ret;
> > +}
> > +
> > +static int __devexit adf7242_remove(struct spi_device *spi)
> > +{
> > +       struct adf7242_local *lp = spi_get_drvdata(spi);
> > +
> > +       ieee802154_unregister_device(lp->dev);
> > +       free_irq(spi->irq, lp);
> > +       flush_work(&lp->irqwork);
> > +       spi_set_drvdata(spi, NULL);
> > +       mutex_destroy(&lp->bmux);
> > +       ieee802154_free_device(lp->dev);
> > +
> > +       return 0;
> > +}
> > +
> > +static struct spi_driver adf7242_driver = {
> > +       .driver = {
> > +               .name   = "adf7242",
> > +               .owner  = THIS_MODULE,
> > +       },
> > +       .probe      = adf7242_probe,
> > +       .remove     = __devexit_p(adf7242_remove),
> > +       .suspend    = adf7242_suspend,
> > +       .resume     = adf7242_resume,
> > +};
> > +
> > +static int __init adf7242_init(void)
> > +{
> > +       return spi_register_driver(&adf7242_driver);
> > +}
> > +module_init(adf7242_init);
> > +
> > +static void __exit adf7242_exit(void)
> > +{
> > +       spi_unregister_driver(&adf7242_driver);
> > +}
> > +module_exit(adf7242_exit);
> > +
> > +MODULE_AUTHOR("Michael Hennerich <[email protected]>");
> > +MODULE_DESCRIPTION("ADF7242 Transceiver Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/spi/adf7242.h
> b/include/linux/spi/adf7242.h
> > new file mode 100644
> > index 0000000..f1bd5f5
> > --- /dev/null
> > +++ b/include/linux/spi/adf7242.h
> > @@ -0,0 +1,53 @@
> > +/*
> > + * Analog Devices ADF7242 Low-Power IEEE 802.15.4 Transceiver
> > + *
> > + * Copyright 2009-2010 Analog Devices Inc.
> > + *
> > + * Licensed under the GPL-2 or later.
> > + */
> > +
> > +#ifndef __LINUX_SPI_ADF7242_H
> > +#define __LINUX_SPI_ADF7242_H
> > +
> > +struct adf7242_platform_data {
> > +
> > +#define ADF_IEEE802154_HW_AACK         (1 << 1)
> > +#define ADF_IEEE802154_AUTO_CSMA_CA    (1 << 2)
> > +#define ADF_IEEE802154_PROMISCUOUS_MODE        (1 << 3)        /* no
> address filtering, turns off HW_AACK */
> > +
> > +       int mode;
> > +
> > +       /*
> > +        * Specifies number of attempts to
> > +        * retransmit unacknowledged
> > +        * frames while in automatic CSMA-CA
> > +        * Tx mode.
> > +        */
> > +       int max_frame_retries;
> > +
> > +       /*
> > +        * Specifies number of attempts to
> > +        * repeat CSMA-CA algorithm prior to
> > +        * cancellation of RC_TX command.
> > +        * Valid range is 0 to 5;
> > +        * 7: CSMA-CA algorithm is off
> > +        */
> > +       int max_cca_retries;
> > +
> > +       /*
> > +        * Specifies the maximum back-off
> > +        * exponent used in the CSMA-CA
> > +        * algorithm; valid range is 4 to 8
> > +        *
> > +        */
> > +       int max_csma_be;
> > +
> > +       /*
> > +        * Specifies the minimum back-off
> > +        * exponent used in the CSMA-CA
> > +        * algorithm; valid range is 0 to
> > +        * csma_max_be
> > +        */
> > +       int min_csma_be;
> > +};
> > +#endif
>
> regards
> Stefan Schmidt

I excuse my broken list reply.
The Outlook Quotefix Macro I typically use on list replies didn't work expected 
on that mail.

Regards,
Michael

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Linux-zigbee-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to