]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'spi/for-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 02:40:03 +0000 (13:40 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 02:40:03 +0000 (13:40 +1100)
17 files changed:
1  2 
drivers/input/misc/ad714x-spi.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/tsc2005.c
drivers/media/i2c/s5c73m3/s5c73m3-spi.c
drivers/mfd/arizona-spi.c
drivers/mfd/da9052-spi.c
drivers/mmc/host/mmc_spi.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/sst25l.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ieee802154/mrf24j40.c
drivers/nfc/st-nci/spi.c
drivers/nfc/trf7970a.c
drivers/staging/mt29f_spinand/mt29f_spinand.c
sound/soc/codecs/ad193x-spi.c
sound/soc/codecs/wm8731.c

index c8170f0829624a111f1d8a3a68ad1abe6d6b7445,fea315e76bc8485927652e58198396f27c470078..aac910326447cfcf39a1ae611cdb435150bbd5d4
@@@ -101,13 -101,22 +101,12 @@@ static int ad714x_spi_probe(struct spi_
        return 0;
  }
  
 -static int ad714x_spi_remove(struct spi_device *spi)
 -{
 -      struct ad714x_chip *chip = spi_get_drvdata(spi);
 -
 -      ad714x_remove(chip);
 -
 -      return 0;
 -}
 -
  static struct spi_driver ad714x_spi_driver = {
        .driver = {
                .name   = "ad714x_captouch",
-               .owner  = THIS_MODULE,
                .pm     = &ad714x_spi_pm,
        },
        .probe          = ad714x_spi_probe,
 -      .remove         = ad714x_spi_remove,
  };
  
  module_spi_driver(ad714x_spi_driver);
index 6c676e41fe3c3b418223497e62cfb33e0dee0637,e431cf63a85d6600ea5b18d1b4008e8e5821e497..a61b2153ab8c20fb685d4af7595dba125df6023f
@@@ -529,8 -529,10 +529,8 @@@ static int ads784x_hwmon_register(struc
  
        ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias,
                                                      ts, ads7846_attr_groups);
 -      if (IS_ERR(ts->hwmon))
 -              return PTR_ERR(ts->hwmon);
  
 -      return 0;
 +      return PTR_ERR_OR_ZERO(ts->hwmon);
  }
  
  static void ads784x_hwmon_unregister(struct spi_device *spi,
@@@ -1498,7 -1500,6 +1498,6 @@@ static int ads7846_remove(struct spi_de
  static struct spi_driver ads7846_driver = {
        .driver = {
                .name   = "ads7846",
-               .owner  = THIS_MODULE,
                .pm     = &ads7846_pm,
                .of_match_table = of_match_ptr(ads7846_dt_ids),
        },
index 1bbe64c89a10e6cfcc845bb472fed785acebab7d,f41f23318484d1fb97a427b38e28f15c6e585f57..b9f593dfd2ef8368223e5d7d7d9ca06856afcc8d
@@@ -2,10 -2,9 +2,10 @@@
   * TSC2005 touchscreen driver
   *
   * Copyright (C) 2006-2010 Nokia Corporation
 + * Copyright (C) 2015 QWERTY Embedded Design
 + * Copyright (C) 2015 EMAC Inc.
   *
 - * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
 - * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
 + * Based on original tsc2005.c by Lauri Leukkunen <lauri.leukkunen@nokia.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   * GNU General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 - *
   */
  
 -#include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/input.h>
 -#include <linux/input/touchscreen.h>
 -#include <linux/interrupt.h>
 -#include <linux/delay.h>
 -#include <linux/pm.h>
 -#include <linux/of.h>
  #include <linux/spi/spi.h>
 -#include <linux/spi/tsc2005.h>
 -#include <linux/regulator/consumer.h>
  #include <linux/regmap.h>
 -#include <linux/gpio/consumer.h>
 -
 -/*
 - * The touchscreen interface operates as follows:
 - *
 - * 1) Pen is pressed against the touchscreen.
 - * 2) TSC2005 performs AD conversion.
 - * 3) After the conversion is done TSC2005 drives DAV line down.
 - * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
 - * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
 - *    values.
 - * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
 - *    tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
 - * 7) When the penup timer expires, there have not been touch or DAV interrupts
 - *    during the last 40ms which means the pen has been lifted.
 - *
 - * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
 - * after a configurable period (in ms) of activity. If esd_timeout is 0, the
 - * watchdog is disabled.
 - */
 -
 -/* control byte 1 */
 -#define TSC2005_CMD                   0x80
 -#define TSC2005_CMD_NORMAL            0x00
 -#define TSC2005_CMD_STOP              0x01
 -#define TSC2005_CMD_12BIT             0x04
 -
 -/* control byte 0 */
 -#define TSC2005_REG_READ              0x01 /* R/W access */
 -#define TSC2005_REG_PND0              0x02 /* Power Not Down Control */
 -#define TSC2005_REG_X                 (0x0 << 3)
 -#define TSC2005_REG_Y                 (0x1 << 3)
 -#define TSC2005_REG_Z1                        (0x2 << 3)
 -#define TSC2005_REG_Z2                        (0x3 << 3)
 -#define TSC2005_REG_AUX                       (0x4 << 3)
 -#define TSC2005_REG_TEMP1             (0x5 << 3)
 -#define TSC2005_REG_TEMP2             (0x6 << 3)
 -#define TSC2005_REG_STATUS            (0x7 << 3)
 -#define TSC2005_REG_AUX_HIGH          (0x8 << 3)
 -#define TSC2005_REG_AUX_LOW           (0x9 << 3)
 -#define TSC2005_REG_TEMP_HIGH         (0xA << 3)
 -#define TSC2005_REG_TEMP_LOW          (0xB << 3)
 -#define TSC2005_REG_CFR0              (0xC << 3)
 -#define TSC2005_REG_CFR1              (0xD << 3)
 -#define TSC2005_REG_CFR2              (0xE << 3)
 -#define TSC2005_REG_CONV_FUNC         (0xF << 3)
 -
 -/* configuration register 0 */
 -#define TSC2005_CFR0_PRECHARGE_276US  0x0040
 -#define TSC2005_CFR0_STABTIME_1MS     0x0300
 -#define TSC2005_CFR0_CLOCK_1MHZ               0x1000
 -#define TSC2005_CFR0_RESOLUTION12     0x2000
 -#define TSC2005_CFR0_PENMODE          0x8000
 -#define TSC2005_CFR0_INITVALUE                (TSC2005_CFR0_STABTIME_1MS    | \
 -                                       TSC2005_CFR0_CLOCK_1MHZ      | \
 -                                       TSC2005_CFR0_RESOLUTION12    | \
 -                                       TSC2005_CFR0_PRECHARGE_276US | \
 -                                       TSC2005_CFR0_PENMODE)
 -
 -/* bits common to both read and write of configuration register 0 */
 -#define       TSC2005_CFR0_RW_MASK            0x3fff
 -
 -/* configuration register 1 */
 -#define TSC2005_CFR1_BATCHDELAY_4MS   0x0003
 -#define TSC2005_CFR1_INITVALUE                TSC2005_CFR1_BATCHDELAY_4MS
 -
 -/* configuration register 2 */
 -#define TSC2005_CFR2_MAVE_Z           0x0004
 -#define TSC2005_CFR2_MAVE_Y           0x0008
 -#define TSC2005_CFR2_MAVE_X           0x0010
 -#define TSC2005_CFR2_AVG_7            0x0800
 -#define TSC2005_CFR2_MEDIUM_15                0x3000
 -#define TSC2005_CFR2_INITVALUE                (TSC2005_CFR2_MAVE_X    | \
 -                                       TSC2005_CFR2_MAVE_Y    | \
 -                                       TSC2005_CFR2_MAVE_Z    | \
 -                                       TSC2005_CFR2_MEDIUM_15 | \
 -                                       TSC2005_CFR2_AVG_7)
 -
 -#define MAX_12BIT                     0xfff
 -#define TSC2005_DEF_X_FUZZ            4
 -#define TSC2005_DEF_Y_FUZZ            8
 -#define TSC2005_DEF_P_FUZZ            2
 -#define TSC2005_DEF_RESISTOR          280
 -
 -#define TSC2005_SPI_MAX_SPEED_HZ      10000000
 -#define TSC2005_PENUP_TIME_MS         40
 -
 -static const struct regmap_range tsc2005_writable_ranges[] = {
 -      regmap_reg_range(TSC2005_REG_AUX_HIGH, TSC2005_REG_CFR2),
 -};
 -
 -static const struct regmap_access_table tsc2005_writable_table = {
 -      .yes_ranges = tsc2005_writable_ranges,
 -      .n_yes_ranges = ARRAY_SIZE(tsc2005_writable_ranges),
 -};
 -
 -static struct regmap_config tsc2005_regmap_config = {
 -      .reg_bits = 8,
 -      .val_bits = 16,
 -      .reg_stride = 0x08,
 -      .max_register = 0x78,
 -      .read_flag_mask = TSC2005_REG_READ,
 -      .write_flag_mask = TSC2005_REG_PND0,
 -      .wr_table = &tsc2005_writable_table,
 -      .use_single_rw = true,
 -};
 -
 -struct tsc2005_data {
 -      u16 x;
 -      u16 y;
 -      u16 z1;
 -      u16 z2;
 -} __packed;
 -#define TSC2005_DATA_REGS 4
 -
 -struct tsc2005 {
 -      struct spi_device       *spi;
 -      struct regmap           *regmap;
 -
 -      struct input_dev        *idev;
 -      char                    phys[32];
 -
 -      struct mutex            mutex;
 -
 -      /* raw copy of previous x,y,z */
 -      int                     in_x;
 -      int                     in_y;
 -      int                     in_z1;
 -      int                     in_z2;
 -
 -      spinlock_t              lock;
 -      struct timer_list       penup_timer;
 +#include "tsc200x-core.h"
  
 -      unsigned int            esd_timeout;
 -      struct delayed_work     esd_work;
 -      unsigned long           last_valid_interrupt;
 -
 -      unsigned int            x_plate_ohm;
 -
 -      bool                    opened;
 -      bool                    suspended;
 -
 -      bool                    pen_down;
 -
 -      struct regulator        *vio;
 -
 -      struct gpio_desc        *reset_gpio;
 -      void                    (*set_reset)(bool enable);
 -};
 -
 -static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
 +static int tsc2005_cmd(struct device *dev, u8 cmd)
  {
 -      u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
 +      u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
        struct spi_transfer xfer = {
 -              .tx_buf         = &tx,
 -              .len            = 1,
 -              .bits_per_word  = 8,
 +              .tx_buf         = &tx,
 +              .len            = 1,
 +              .bits_per_word  = 8,
        };
        struct spi_message msg;
 +      struct spi_device *spi = to_spi_device(dev);
        int error;
  
        spi_message_init(&msg);
        spi_message_add_tail(&xfer, &msg);
  
 -      error = spi_sync(ts->spi, &msg);
 +      error = spi_sync(spi, &msg);
        if (error) {
 -              dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n",
 +              dev_err(dev, "%s: failed, command: %x, spi error: %d\n",
                        __func__, cmd, error);
                return error;
        }
        return 0;
  }
  
 -static void tsc2005_update_pen_state(struct tsc2005 *ts,
 -                                   int x, int y, int pressure)
 -{
 -      if (pressure) {
 -              input_report_abs(ts->idev, ABS_X, x);
 -              input_report_abs(ts->idev, ABS_Y, y);
 -              input_report_abs(ts->idev, ABS_PRESSURE, pressure);
 -              if (!ts->pen_down) {
 -                      input_report_key(ts->idev, BTN_TOUCH, !!pressure);
 -                      ts->pen_down = true;
 -              }
 -      } else {
 -              input_report_abs(ts->idev, ABS_PRESSURE, 0);
 -              if (ts->pen_down) {
 -                      input_report_key(ts->idev, BTN_TOUCH, 0);
 -                      ts->pen_down = false;
 -              }
 -      }
 -      input_sync(ts->idev);
 -      dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
 -              pressure);
 -}
 -
 -static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
 -{
 -      struct tsc2005 *ts = _ts;
 -      unsigned long flags;
 -      unsigned int pressure;
 -      struct tsc2005_data tsdata;
 -      int error;
 -
 -      /* read the coordinates */
 -      error = regmap_bulk_read(ts->regmap, TSC2005_REG_X, &tsdata,
 -                               TSC2005_DATA_REGS);
 -      if (unlikely(error))
 -              goto out;
 -
 -      /* validate position */
 -      if (unlikely(tsdata.x > MAX_12BIT || tsdata.y > MAX_12BIT))
 -              goto out;
 -
 -      /* Skip reading if the pressure components are out of range */
 -      if (unlikely(tsdata.z1 == 0 || tsdata.z2 > MAX_12BIT))
 -              goto out;
 -      if (unlikely(tsdata.z1 >= tsdata.z2))
 -              goto out;
 -
 -       /*
 -      * Skip point if this is a pen down with the exact same values as
 -      * the value before pen-up - that implies SPI fed us stale data
 -      */
 -      if (!ts->pen_down &&
 -          ts->in_x == tsdata.x && ts->in_y == tsdata.y &&
 -          ts->in_z1 == tsdata.z1 && ts->in_z2 == tsdata.z2) {
 -              goto out;
 -      }
 -
 -      /*
 -       * At this point we are happy we have a valid and useful reading.
 -       * Remember it for later comparisons. We may now begin downsampling.
 -       */
 -      ts->in_x = tsdata.x;
 -      ts->in_y = tsdata.y;
 -      ts->in_z1 = tsdata.z1;
 -      ts->in_z2 = tsdata.z2;
 -
 -      /* Compute touch pressure resistance using equation #1 */
 -      pressure = tsdata.x * (tsdata.z2 - tsdata.z1) / tsdata.z1;
 -      pressure = pressure * ts->x_plate_ohm / 4096;
 -      if (unlikely(pressure > MAX_12BIT))
 -              goto out;
 -
 -      spin_lock_irqsave(&ts->lock, flags);
 -
 -      tsc2005_update_pen_state(ts, tsdata.x, tsdata.y, pressure);
 -      mod_timer(&ts->penup_timer,
 -                jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
 -
 -      spin_unlock_irqrestore(&ts->lock, flags);
 -
 -      ts->last_valid_interrupt = jiffies;
 -out:
 -      return IRQ_HANDLED;
 -}
 -
 -static void tsc2005_penup_timer(unsigned long data)
 -{
 -      struct tsc2005 *ts = (struct tsc2005 *)data;
 -      unsigned long flags;
 -
 -      spin_lock_irqsave(&ts->lock, flags);
 -      tsc2005_update_pen_state(ts, 0, 0, 0);
 -      spin_unlock_irqrestore(&ts->lock, flags);
 -}
 -
 -static void tsc2005_start_scan(struct tsc2005 *ts)
 -{
 -      regmap_write(ts->regmap, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
 -      regmap_write(ts->regmap, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
 -      regmap_write(ts->regmap, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
 -      tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
 -}
 -
 -static void tsc2005_stop_scan(struct tsc2005 *ts)
 -{
 -      tsc2005_cmd(ts, TSC2005_CMD_STOP);
 -}
 -
 -static void tsc2005_set_reset(struct tsc2005 *ts, bool enable)
 -{
 -      if (ts->reset_gpio)
 -              gpiod_set_value_cansleep(ts->reset_gpio, enable);
 -      else if (ts->set_reset)
 -              ts->set_reset(enable);
 -}
 -
 -/* must be called with ts->mutex held */
 -static void __tsc2005_disable(struct tsc2005 *ts)
 -{
 -      tsc2005_stop_scan(ts);
 -
 -      disable_irq(ts->spi->irq);
 -      del_timer_sync(&ts->penup_timer);
 -
 -      cancel_delayed_work_sync(&ts->esd_work);
 -
 -      enable_irq(ts->spi->irq);
 -}
 -
 -/* must be called with ts->mutex held */
 -static void __tsc2005_enable(struct tsc2005 *ts)
 -{
 -      tsc2005_start_scan(ts);
 -
 -      if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) {
 -              ts->last_valid_interrupt = jiffies;
 -              schedule_delayed_work(&ts->esd_work,
 -                              round_jiffies_relative(
 -                                      msecs_to_jiffies(ts->esd_timeout)));
 -      }
 -
 -}
 -
 -static ssize_t tsc2005_selftest_show(struct device *dev,
 -                                   struct device_attribute *attr,
 -                                   char *buf)
 -{
 -      struct tsc2005 *ts = dev_get_drvdata(dev);
 -      unsigned int temp_high;
 -      unsigned int temp_high_orig;
 -      unsigned int temp_high_test;
 -      bool success = true;
 -      int error;
 -
 -      mutex_lock(&ts->mutex);
 -
 -      /*
 -       * Test TSC2005 communications via temp high register.
 -       */
 -      __tsc2005_disable(ts);
 -
 -      error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
 -      if (error) {
 -              dev_warn(dev, "selftest failed: read error %d\n", error);
 -              success = false;
 -              goto out;
 -      }
 -
 -      temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
 -
 -      error = regmap_write(ts->regmap, TSC2005_REG_TEMP_HIGH, temp_high_test);
 -      if (error) {
 -              dev_warn(dev, "selftest failed: write error %d\n", error);
 -              success = false;
 -              goto out;
 -      }
 -
 -      error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high);
 -      if (error) {
 -              dev_warn(dev, "selftest failed: read error %d after write\n",
 -                       error);
 -              success = false;
 -              goto out;
 -      }
 -
 -      if (temp_high != temp_high_test) {
 -              dev_warn(dev, "selftest failed: %d != %d\n",
 -                       temp_high, temp_high_test);
 -              success = false;
 -      }
 -
 -      /* hardware reset */
 -      tsc2005_set_reset(ts, false);
 -      usleep_range(100, 500); /* only 10us required */
 -      tsc2005_set_reset(ts, true);
 -
 -      if (!success)
 -              goto out;
 -
 -      /* test that the reset really happened */
 -      error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high);
 -      if (error) {
 -              dev_warn(dev, "selftest failed: read error %d after reset\n",
 -                       error);
 -              success = false;
 -              goto out;
 -      }
 -
 -      if (temp_high != temp_high_orig) {
 -              dev_warn(dev, "selftest failed after reset: %d != %d\n",
 -                       temp_high, temp_high_orig);
 -              success = false;
 -      }
 -
 -out:
 -      __tsc2005_enable(ts);
 -      mutex_unlock(&ts->mutex);
 -
 -      return sprintf(buf, "%d\n", success);
 -}
 -
 -static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
 -
 -static struct attribute *tsc2005_attrs[] = {
 -      &dev_attr_selftest.attr,
 -      NULL
 -};
 -
 -static umode_t tsc2005_attr_is_visible(struct kobject *kobj,
 -                                    struct attribute *attr, int n)
 -{
 -      struct device *dev = container_of(kobj, struct device, kobj);
 -      struct tsc2005 *ts = dev_get_drvdata(dev);
 -      umode_t mode = attr->mode;
 -
 -      if (attr == &dev_attr_selftest.attr) {
 -              if (!ts->set_reset && !ts->reset_gpio)
 -                      mode = 0;
 -      }
 -
 -      return mode;
 -}
 -
 -static const struct attribute_group tsc2005_attr_group = {
 -      .is_visible     = tsc2005_attr_is_visible,
 -      .attrs          = tsc2005_attrs,
 -};
 -
 -static void tsc2005_esd_work(struct work_struct *work)
 -{
 -      struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
 -      int error;
 -      unsigned int r;
 -
 -      if (!mutex_trylock(&ts->mutex)) {
 -              /*
 -               * If the mutex is taken, it means that disable or enable is in
 -               * progress. In that case just reschedule the work. If the work
 -               * is not needed, it will be canceled by disable.
 -               */
 -              goto reschedule;
 -      }
 -
 -      if (time_is_after_jiffies(ts->last_valid_interrupt +
 -                                msecs_to_jiffies(ts->esd_timeout)))
 -              goto out;
 -
 -      /* We should be able to read register without disabling interrupts. */
 -      error = regmap_read(ts->regmap, TSC2005_REG_CFR0, &r);
 -      if (!error &&
 -          !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
 -              goto out;
 -      }
 -
 -      /*
 -       * If we could not read our known value from configuration register 0
 -       * then we should reset the controller as if from power-up and start
 -       * scanning again.
 -       */
 -      dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
 -
 -      disable_irq(ts->spi->irq);
 -      del_timer_sync(&ts->penup_timer);
 -
 -      tsc2005_update_pen_state(ts, 0, 0, 0);
 -
 -      tsc2005_set_reset(ts, false);
 -      usleep_range(100, 500); /* only 10us required */
 -      tsc2005_set_reset(ts, true);
 -
 -      enable_irq(ts->spi->irq);
 -      tsc2005_start_scan(ts);
 -
 -out:
 -      mutex_unlock(&ts->mutex);
 -reschedule:
 -      /* re-arm the watchdog */
 -      schedule_delayed_work(&ts->esd_work,
 -                            round_jiffies_relative(
 -                                      msecs_to_jiffies(ts->esd_timeout)));
 -}
 -
 -static int tsc2005_open(struct input_dev *input)
 -{
 -      struct tsc2005 *ts = input_get_drvdata(input);
 -
 -      mutex_lock(&ts->mutex);
 -
 -      if (!ts->suspended)
 -              __tsc2005_enable(ts);
 -
 -      ts->opened = true;
 -
 -      mutex_unlock(&ts->mutex);
 -
 -      return 0;
 -}
 -
 -static void tsc2005_close(struct input_dev *input)
 -{
 -      struct tsc2005 *ts = input_get_drvdata(input);
 -
 -      mutex_lock(&ts->mutex);
 -
 -      if (!ts->suspended)
 -              __tsc2005_disable(ts);
 -
 -      ts->opened = false;
 -
 -      mutex_unlock(&ts->mutex);
 -}
 -
  static int tsc2005_probe(struct spi_device *spi)
  {
 -      const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev);
 -      struct device_node *np = spi->dev.of_node;
 -
 -      struct tsc2005 *ts;
 -      struct input_dev *input_dev;
 -      unsigned int max_x = MAX_12BIT;
 -      unsigned int max_y = MAX_12BIT;
 -      unsigned int max_p = MAX_12BIT;
 -      unsigned int fudge_x = TSC2005_DEF_X_FUZZ;
 -      unsigned int fudge_y = TSC2005_DEF_Y_FUZZ;
 -      unsigned int fudge_p = TSC2005_DEF_P_FUZZ;
 -      unsigned int x_plate_ohm = TSC2005_DEF_RESISTOR;
 -      unsigned int esd_timeout;
        int error;
  
 -      if (!np && !pdata) {
 -              dev_err(&spi->dev, "no platform data\n");
 -              return -ENODEV;
 -      }
 -
 -      if (spi->irq <= 0) {
 -              dev_err(&spi->dev, "no irq\n");
 -              return -ENODEV;
 -      }
 -
 -      if (pdata) {
 -              fudge_x = pdata->ts_x_fudge;
 -              fudge_y = pdata->ts_y_fudge;
 -              fudge_p = pdata->ts_pressure_fudge;
 -              max_x   = pdata->ts_x_max;
 -              max_y   = pdata->ts_y_max;
 -              max_p   = pdata->ts_pressure_max;
 -              x_plate_ohm = pdata->ts_x_plate_ohm;
 -              esd_timeout = pdata->esd_timeout_ms;
 -      } else {
 -              x_plate_ohm = TSC2005_DEF_RESISTOR;
 -              of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
 -              esd_timeout = 0;
 -              of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
 -                                                              &esd_timeout);
 -      }
 -
        spi->mode = SPI_MODE_0;
        spi->bits_per_word = 8;
        if (!spi->max_speed_hz)
        if (error)
                return error;
  
 -      ts = devm_kzalloc(&spi->dev, sizeof(*ts), GFP_KERNEL);
 -      if (!ts)
 -              return -ENOMEM;
 -
 -      input_dev = devm_input_allocate_device(&spi->dev);
 -      if (!input_dev)
 -              return -ENOMEM;
 -
 -      ts->spi = spi;
 -      ts->idev = input_dev;
 -
 -      ts->regmap = devm_regmap_init_spi(spi, &tsc2005_regmap_config);
 -      if (IS_ERR(ts->regmap))
 -              return PTR_ERR(ts->regmap);
 -
 -      ts->x_plate_ohm = x_plate_ohm;
 -      ts->esd_timeout = esd_timeout;
 -
 -      ts->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
 -                                               GPIOD_OUT_HIGH);
 -      if (IS_ERR(ts->reset_gpio)) {
 -              error = PTR_ERR(ts->reset_gpio);
 -              dev_err(&spi->dev, "error acquiring reset gpio: %d\n", error);
 -              return error;
 -      }
 -
 -      ts->vio = devm_regulator_get_optional(&spi->dev, "vio");
 -      if (IS_ERR(ts->vio)) {
 -              error = PTR_ERR(ts->vio);
 -              dev_err(&spi->dev, "vio regulator missing (%d)", error);
 -              return error;
 -      }
 -
 -      if (!ts->reset_gpio && pdata)
 -              ts->set_reset = pdata->set_reset;
 -
 -      mutex_init(&ts->mutex);
 -
 -      spin_lock_init(&ts->lock);
 -      setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
 -
 -      INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
 -
 -      snprintf(ts->phys, sizeof(ts->phys),
 -               "%s/input-ts", dev_name(&spi->dev));
 -
 -      input_dev->name = "TSC2005 touchscreen";
 -      input_dev->phys = ts->phys;
 -      input_dev->id.bustype = BUS_SPI;
 -      input_dev->dev.parent = &spi->dev;
 -      input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
 -      input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 -
 -      input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
 -      input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
 -      input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
 -
 -      if (np)
 -              touchscreen_parse_properties(input_dev, false);
 -
 -      input_dev->open = tsc2005_open;
 -      input_dev->close = tsc2005_close;
 -
 -      input_set_drvdata(input_dev, ts);
 -
 -      /* Ensure the touchscreen is off */
 -      tsc2005_stop_scan(ts);
 -
 -      error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
 -                                        tsc2005_irq_thread,
 -                                        IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 -                                        "tsc2005", ts);
 -      if (error) {
 -              dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
 -              return error;
 -      }
 -
 -      /* enable regulator for DT */
 -      if (ts->vio) {
 -              error = regulator_enable(ts->vio);
 -              if (error)
 -                      return error;
 -      }
 -
 -      dev_set_drvdata(&spi->dev, ts);
 -      error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
 -      if (error) {
 -              dev_err(&spi->dev,
 -                      "Failed to create sysfs attributes, err: %d\n", error);
 -              goto disable_regulator;
 -      }
 -
 -      error = input_register_device(ts->idev);
 -      if (error) {
 -              dev_err(&spi->dev,
 -                      "Failed to register input device, err: %d\n", error);
 -              goto err_remove_sysfs;
 -      }
 -
 -      irq_set_irq_wake(spi->irq, 1);
 -      return 0;
 -
 -err_remove_sysfs:
 -      sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
 -disable_regulator:
 -      if (ts->vio)
 -              regulator_disable(ts->vio);
 -      return error;
 +      return tsc200x_probe(&spi->dev, spi->irq, BUS_SPI,
 +                           devm_regmap_init_spi(spi, &tsc200x_regmap_config),
 +                           tsc2005_cmd);
  }
  
  static int tsc2005_remove(struct spi_device *spi)
  {
 -      struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
 -
 -      sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
 -
 -      if (ts->vio)
 -              regulator_disable(ts->vio);
 -
 -      return 0;
 -}
 -
 -static int __maybe_unused tsc2005_suspend(struct device *dev)
 -{
 -      struct tsc2005 *ts = dev_get_drvdata(dev);
 -
 -      mutex_lock(&ts->mutex);
 -
 -      if (!ts->suspended && ts->opened)
 -              __tsc2005_disable(ts);
 -
 -      ts->suspended = true;
 -
 -      mutex_unlock(&ts->mutex);
 -
 -      return 0;
 -}
 -
 -static int __maybe_unused tsc2005_resume(struct device *dev)
 -{
 -      struct tsc2005 *ts = dev_get_drvdata(dev);
 -
 -      mutex_lock(&ts->mutex);
 -
 -      if (ts->suspended && ts->opened)
 -              __tsc2005_enable(ts);
 -
 -      ts->suspended = false;
 -
 -      mutex_unlock(&ts->mutex);
 -
 -      return 0;
 +      return tsc200x_remove(&spi->dev);
  }
  
 -static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
 -
  static struct spi_driver tsc2005_driver = {
        .driver = {
                .name   = "tsc2005",
-               .owner  = THIS_MODULE,
 -              .pm     = &tsc2005_pm_ops,
 +              .pm     = &tsc200x_pm_ops,
        },
        .probe  = tsc2005_probe,
        .remove = tsc2005_remove,
  };
 -
  module_spi_driver(tsc2005_driver);
  
 -MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
 +MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
  MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("spi:tsc2005");
index 17ac4417fb176a50518ac57e9c09e7b1c415486f,d744b170c9ed64c7b18ce6e12db2a7b880a911fa..72ef9f936e6ceb13ad7b94e5c998ffa9543700e8
@@@ -31,7 -31,6 +31,7 @@@ static const struct of_device_id s5c73m
        { .compatible = "samsung,s5c73m3" },
        { }
  };
 +MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids);
  
  enum spi_direction {
        SPI_DIR_RX,
@@@ -150,7 -149,6 +150,6 @@@ int s5c73m3_register_spi_driver(struct 
        spidrv->remove = s5c73m3_spi_remove;
        spidrv->probe = s5c73m3_spi_probe;
        spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
-       spidrv->driver.owner = THIS_MODULE;
        spidrv->driver.of_match_table = s5c73m3_spi_ids;
  
        return spi_register_driver(spidrv);
index 8cffb1cfe73d112052859a30c47ad413508c878a,03d62f7b47205cbd5c8db2bce120a8c5d124b84d..befbc89bfd3456c210d736d2ad295c646a2bd4fc
@@@ -27,7 -27,7 +27,7 @@@ static int arizona_spi_probe(struct spi
  {
        const struct spi_device_id *id = spi_get_device_id(spi);
        struct arizona *arizona;
 -      const struct regmap_config *regmap_config;
 +      const struct regmap_config *regmap_config = NULL;
        unsigned long type;
        int ret;
  
                type = id->driver_data;
  
        switch (type) {
 -#ifdef CONFIG_MFD_WM5102
        case WM5102:
 -              regmap_config = &wm5102_spi_regmap;
 +              if (IS_ENABLED(CONFIG_MFD_WM5102))
 +                      regmap_config = &wm5102_spi_regmap;
                break;
 -#endif
 -#ifdef CONFIG_MFD_WM5110
        case WM5110:
        case WM8280:
 -              regmap_config = &wm5110_spi_regmap;
 +              if (IS_ENABLED(CONFIG_MFD_WM5110))
 +                      regmap_config = &wm5110_spi_regmap;
                break;
 -#endif
        default:
 -              dev_err(&spi->dev, "Unknown device type %ld\n",
 -                      id->driver_data);
 +              dev_err(&spi->dev, "Unknown device type %ld\n", type);
 +              return -EINVAL;
 +      }
 +
 +      if (!regmap_config) {
 +              dev_err(&spi->dev,
 +                      "No kernel support for device type %ld\n", type);
                return -EINVAL;
        }
  
@@@ -69,7 -66,7 +69,7 @@@
                return ret;
        }
  
 -      arizona->type = id->driver_data;
 +      arizona->type = type;
        arizona->dev = &spi->dev;
        arizona->irq = spi->irq;
  
@@@ -96,7 -93,6 +96,6 @@@ MODULE_DEVICE_TABLE(spi, arizona_spi_id
  static struct spi_driver arizona_spi_driver = {
        .driver = {
                .name   = "arizona",
-               .owner  = THIS_MODULE,
                .pm     = &arizona_pm_ops,
                .of_match_table = of_match_ptr(arizona_of_match),
        },
diff --combined drivers/mfd/da9052-spi.c
index 0f5e2c2858c18deebfa65d00529fd61eead11620,71b89dd4e8de26297b5487cd2c42c1e19dcbcba3..b9ea1b27db642d452b39ceaf1a5a96fa9657804c
@@@ -56,7 -56,11 +56,7 @@@ static int da9052_spi_probe(struct spi_
                return ret;
        }
  
 -      ret = da9052_device_init(da9052, id->driver_data);
 -      if (ret != 0)
 -              return ret;
 -
 -      return 0;
 +      return da9052_device_init(da9052, id->driver_data);
  }
  
  static int da9052_spi_remove(struct spi_device *spi)
@@@ -82,7 -86,6 +82,6 @@@ static struct spi_driver da9052_spi_dri
        .id_table = da9052_spi_id,
        .driver = {
                .name = "da9052",
-               .owner = THIS_MODULE,
        },
  };
  
index 8ee11f4120fcae295756118c492b9cdef150eadf,8c79831b20fbcda44891f3cc7d1f3a5f6017dc54..1c1b45ef3faf847d4087d61904ed18c1a6f7ce5e
@@@ -1511,12 -1511,10 +1511,11 @@@ static const struct of_device_id mmc_sp
        { .compatible = "mmc-spi-slot", },
        {},
  };
 +MODULE_DEVICE_TABLE(of, mmc_spi_of_match_table);
  
  static struct spi_driver mmc_spi_driver = {
        .driver = {
                .name =         "mmc_spi",
-               .owner =        THIS_MODULE,
                .of_match_table = mmc_spi_of_match_table,
        },
        .probe =        mmc_spi_probe,
index 4b5d7a4655fd46bdac14ba04e51de56be91af2fe,fcf171a1325e1af7765c449a33d4c7df3fa26f81..fe9ceb7b5405adc029842ebc444e8c82e690ec89
@@@ -31,6 -31,7 +31,6 @@@
  struct m25p {
        struct spi_device       *spi;
        struct spi_nor          spi_nor;
 -      struct mtd_info         mtd;
        u8                      command[MAX_CMD_SIZE];
  };
  
@@@ -61,7 -62,8 +61,7 @@@ static int m25p_cmdsz(struct spi_nor *n
        return 1 + nor->addr_width;
  }
  
 -static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
 -                      int wr_en)
 +static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
  {
        struct m25p *flash = nor->priv;
        struct spi_device *spi = flash->spi;
@@@ -157,7 -159,7 +157,7 @@@ static int m25p80_erase(struct spi_nor 
        struct m25p *flash = nor->priv;
  
        dev_dbg(nor->dev, "%dKiB at 0x%08x\n",
 -              flash->mtd.erasesize / 1024, (u32)offset);
 +              flash->spi_nor.mtd.erasesize / 1024, (u32)offset);
  
        /* Set up command buffer. */
        flash->command[0] = nor->erase_opcode;
@@@ -199,10 -201,11 +199,10 @@@ static int m25p_probe(struct spi_devic
        nor->read_reg = m25p80_read_reg;
  
        nor->dev = &spi->dev;
 -      nor->mtd = &flash->mtd;
 +      nor->flash_node = spi->dev.of_node;
        nor->priv = flash;
  
        spi_set_drvdata(spi, flash);
 -      flash->mtd.priv = nor;
        flash->spi = spi;
  
        if (spi->mode & SPI_RX_QUAD)
                mode = SPI_NOR_DUAL;
  
        if (data && data->name)
 -              flash->mtd.name = data->name;
 +              nor->mtd.name = data->name;
  
        /* For some (historical?) reason many platforms provide two different
         * names in flash_platform_data: "name" and "type". Quite often name is
  
        ppdata.of_node = spi->dev.of_node;
  
 -      return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
 +      return mtd_device_parse_register(&nor->mtd, NULL, &ppdata,
                        data ? data->parts : NULL,
                        data ? data->nr_parts : 0);
  }
@@@ -240,7 -243,7 +240,7 @@@ static int m25p_remove(struct spi_devic
        struct m25p     *flash = spi_get_drvdata(spi);
  
        /* Clean up MTD stuff. */
 -      return mtd_device_unregister(&flash->mtd);
 +      return mtd_device_unregister(&flash->spi_nor.mtd);
  }
  
  /*
@@@ -301,7 -304,6 +301,6 @@@ MODULE_DEVICE_TABLE(of, m25p_of_table)
  static struct spi_driver m25p80_driver = {
        .driver = {
                .name   = "m25p80",
-               .owner  = THIS_MODULE,
                .of_match_table = m25p_of_table,
        },
        .id_table       = m25p_ids,
index 39666d552682e9d607025f3d01ba0afd513dd260,70c16399e8bad28ef1fca2b5834aa38ea98370af..e4a88715a844952b73a62bd5427af89b46935cd4
@@@ -648,6 -648,7 +648,6 @@@ static int add_dataflash_otp(struct spi
        device->size = nr_pages * pagesize;
        device->erasesize = pagesize;
        device->writesize = pagesize;
 -      device->owner = THIS_MODULE;
        device->type = MTD_DATAFLASH;
        device->flags = MTD_WRITEABLE;
        device->_erase = dataflash_erase;
@@@ -910,7 -911,6 +910,6 @@@ static int dataflash_remove(struct spi_
  static struct spi_driver dataflash_driver = {
        .driver = {
                .name           = "mtd_dataflash",
-               .owner          = THIS_MODULE,
                .of_match_table = of_match_ptr(dataflash_dt_ids),
        },
  
index 3928014f83ac050325c52fbd7d9949b11a9a37e5,18febf74404d808597e0b1b737535e8a82b8369e..5b84d71efb3642f179b5128ae2d4c6c76a4cdc31
@@@ -374,8 -374,9 +374,8 @@@ static int sst25l_probe(struct spi_devi
        data = dev_get_platdata(&spi->dev);
        if (data && data->name)
                flash->mtd.name = data->name;
 -      else
 -              flash->mtd.name = dev_name(&spi->dev);
  
 +      flash->mtd.dev.parent   = &spi->dev;
        flash->mtd.type         = MTD_NORFLASH;
        flash->mtd.flags        = MTD_CAP_NORFLASH;
        flash->mtd.erasesize    = flash_info->erase_size;
@@@ -416,7 -417,6 +416,6 @@@ static int sst25l_remove(struct spi_dev
  static struct spi_driver sst25l_driver = {
        .driver = {
                .name   = "sst25l",
-               .owner  = THIS_MODULE,
        },
        .probe          = sst25l_probe,
        .remove         = sst25l_remove,
index de6e4fa2d6aafd24cd53ce7b8a7eb5f272c3d804,46805ab0764f94cadac760a17f23e7ad170e16f5..0fbbba7a0cae38afe5fc6dfa122489c1a3271fdf
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/skbuff.h>
  #include <linux/of_gpio.h>
  #include <linux/ieee802154.h>
 +#include <linux/debugfs.h>
  
  #include <net/mac802154.h>
  #include <net/cfg802154.h>
@@@ -81,16 -80,7 +81,16 @@@ struct at86rf230_state_change 
        u8 from_state;
        u8 to_state;
  
 -      bool irq_enable;
 +      bool free;
 +};
 +
 +struct at86rf230_trac {
 +      u64 success;
 +      u64 success_data_pending;
 +      u64 success_wait_for_ack;
 +      u64 channel_access_failure;
 +      u64 no_ack;
 +      u64 invalid;
  };
  
  struct at86rf230_local {
        struct completion state_complete;
        struct at86rf230_state_change state;
  
 -      struct at86rf230_state_change irq;
 -
        unsigned long cal_timeout;
        bool is_tx;
        bool is_tx_from_off;
        u8 tx_retry;
        struct sk_buff *tx_skb;
        struct at86rf230_state_change tx;
 +
 +      struct at86rf230_trac trac;
  };
  
  #define AT86RF2XX_NUMREGS 0x3F
  static void
  at86rf230_async_state_change(struct at86rf230_local *lp,
                             struct at86rf230_state_change *ctx,
 -                           const u8 state, void (*complete)(void *context),
 -                           const bool irq_enable);
 +                           const u8 state, void (*complete)(void *context));
  
  static inline void
  at86rf230_sleep(struct at86rf230_local *lp)
@@@ -349,10 -340,8 +349,10 @@@ at86rf230_async_error_recover(void *con
        struct at86rf230_local *lp = ctx->lp;
  
        lp->is_tx = 0;
 -      at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false);
 +      at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL);
        ieee802154_wake_queue(lp->hw);
 +      if (ctx->free)
 +              kfree(ctx);
  }
  
  static inline void
@@@ -362,14 -351,15 +362,14 @@@ at86rf230_async_error(struct at86rf230_
        dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
  
        at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
 -                                   at86rf230_async_error_recover, false);
 +                                   at86rf230_async_error_recover);
  }
  
  /* Generic function to get some register value in async mode */
  static void
 -at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
 +at86rf230_async_read_reg(struct at86rf230_local *lp, u8 reg,
                         struct at86rf230_state_change *ctx,
 -                       void (*complete)(void *context),
 -                       const bool irq_enable)
 +                       void (*complete)(void *context))
  {
        int rc;
  
  
        tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
        ctx->msg.complete = complete;
 -      ctx->irq_enable = irq_enable;
        rc = spi_async(lp->spi, &ctx->msg);
 -      if (rc) {
 -              if (irq_enable)
 -                      enable_irq(ctx->irq);
 -
 +      if (rc)
                at86rf230_async_error(lp, ctx, rc);
 -      }
  }
  
 -static inline u8 at86rf230_state_to_force(u8 state)
 +static void
 +at86rf230_async_write_reg(struct at86rf230_local *lp, u8 reg, u8 val,
 +                        struct at86rf230_state_change *ctx,
 +                        void (*complete)(void *context))
  {
 -      if (state == STATE_TX_ON)
 -              return STATE_FORCE_TX_ON;
 -      else
 -              return STATE_FORCE_TRX_OFF;
 +      int rc;
 +
 +      ctx->buf[0] = (reg & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
 +      ctx->buf[1] = val;
 +      ctx->msg.complete = complete;
 +      rc = spi_async(lp->spi, &ctx->msg);
 +      if (rc)
 +              at86rf230_async_error(lp, ctx, rc);
  }
  
  static void
@@@ -438,11 -426,12 +438,11 @@@ at86rf230_async_state_assert(void *cont
                                u8 state = ctx->to_state;
  
                                if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
 -                                      state = at86rf230_state_to_force(state);
 +                                      state = STATE_FORCE_TRX_OFF;
                                lp->tx_retry++;
  
                                at86rf230_async_state_change(lp, ctx, state,
 -                                                           ctx->complete,
 -                                                           ctx->irq_enable);
 +                                                           ctx->complete);
                                return;
                        }
                }
@@@ -463,7 -452,8 +463,7 @@@ static enum hrtimer_restart at86rf230_a
        struct at86rf230_local *lp = ctx->lp;
  
        at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
 -                               at86rf230_async_state_assert,
 -                               ctx->irq_enable);
 +                               at86rf230_async_state_assert);
  
        return HRTIMER_NORESTART;
  }
@@@ -568,12 -558,14 +568,12 @@@ at86rf230_async_state_change_start(voi
        struct at86rf230_local *lp = ctx->lp;
        u8 *buf = ctx->buf;
        const u8 trx_state = buf[1] & TRX_STATE_MASK;
 -      int rc;
  
        /* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
        if (trx_state == STATE_TRANSITION_IN_PROGRESS) {
                udelay(1);
                at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
 -                                       at86rf230_async_state_change_start,
 -                                       ctx->irq_enable);
 +                                       at86rf230_async_state_change_start);
                return;
        }
  
        /* Going into the next step for a state change which do a timing
         * relevant delay.
         */
 -      buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
 -      buf[1] = ctx->to_state;
 -      ctx->msg.complete = at86rf230_async_state_delay;
 -      rc = spi_async(lp->spi, &ctx->msg);
 -      if (rc) {
 -              if (ctx->irq_enable)
 -                      enable_irq(ctx->irq);
 -
 -              at86rf230_async_error(lp, ctx, rc);
 -      }
 +      at86rf230_async_write_reg(lp, RG_TRX_STATE, ctx->to_state, ctx,
 +                                at86rf230_async_state_delay);
  }
  
  static void
  at86rf230_async_state_change(struct at86rf230_local *lp,
                             struct at86rf230_state_change *ctx,
 -                           const u8 state, void (*complete)(void *context),
 -                           const bool irq_enable)
 +                           const u8 state, void (*complete)(void *context))
  {
        /* Initialization for the state change context */
        ctx->to_state = state;
        ctx->complete = complete;
 -      ctx->irq_enable = irq_enable;
        at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
 -                               at86rf230_async_state_change_start,
 -                               irq_enable);
 +                               at86rf230_async_state_change_start);
  }
  
  static void
@@@ -625,7 -628,8 +625,7 @@@ at86rf230_sync_state_change(struct at86
        unsigned long rc;
  
        at86rf230_async_state_change(lp, &lp->state, state,
 -                                   at86rf230_sync_state_change_complete,
 -                                   false);
 +                                   at86rf230_sync_state_change_complete);
  
        rc = wait_for_completion_timeout(&lp->state_complete,
                                         msecs_to_jiffies(100));
@@@ -643,8 -647,9 +643,8 @@@ at86rf230_tx_complete(void *context
        struct at86rf230_state_change *ctx = context;
        struct at86rf230_local *lp = ctx->lp;
  
 -      enable_irq(ctx->irq);
 -
        ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
 +      kfree(ctx);
  }
  
  static void
@@@ -654,7 -659,7 +654,7 @@@ at86rf230_tx_on(void *context
        struct at86rf230_local *lp = ctx->lp;
  
        at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON,
 -                                   at86rf230_tx_complete, true);
 +                                   at86rf230_tx_complete);
  }
  
  static void
@@@ -662,33 -667,28 +662,33 @@@ at86rf230_tx_trac_check(void *context
  {
        struct at86rf230_state_change *ctx = context;
        struct at86rf230_local *lp = ctx->lp;
 -      const u8 *buf = ctx->buf;
 -      const u8 trac = (buf[1] & 0xe0) >> 5;
  
 -      /* If trac status is different than zero we need to do a state change
 -       * to STATE_FORCE_TRX_OFF then STATE_RX_AACK_ON to recover the
 -       * transceiver.
 -       */
 -      if (trac)
 -              at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
 -                                           at86rf230_tx_on, true);
 -      else
 -              at86rf230_tx_on(context);
 -}
 +      if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
 +              u8 trac = TRAC_MASK(ctx->buf[1]);
  
 -static void
 -at86rf230_tx_trac_status(void *context)
 -{
 -      struct at86rf230_state_change *ctx = context;
 -      struct at86rf230_local *lp = ctx->lp;
 +              switch (trac) {
 +              case TRAC_SUCCESS:
 +                      lp->trac.success++;
 +                      break;
 +              case TRAC_SUCCESS_DATA_PENDING:
 +                      lp->trac.success_data_pending++;
 +                      break;
 +              case TRAC_CHANNEL_ACCESS_FAILURE:
 +                      lp->trac.channel_access_failure++;
 +                      break;
 +              case TRAC_NO_ACK:
 +                      lp->trac.no_ack++;
 +                      break;
 +              case TRAC_INVALID:
 +                      lp->trac.invalid++;
 +                      break;
 +              default:
 +                      WARN_ONCE(1, "received tx trac status %d\n", trac);
 +                      break;
 +              }
 +      }
  
 -      at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
 -                               at86rf230_tx_trac_check, true);
 +      at86rf230_async_state_change(lp, ctx, STATE_TX_ON, at86rf230_tx_on);
  }
  
  static void
@@@ -696,6 -696,7 +696,6 @@@ at86rf230_rx_read_frame_complete(void *
  {
        struct at86rf230_state_change *ctx = context;
        struct at86rf230_local *lp = ctx->lp;
 -      u8 rx_local_buf[AT86RF2XX_MAX_BUF];
        const u8 *buf = ctx->buf;
        struct sk_buff *skb;
        u8 len, lqi;
        }
        lqi = buf[2 + len];
  
 -      memcpy(rx_local_buf, buf + 2, len);
 -      ctx->trx.len = 2;
 -      enable_irq(ctx->irq);
 -
        skb = dev_alloc_skb(IEEE802154_MTU);
        if (!skb) {
                dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n");
 +              kfree(ctx);
                return;
        }
  
 -      memcpy(skb_put(skb, len), rx_local_buf, len);
 +      memcpy(skb_put(skb, len), buf + 2, len);
        ieee802154_rx_irqsafe(lp->hw, skb, lqi);
 +      kfree(ctx);
  }
  
  static void
 -at86rf230_rx_read_frame(void *context)
 +at86rf230_rx_trac_check(void *context)
  {
        struct at86rf230_state_change *ctx = context;
        struct at86rf230_local *lp = ctx->lp;
        u8 *buf = ctx->buf;
        int rc;
  
 +      if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) {
 +              u8 trac = TRAC_MASK(buf[1]);
 +
 +              switch (trac) {
 +              case TRAC_SUCCESS:
 +                      lp->trac.success++;
 +                      break;
 +              case TRAC_SUCCESS_WAIT_FOR_ACK:
 +                      lp->trac.success_wait_for_ack++;
 +                      break;
 +              case TRAC_INVALID:
 +                      lp->trac.invalid++;
 +                      break;
 +              default:
 +                      WARN_ONCE(1, "received rx trac status %d\n", trac);
 +                      break;
 +              }
 +      }
 +
        buf[0] = CMD_FB;
        ctx->trx.len = AT86RF2XX_MAX_BUF;
        ctx->msg.complete = at86rf230_rx_read_frame_complete;
        rc = spi_async(lp->spi, &ctx->msg);
        if (rc) {
                ctx->trx.len = 2;
 -              enable_irq(ctx->irq);
                at86rf230_async_error(lp, ctx, rc);
        }
  }
  
  static void
 -at86rf230_rx_trac_check(void *context)
 +at86rf230_irq_trx_end(void *context)
  {
 -      /* Possible check on trac status here. This could be useful to make
 -       * some stats why receive is failed. Not used at the moment, but it's
 -       * maybe timing relevant. Datasheet doesn't say anything about this.
 -       * The programming guide say do it so.
 -       */
 -
 -      at86rf230_rx_read_frame(context);
 -}
 +      struct at86rf230_state_change *ctx = context;
 +      struct at86rf230_local *lp = ctx->lp;
  
 -static void
 -at86rf230_irq_trx_end(struct at86rf230_local *lp)
 -{
        if (lp->is_tx) {
                lp->is_tx = 0;
 -              at86rf230_async_state_change(lp, &lp->irq,
 -                                           STATE_FORCE_TX_ON,
 -                                           at86rf230_tx_trac_status,
 -                                           true);
 +              at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
 +                                       at86rf230_tx_trac_check);
        } else {
 -              at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
 -                                       at86rf230_rx_trac_check, true);
 +              at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
 +                                       at86rf230_rx_trac_check);
        }
  }
  
@@@ -778,59 -774,32 +778,59 @@@ at86rf230_irq_status(void *context
        struct at86rf230_state_change *ctx = context;
        struct at86rf230_local *lp = ctx->lp;
        const u8 *buf = ctx->buf;
 -      const u8 irq = buf[1];
 +      u8 irq = buf[1];
 +
 +      enable_irq(lp->spi->irq);
  
        if (irq & IRQ_TRX_END) {
 -              at86rf230_irq_trx_end(lp);
 +              at86rf230_irq_trx_end(ctx);
        } else {
 -              enable_irq(ctx->irq);
                dev_err(&lp->spi->dev, "not supported irq %02x received\n",
                        irq);
 +              kfree(ctx);
        }
  }
  
 +static void
 +at86rf230_setup_spi_messages(struct at86rf230_local *lp,
 +                           struct at86rf230_state_change *state)
 +{
 +      state->lp = lp;
 +      state->irq = lp->spi->irq;
 +      spi_message_init(&state->msg);
 +      state->msg.context = state;
 +      state->trx.len = 2;
 +      state->trx.tx_buf = state->buf;
 +      state->trx.rx_buf = state->buf;
 +      spi_message_add_tail(&state->trx, &state->msg);
 +      hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 +      state->timer.function = at86rf230_async_state_timer;
 +}
 +
  static irqreturn_t at86rf230_isr(int irq, void *data)
  {
        struct at86rf230_local *lp = data;
 -      struct at86rf230_state_change *ctx = &lp->irq;
 -      u8 *buf = ctx->buf;
 +      struct at86rf230_state_change *ctx;
        int rc;
  
        disable_irq_nosync(irq);
  
 -      buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
 +      ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
 +      if (!ctx) {
 +              enable_irq(irq);
 +              return IRQ_NONE;
 +      }
 +
 +      at86rf230_setup_spi_messages(lp, ctx);
 +      /* tell on error handling to free ctx */
 +      ctx->free = true;
 +
 +      ctx->buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
        ctx->msg.complete = at86rf230_irq_status;
        rc = spi_async(lp->spi, &ctx->msg);
        if (rc) {
 -              enable_irq(irq);
                at86rf230_async_error(lp, ctx, rc);
 +              enable_irq(irq);
                return IRQ_NONE;
        }
  
@@@ -842,14 -811,21 +842,14 @@@ at86rf230_write_frame_complete(void *co
  {
        struct at86rf230_state_change *ctx = context;
        struct at86rf230_local *lp = ctx->lp;
 -      u8 *buf = ctx->buf;
 -      int rc;
  
        ctx->trx.len = 2;
  
 -      if (gpio_is_valid(lp->slp_tr)) {
 +      if (gpio_is_valid(lp->slp_tr))
                at86rf230_slp_tr_rising_edge(lp);
 -      } else {
 -              buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
 -              buf[1] = STATE_BUSY_TX;
 -              ctx->msg.complete = NULL;
 -              rc = spi_async(lp->spi, &ctx->msg);
 -              if (rc)
 -                      at86rf230_async_error(lp, ctx, rc);
 -      }
 +      else
 +              at86rf230_async_write_reg(lp, RG_TRX_STATE, STATE_BUSY_TX, ctx,
 +                                        NULL);
  }
  
  static void
@@@ -882,7 -858,7 +882,7 @@@ at86rf230_xmit_tx_on(void *context
        struct at86rf230_local *lp = ctx->lp;
  
        at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
 -                                   at86rf230_write_frame, false);
 +                                   at86rf230_write_frame);
  }
  
  static void
@@@ -895,10 -871,12 +895,10 @@@ at86rf230_xmit_start(void *context
        if (lp->is_tx_from_off) {
                lp->is_tx_from_off = false;
                at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
 -                                           at86rf230_write_frame,
 -                                           false);
 +                                           at86rf230_write_frame);
        } else {
                at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
 -                                           at86rf230_xmit_tx_on,
 -                                           false);
 +                                           at86rf230_xmit_tx_on);
        }
  }
  
@@@ -921,7 -899,7 +921,7 @@@ at86rf230_xmit(struct ieee802154_hw *hw
        if (time_is_before_jiffies(lp->cal_timeout)) {
                lp->is_tx_from_off = true;
                at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF,
 -                                           at86rf230_xmit_start, false);
 +                                           at86rf230_xmit_start);
        } else {
                at86rf230_xmit_start(ctx);
        }
@@@ -942,10 -920,6 +942,10 @@@ at86rf230_start(struct ieee802154_hw *h
  {
        struct at86rf230_local *lp = hw->priv;
  
 +      /* reset trac stats on start */
 +      if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS))
 +              memset(&lp->trac, 0, sizeof(struct at86rf230_trac));
 +
        at86rf230_awake(lp);
        enable_irq(lp->spi->irq);
  
@@@ -1380,6 -1354,10 +1380,6 @@@ static int at86rf230_hw_init(struct at8
                return rc;
  
        irq_type = irq_get_trigger_type(lp->spi->irq);
 -      if (irq_type == IRQ_TYPE_EDGE_RISING ||
 -          irq_type == IRQ_TYPE_EDGE_FALLING)
 -              dev_warn(&lp->spi->dev,
 -                       "Using edge triggered irq's are not recommended!\n");
        if (irq_type == IRQ_TYPE_EDGE_FALLING ||
            irq_type == IRQ_TYPE_LEVEL_LOW)
                irq_pol = IRQ_ACTIVE_LOW;
@@@ -1605,65 -1583,42 +1605,65 @@@ not_supp
        return rc;
  }
  
 -static void
 -at86rf230_setup_spi_messages(struct at86rf230_local *lp)
 +#ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS
 +static struct dentry *at86rf230_debugfs_root;
 +
 +static int at86rf230_stats_show(struct seq_file *file, void *offset)
 +{
 +      struct at86rf230_local *lp = file->private;
 +
 +      seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success);
 +      seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n",
 +                 lp->trac.success_data_pending);
 +      seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n",
 +                 lp->trac.success_wait_for_ack);
 +      seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n",
 +                 lp->trac.channel_access_failure);
 +      seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack);
 +      seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid);
 +      return 0;
 +}
 +
 +static int at86rf230_stats_open(struct inode *inode, struct file *file)
 +{
 +      return single_open(file, at86rf230_stats_show, inode->i_private);
 +}
 +
 +static const struct file_operations at86rf230_stats_fops = {
 +      .open           = at86rf230_stats_open,
 +      .read           = seq_read,
 +      .llseek         = seq_lseek,
 +      .release        = single_release,
 +};
 +
 +static int at86rf230_debugfs_init(struct at86rf230_local *lp)
 +{
 +      char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-";
 +      struct dentry *stats;
 +
 +      strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN);
 +
 +      at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
 +      if (!at86rf230_debugfs_root)
 +              return -ENOMEM;
 +
 +      stats = debugfs_create_file("trac_stats", S_IRUGO,
 +                                  at86rf230_debugfs_root, lp,
 +                                  &at86rf230_stats_fops);
 +      if (!stats)
 +              return -ENOMEM;
 +
 +      return 0;
 +}
 +
 +static void at86rf230_debugfs_remove(void)
  {
 -      lp->state.lp = lp;
 -      lp->state.irq = lp->spi->irq;
 -      spi_message_init(&lp->state.msg);
 -      lp->state.msg.context = &lp->state;
 -      lp->state.trx.len = 2;
 -      lp->state.trx.tx_buf = lp->state.buf;
 -      lp->state.trx.rx_buf = lp->state.buf;
 -      spi_message_add_tail(&lp->state.trx, &lp->state.msg);
 -      hrtimer_init(&lp->state.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 -      lp->state.timer.function = at86rf230_async_state_timer;
 -
 -      lp->irq.lp = lp;
 -      lp->irq.irq = lp->spi->irq;
 -      spi_message_init(&lp->irq.msg);
 -      lp->irq.msg.context = &lp->irq;
 -      lp->irq.trx.len = 2;
 -      lp->irq.trx.tx_buf = lp->irq.buf;
 -      lp->irq.trx.rx_buf = lp->irq.buf;
 -      spi_message_add_tail(&lp->irq.trx, &lp->irq.msg);
 -      hrtimer_init(&lp->irq.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 -      lp->irq.timer.function = at86rf230_async_state_timer;
 -
 -      lp->tx.lp = lp;
 -      lp->tx.irq = lp->spi->irq;
 -      spi_message_init(&lp->tx.msg);
 -      lp->tx.msg.context = &lp->tx;
 -      lp->tx.trx.len = 2;
 -      lp->tx.trx.tx_buf = lp->tx.buf;
 -      lp->tx.trx.rx_buf = lp->tx.buf;
 -      spi_message_add_tail(&lp->tx.trx, &lp->tx.msg);
 -      hrtimer_init(&lp->tx.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 -      lp->tx.timer.function = at86rf230_async_state_timer;
 +      debugfs_remove_recursive(at86rf230_debugfs_root);
  }
 +#else
 +static int at86rf230_debugfs_init(struct at86rf230_local *lp) { return 0; }
 +static void at86rf230_debugfs_remove(void) { }
 +#endif
  
  static int at86rf230_probe(struct spi_device *spi)
  {
                goto free_dev;
        }
  
 -      at86rf230_setup_spi_messages(lp);
 +      at86rf230_setup_spi_messages(lp, &lp->state);
 +      at86rf230_setup_spi_messages(lp, &lp->tx);
  
        rc = at86rf230_detect_device(lp);
        if (rc < 0)
        /* going into sleep by default */
        at86rf230_sleep(lp);
  
 -      rc = ieee802154_register_hw(lp->hw);
 +      rc = at86rf230_debugfs_init(lp);
        if (rc)
                goto free_dev;
  
 +      rc = ieee802154_register_hw(lp->hw);
 +      if (rc)
 +              goto free_debugfs;
 +
        return rc;
  
 +free_debugfs:
 +      at86rf230_debugfs_remove();
  free_dev:
        ieee802154_free_hw(lp->hw);
  
@@@ -1787,7 -1735,6 +1787,7 @@@ static int at86rf230_remove(struct spi_
        at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
        ieee802154_unregister_hw(lp->hw);
        ieee802154_free_hw(lp->hw);
 +      at86rf230_debugfs_remove();
        dev_dbg(&spi->dev, "unregistered at86rf230\n");
  
        return 0;
@@@ -1816,7 -1763,6 +1816,6 @@@ static struct spi_driver at86rf230_driv
        .driver = {
                .of_match_table = of_match_ptr(at86rf230_of_match),
                .name   = "at86rf230",
-               .owner  = THIS_MODULE,
        },
        .probe      = at86rf230_probe,
        .remove     = at86rf230_remove,
index aca0fb3cccbf5f294e689daae6722638356badab,e4c37d48add16a40c67c8cc36e7288054b7efa85..4cdf51638972095644204eebccf46c8c77421ef2
  #include <linux/spi/spi.h>
  #include <linux/interrupt.h>
  #include <linux/module.h>
 +#include <linux/regmap.h>
  #include <linux/ieee802154.h>
 +#include <linux/irq.h>
  #include <net/cfg802154.h>
  #include <net/mac802154.h>
  
  /* MRF24J40 Short Address Registers */
 -#define REG_RXMCR    0x00  /* Receive MAC control */
 -#define REG_PANIDL   0x01  /* PAN ID (low) */
 -#define REG_PANIDH   0x02  /* PAN ID (high) */
 -#define REG_SADRL    0x03  /* Short address (low) */
 -#define REG_SADRH    0x04  /* Short address (high) */
 -#define REG_EADR0    0x05  /* Long address (low) (high is EADR7) */
 -#define REG_TXMCR    0x11  /* Transmit MAC control */
 -#define REG_PACON0   0x16  /* Power Amplifier Control */
 -#define REG_PACON1   0x17  /* Power Amplifier Control */
 -#define REG_PACON2   0x18  /* Power Amplifier Control */
 -#define REG_TXNCON   0x1B  /* Transmit Normal FIFO Control */
 -#define REG_TXSTAT   0x24  /* TX MAC Status Register */
 -#define REG_SOFTRST  0x2A  /* Soft Reset */
 -#define REG_TXSTBL   0x2E  /* TX Stabilization */
 -#define REG_INTSTAT  0x31  /* Interrupt Status */
 -#define REG_INTCON   0x32  /* Interrupt Control */
 -#define REG_GPIO     0x33  /* GPIO */
 -#define REG_TRISGPIO 0x34  /* GPIO direction */
 -#define REG_RFCTL    0x36  /* RF Control Mode Register */
 -#define REG_BBREG1   0x39  /* Baseband Registers */
 -#define REG_BBREG2   0x3A  /* */
 -#define REG_BBREG6   0x3E  /* */
 -#define REG_CCAEDTH  0x3F  /* Energy Detection Threshold */
 +#define REG_RXMCR     0x00  /* Receive MAC control */
 +#define BIT_PROMI     BIT(0)
 +#define BIT_ERRPKT    BIT(1)
 +#define BIT_NOACKRSP  BIT(5)
 +#define BIT_PANCOORD  BIT(3)
 +
 +#define REG_PANIDL    0x01  /* PAN ID (low) */
 +#define REG_PANIDH    0x02  /* PAN ID (high) */
 +#define REG_SADRL     0x03  /* Short address (low) */
 +#define REG_SADRH     0x04  /* Short address (high) */
 +#define REG_EADR0     0x05  /* Long address (low) (high is EADR7) */
 +#define REG_EADR1     0x06
 +#define REG_EADR2     0x07
 +#define REG_EADR3     0x08
 +#define REG_EADR4     0x09
 +#define REG_EADR5     0x0A
 +#define REG_EADR6     0x0B
 +#define REG_EADR7     0x0C
 +#define REG_RXFLUSH   0x0D
 +#define REG_ORDER     0x10
 +#define REG_TXMCR     0x11  /* Transmit MAC control */
 +#define TXMCR_MIN_BE_SHIFT            3
 +#define TXMCR_MIN_BE_MASK             0x18
 +#define TXMCR_CSMA_RETRIES_SHIFT      0
 +#define TXMCR_CSMA_RETRIES_MASK               0x07
 +
 +#define REG_ACKTMOUT  0x12
 +#define REG_ESLOTG1   0x13
 +#define REG_SYMTICKL  0x14
 +#define REG_SYMTICKH  0x15
 +#define REG_PACON0    0x16  /* Power Amplifier Control */
 +#define REG_PACON1    0x17  /* Power Amplifier Control */
 +#define REG_PACON2    0x18  /* Power Amplifier Control */
 +#define REG_TXBCON0   0x1A
 +#define REG_TXNCON    0x1B  /* Transmit Normal FIFO Control */
 +#define BIT_TXNTRIG   BIT(0)
 +#define BIT_TXNACKREQ BIT(2)
 +
 +#define REG_TXG1CON   0x1C
 +#define REG_TXG2CON   0x1D
 +#define REG_ESLOTG23  0x1E
 +#define REG_ESLOTG45  0x1F
 +#define REG_ESLOTG67  0x20
 +#define REG_TXPEND    0x21
 +#define REG_WAKECON   0x22
 +#define REG_FROMOFFSET        0x23
 +#define REG_TXSTAT    0x24  /* TX MAC Status Register */
 +#define REG_TXBCON1   0x25
 +#define REG_GATECLK   0x26
 +#define REG_TXTIME    0x27
 +#define REG_HSYMTMRL  0x28
 +#define REG_HSYMTMRH  0x29
 +#define REG_SOFTRST   0x2A  /* Soft Reset */
 +#define REG_SECCON0   0x2C
 +#define REG_SECCON1   0x2D
 +#define REG_TXSTBL    0x2E  /* TX Stabilization */
 +#define REG_RXSR      0x30
 +#define REG_INTSTAT   0x31  /* Interrupt Status */
 +#define BIT_TXNIF     BIT(0)
 +#define BIT_RXIF      BIT(3)
 +
 +#define REG_INTCON    0x32  /* Interrupt Control */
 +#define BIT_TXNIE     BIT(0)
 +#define BIT_RXIE      BIT(3)
 +
 +#define REG_GPIO      0x33  /* GPIO */
 +#define REG_TRISGPIO  0x34  /* GPIO direction */
 +#define REG_SLPACK    0x35
 +#define REG_RFCTL     0x36  /* RF Control Mode Register */
 +#define BIT_RFRST     BIT(2)
 +
 +#define REG_SECCR2    0x37
 +#define REG_BBREG0    0x38
 +#define REG_BBREG1    0x39  /* Baseband Registers */
 +#define BIT_RXDECINV  BIT(2)
 +
 +#define REG_BBREG2    0x3A  /* */
 +#define BBREG2_CCA_MODE_SHIFT 6
 +#define BBREG2_CCA_MODE_MASK  0xc0
 +
 +#define REG_BBREG3    0x3B
 +#define REG_BBREG4    0x3C
 +#define REG_BBREG6    0x3E  /* */
 +#define REG_CCAEDTH   0x3F  /* Energy Detection Threshold */
  
  /* MRF24J40 Long Address Registers */
 -#define REG_RFCON0     0x200  /* RF Control Registers */
 -#define REG_RFCON1     0x201
 -#define REG_RFCON2     0x202
 -#define REG_RFCON3     0x203
 -#define REG_RFCON5     0x205
 -#define REG_RFCON6     0x206
 -#define REG_RFCON7     0x207
 -#define REG_RFCON8     0x208
 -#define REG_RSSI       0x210
 -#define REG_SLPCON0    0x211  /* Sleep Clock Control Registers */
 -#define REG_SLPCON1    0x220
 -#define REG_WAKETIMEL  0x222  /* Wake-up Time Match Value Low */
 -#define REG_WAKETIMEH  0x223  /* Wake-up Time Match Value High */
 -#define REG_TESTMODE   0x22F  /* Test mode */
 -#define REG_RX_FIFO    0x300  /* Receive FIFO */
 +#define REG_RFCON0    0x200  /* RF Control Registers */
 +#define RFCON0_CH_SHIFT       4
 +#define RFCON0_CH_MASK        0xf0
 +#define RFOPT_RECOMMEND       3
 +
 +#define REG_RFCON1    0x201
 +#define REG_RFCON2    0x202
 +#define REG_RFCON3    0x203
 +
 +#define TXPWRL_MASK   0xc0
 +#define TXPWRL_SHIFT  6
 +#define TXPWRL_30     0x3
 +#define TXPWRL_20     0x2
 +#define TXPWRL_10     0x1
 +#define TXPWRL_0      0x0
 +
 +#define TXPWRS_MASK   0x38
 +#define TXPWRS_SHIFT  3
 +#define TXPWRS_6_3    0x7
 +#define TXPWRS_4_9    0x6
 +#define TXPWRS_3_7    0x5
 +#define TXPWRS_2_8    0x4
 +#define TXPWRS_1_9    0x3
 +#define TXPWRS_1_2    0x2
 +#define TXPWRS_0_5    0x1
 +#define TXPWRS_0      0x0
 +
 +#define REG_RFCON5    0x205
 +#define REG_RFCON6    0x206
 +#define REG_RFCON7    0x207
 +#define REG_RFCON8    0x208
 +#define REG_SLPCAL0   0x209
 +#define REG_SLPCAL1   0x20A
 +#define REG_SLPCAL2   0x20B
 +#define REG_RFSTATE   0x20F
 +#define REG_RSSI      0x210
 +#define REG_SLPCON0   0x211  /* Sleep Clock Control Registers */
 +#define BIT_INTEDGE   BIT(1)
 +
 +#define REG_SLPCON1   0x220
 +#define REG_WAKETIMEL 0x222  /* Wake-up Time Match Value Low */
 +#define REG_WAKETIMEH 0x223  /* Wake-up Time Match Value High */
 +#define REG_REMCNTL   0x224
 +#define REG_REMCNTH   0x225
 +#define REG_MAINCNT0  0x226
 +#define REG_MAINCNT1  0x227
 +#define REG_MAINCNT2  0x228
 +#define REG_MAINCNT3  0x229
 +#define REG_TESTMODE  0x22F  /* Test mode */
 +#define REG_ASSOEAR0  0x230
 +#define REG_ASSOEAR1  0x231
 +#define REG_ASSOEAR2  0x232
 +#define REG_ASSOEAR3  0x233
 +#define REG_ASSOEAR4  0x234
 +#define REG_ASSOEAR5  0x235
 +#define REG_ASSOEAR6  0x236
 +#define REG_ASSOEAR7  0x237
 +#define REG_ASSOSAR0  0x238
 +#define REG_ASSOSAR1  0x239
 +#define REG_UNONCE0   0x240
 +#define REG_UNONCE1   0x241
 +#define REG_UNONCE2   0x242
 +#define REG_UNONCE3   0x243
 +#define REG_UNONCE4   0x244
 +#define REG_UNONCE5   0x245
 +#define REG_UNONCE6   0x246
 +#define REG_UNONCE7   0x247
 +#define REG_UNONCE8   0x248
 +#define REG_UNONCE9   0x249
 +#define REG_UNONCE10  0x24A
 +#define REG_UNONCE11  0x24B
 +#define REG_UNONCE12  0x24C
 +#define REG_RX_FIFO   0x300  /* Receive FIFO */
  
  /* Device configuration: Only channels 11-26 on page 0 are supported. */
  #define MRF24J40_CHAN_MIN 11
@@@ -202,52 -81,11 +202,52 @@@ struct mrf24j40 
        struct spi_device *spi;
        struct ieee802154_hw *hw;
  
 -      struct mutex buffer_mutex; /* only used to protect buf */
 -      struct completion tx_complete;
 -      u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
 +      struct regmap *regmap_short;
 +      struct regmap *regmap_long;
 +
 +      /* for writing txfifo */
 +      struct spi_message tx_msg;
 +      u8 tx_hdr_buf[2];
 +      struct spi_transfer tx_hdr_trx;
 +      u8 tx_len_buf[2];
 +      struct spi_transfer tx_len_trx;
 +      struct spi_transfer tx_buf_trx;
 +      struct sk_buff *tx_skb;
 +
 +      /* post transmit message to send frame out  */
 +      struct spi_message tx_post_msg;
 +      u8 tx_post_buf[2];
 +      struct spi_transfer tx_post_trx;
 +
 +      /* for protect/unprotect/read length rxfifo */
 +      struct spi_message rx_msg;
 +      u8 rx_buf[3];
 +      struct spi_transfer rx_trx;
 +
 +      /* receive handling */
 +      struct spi_message rx_buf_msg;
 +      u8 rx_addr_buf[2];
 +      struct spi_transfer rx_addr_trx;
 +      u8 rx_lqi_buf[2];
 +      struct spi_transfer rx_lqi_trx;
 +      u8 rx_fifo_buf[RX_FIFO_SIZE];
 +      struct spi_transfer rx_fifo_buf_trx;
 +
 +      /* isr handling for reading intstat */
 +      struct spi_message irq_msg;
 +      u8 irq_buf[2];
 +      struct spi_transfer irq_trx;
  };
  
 +/* regmap information for short address register access */
 +#define MRF24J40_SHORT_WRITE  0x01
 +#define MRF24J40_SHORT_READ   0x00
 +#define MRF24J40_SHORT_NUMREGS        0x3F
 +
 +/* regmap information for long address register access */
 +#define MRF24J40_LONG_ACCESS  0x80
 +#define MRF24J40_LONG_NUMREGS 0x38F
 +
  /* Read/Write SPI Commands for Short and Long Address registers. */
  #define MRF24J40_READSHORT(reg) ((reg) << 1)
  #define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1)
  
  #define printdev(X) (&X->spi->dev)
  
 -static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value)
 +static bool
 +mrf24j40_short_reg_writeable(struct device *dev, unsigned int reg)
  {
 -      int ret;
 -      struct spi_message msg;
 -      struct spi_transfer xfer = {
 -              .len = 2,
 -              .tx_buf = devrec->buf,
 -              .rx_buf = devrec->buf,
 -      };
 +      switch (reg) {
 +      case REG_RXMCR:
 +      case REG_PANIDL:
 +      case REG_PANIDH:
 +      case REG_SADRL:
 +      case REG_SADRH:
 +      case REG_EADR0:
 +      case REG_EADR1:
 +      case REG_EADR2:
 +      case REG_EADR3:
 +      case REG_EADR4:
 +      case REG_EADR5:
 +      case REG_EADR6:
 +      case REG_EADR7:
 +      case REG_RXFLUSH:
 +      case REG_ORDER:
 +      case REG_TXMCR:
 +      case REG_ACKTMOUT:
 +      case REG_ESLOTG1:
 +      case REG_SYMTICKL:
 +      case REG_SYMTICKH:
 +      case REG_PACON0:
 +      case REG_PACON1:
 +      case REG_PACON2:
 +      case REG_TXBCON0:
 +      case REG_TXNCON:
 +      case REG_TXG1CON:
 +      case REG_TXG2CON:
 +      case REG_ESLOTG23:
 +      case REG_ESLOTG45:
 +      case REG_ESLOTG67:
 +      case REG_TXPEND:
 +      case REG_WAKECON:
 +      case REG_FROMOFFSET:
 +      case REG_TXBCON1:
 +      case REG_GATECLK:
 +      case REG_TXTIME:
 +      case REG_HSYMTMRL:
 +      case REG_HSYMTMRH:
 +      case REG_SOFTRST:
 +      case REG_SECCON0:
 +      case REG_SECCON1:
 +      case REG_TXSTBL:
 +      case REG_RXSR:
 +      case REG_INTCON:
 +      case REG_TRISGPIO:
 +      case REG_GPIO:
 +      case REG_RFCTL:
 +      case REG_SLPACK:
 +      case REG_BBREG0:
 +      case REG_BBREG1:
 +      case REG_BBREG2:
 +      case REG_BBREG3:
 +      case REG_BBREG4:
 +      case REG_BBREG6:
 +      case REG_CCAEDTH:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
  
 -      spi_message_init(&msg);
 -      spi_message_add_tail(&xfer, &msg);
 +static bool
 +mrf24j40_short_reg_readable(struct device *dev, unsigned int reg)
 +{
 +      bool rc;
 +
 +      /* all writeable are also readable */
 +      rc = mrf24j40_short_reg_writeable(dev, reg);
 +      if (rc)
 +              return rc;
 +
 +      /* readonly regs */
 +      switch (reg) {
 +      case REG_TXSTAT:
 +      case REG_INTSTAT:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
  
 -      mutex_lock(&devrec->buffer_mutex);
 -      devrec->buf[0] = MRF24J40_WRITESHORT(reg);
 -      devrec->buf[1] = value;
 +static bool
 +mrf24j40_short_reg_volatile(struct device *dev, unsigned int reg)
 +{
 +      /* can be changed during runtime */
 +      switch (reg) {
 +      case REG_TXSTAT:
 +      case REG_INTSTAT:
 +      case REG_RXFLUSH:
 +      case REG_TXNCON:
 +      case REG_SOFTRST:
 +      case REG_RFCTL:
 +      case REG_TXBCON0:
 +      case REG_TXG1CON:
 +      case REG_TXG2CON:
 +      case REG_TXBCON1:
 +      case REG_SECCON0:
 +      case REG_RXSR:
 +      case REG_SLPACK:
 +      case REG_SECCR2:
 +      case REG_BBREG6:
 +      /* use them in spi_async and regmap so it's volatile */
 +      case REG_BBREG1:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
  
 -      ret = spi_sync(devrec->spi, &msg);
 -      if (ret)
 -              dev_err(printdev(devrec),
 -                      "SPI write Failed for short register 0x%hhx\n", reg);
 +static bool
 +mrf24j40_short_reg_precious(struct device *dev, unsigned int reg)
 +{
 +      /* don't clear irq line on read */
 +      switch (reg) {
 +      case REG_INTSTAT:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
  
 -      mutex_unlock(&devrec->buffer_mutex);
 -      return ret;
 +static const struct regmap_config mrf24j40_short_regmap = {
 +      .name = "mrf24j40_short",
 +      .reg_bits = 7,
 +      .val_bits = 8,
 +      .pad_bits = 1,
 +      .write_flag_mask = MRF24J40_SHORT_WRITE,
 +      .read_flag_mask = MRF24J40_SHORT_READ,
 +      .cache_type = REGCACHE_RBTREE,
 +      .max_register = MRF24J40_SHORT_NUMREGS,
 +      .writeable_reg = mrf24j40_short_reg_writeable,
 +      .readable_reg = mrf24j40_short_reg_readable,
 +      .volatile_reg = mrf24j40_short_reg_volatile,
 +      .precious_reg = mrf24j40_short_reg_precious,
 +};
 +
 +static bool
 +mrf24j40_long_reg_writeable(struct device *dev, unsigned int reg)
 +{
 +      switch (reg) {
 +      case REG_RFCON0:
 +      case REG_RFCON1:
 +      case REG_RFCON2:
 +      case REG_RFCON3:
 +      case REG_RFCON5:
 +      case REG_RFCON6:
 +      case REG_RFCON7:
 +      case REG_RFCON8:
 +      case REG_SLPCAL2:
 +      case REG_SLPCON0:
 +      case REG_SLPCON1:
 +      case REG_WAKETIMEL:
 +      case REG_WAKETIMEH:
 +      case REG_REMCNTL:
 +      case REG_REMCNTH:
 +      case REG_MAINCNT0:
 +      case REG_MAINCNT1:
 +      case REG_MAINCNT2:
 +      case REG_MAINCNT3:
 +      case REG_TESTMODE:
 +      case REG_ASSOEAR0:
 +      case REG_ASSOEAR1:
 +      case REG_ASSOEAR2:
 +      case REG_ASSOEAR3:
 +      case REG_ASSOEAR4:
 +      case REG_ASSOEAR5:
 +      case REG_ASSOEAR6:
 +      case REG_ASSOEAR7:
 +      case REG_ASSOSAR0:
 +      case REG_ASSOSAR1:
 +      case REG_UNONCE0:
 +      case REG_UNONCE1:
 +      case REG_UNONCE2:
 +      case REG_UNONCE3:
 +      case REG_UNONCE4:
 +      case REG_UNONCE5:
 +      case REG_UNONCE6:
 +      case REG_UNONCE7:
 +      case REG_UNONCE8:
 +      case REG_UNONCE9:
 +      case REG_UNONCE10:
 +      case REG_UNONCE11:
 +      case REG_UNONCE12:
 +              return true;
 +      default:
 +              return false;
 +      }
  }
  
 -static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
 +static bool
 +mrf24j40_long_reg_readable(struct device *dev, unsigned int reg)
  {
 -      int ret = -1;
 -      struct spi_message msg;
 -      struct spi_transfer xfer = {
 -              .len = 2,
 -              .tx_buf = devrec->buf,
 -              .rx_buf = devrec->buf,
 -      };
 +      bool rc;
 +
 +      /* all writeable are also readable */
 +      rc = mrf24j40_long_reg_writeable(dev, reg);
 +      if (rc)
 +              return rc;
 +
 +      /* readonly regs */
 +      switch (reg) {
 +      case REG_SLPCAL0:
 +      case REG_SLPCAL1:
 +      case REG_RFSTATE:
 +      case REG_RSSI:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
  
 -      spi_message_init(&msg);
 -      spi_message_add_tail(&xfer, &msg);
 +static bool
 +mrf24j40_long_reg_volatile(struct device *dev, unsigned int reg)
 +{
 +      /* can be changed during runtime */
 +      switch (reg) {
 +      case REG_SLPCAL0:
 +      case REG_SLPCAL1:
 +      case REG_SLPCAL2:
 +      case REG_RFSTATE:
 +      case REG_RSSI:
 +      case REG_MAINCNT3:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
  
 -      mutex_lock(&devrec->buffer_mutex);
 -      devrec->buf[0] = MRF24J40_READSHORT(reg);
 -      devrec->buf[1] = 0;
 +static const struct regmap_config mrf24j40_long_regmap = {
 +      .name = "mrf24j40_long",
 +      .reg_bits = 11,
 +      .val_bits = 8,
 +      .pad_bits = 5,
 +      .write_flag_mask = MRF24J40_LONG_ACCESS,
 +      .read_flag_mask = MRF24J40_LONG_ACCESS,
 +      .cache_type = REGCACHE_RBTREE,
 +      .max_register = MRF24J40_LONG_NUMREGS,
 +      .writeable_reg = mrf24j40_long_reg_writeable,
 +      .readable_reg = mrf24j40_long_reg_readable,
 +      .volatile_reg = mrf24j40_long_reg_volatile,
 +};
  
 -      ret = spi_sync(devrec->spi, &msg);
 -      if (ret)
 -              dev_err(printdev(devrec),
 -                      "SPI read Failed for short register 0x%hhx\n", reg);
 -      else
 -              *val = devrec->buf[1];
 +static int mrf24j40_long_regmap_write(void *context, const void *data,
 +                                    size_t count)
 +{
 +      struct spi_device *spi = context;
 +      u8 buf[3];
  
 -      mutex_unlock(&devrec->buffer_mutex);
 -      return ret;
 +      if (count > 3)
 +              return -EINVAL;
 +
 +      /* regmap supports read/write mask only in frist byte
 +       * long write access need to set the 12th bit, so we
 +       * make special handling for write.
 +       */
 +      memcpy(buf, data, count);
 +      buf[1] |= (1 << 4);
 +
 +      return spi_write(spi, buf, count);
  }
  
 -static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
 +static int
 +mrf24j40_long_regmap_read(void *context, const void *reg, size_t reg_size,
 +                        void *val, size_t val_size)
  {
 -      int ret;
 -      u16 cmd;
 -      struct spi_message msg;
 -      struct spi_transfer xfer = {
 -              .len = 3,
 -              .tx_buf = devrec->buf,
 -              .rx_buf = devrec->buf,
 -      };
 -
 -      spi_message_init(&msg);
 -      spi_message_add_tail(&xfer, &msg);
 -
 -      cmd = MRF24J40_READLONG(reg);
 -      mutex_lock(&devrec->buffer_mutex);
 -      devrec->buf[0] = cmd >> 8 & 0xff;
 -      devrec->buf[1] = cmd & 0xff;
 -      devrec->buf[2] = 0;
 -
 -      ret = spi_sync(devrec->spi, &msg);
 -      if (ret)
 -              dev_err(printdev(devrec),
 -                      "SPI read Failed for long register 0x%hx\n", reg);
 -      else
 -              *value = devrec->buf[2];
 +      struct spi_device *spi = context;
  
 -      mutex_unlock(&devrec->buffer_mutex);
 -      return ret;
 +      return spi_write_then_read(spi, reg, reg_size, val, val_size);
  }
  
 -static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val)
 +static const struct regmap_bus mrf24j40_long_regmap_bus = {
 +      .write = mrf24j40_long_regmap_write,
 +      .read = mrf24j40_long_regmap_read,
 +      .reg_format_endian_default = REGMAP_ENDIAN_BIG,
 +      .val_format_endian_default = REGMAP_ENDIAN_BIG,
 +};
 +
 +static void write_tx_buf_complete(void *context)
  {
 +      struct mrf24j40 *devrec = context;
 +      __le16 fc = ieee802154_get_fc_from_skb(devrec->tx_skb);
 +      u8 val = BIT_TXNTRIG;
        int ret;
 -      u16 cmd;
 -      struct spi_message msg;
 -      struct spi_transfer xfer = {
 -              .len = 3,
 -              .tx_buf = devrec->buf,
 -              .rx_buf = devrec->buf,
 -      };
  
 -      spi_message_init(&msg);
 -      spi_message_add_tail(&xfer, &msg);
 +      if (ieee802154_is_ackreq(fc))
 +              val |= BIT_TXNACKREQ;
  
 -      cmd = MRF24J40_WRITELONG(reg);
 -      mutex_lock(&devrec->buffer_mutex);
 -      devrec->buf[0] = cmd >> 8 & 0xff;
 -      devrec->buf[1] = cmd & 0xff;
 -      devrec->buf[2] = val;
 +      devrec->tx_post_msg.complete = NULL;
 +      devrec->tx_post_buf[0] = MRF24J40_WRITESHORT(REG_TXNCON);
 +      devrec->tx_post_buf[1] = val;
  
 -      ret = spi_sync(devrec->spi, &msg);
 +      ret = spi_async(devrec->spi, &devrec->tx_post_msg);
        if (ret)
 -              dev_err(printdev(devrec),
 -                      "SPI write Failed for long register 0x%hx\n", reg);
 -
 -      mutex_unlock(&devrec->buffer_mutex);
 -      return ret;
 +              dev_err(printdev(devrec), "SPI write Failed for transmit buf\n");
  }
  
  /* This function relies on an undocumented write method. Once a write command
  static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
                        const u8 *data, size_t length)
  {
 -      int ret;
        u16 cmd;
 -      u8 lengths[2];
 -      struct spi_message msg;
 -      struct spi_transfer addr_xfer = {
 -              .len = 2,
 -              .tx_buf = devrec->buf,
 -      };
 -      struct spi_transfer lengths_xfer = {
 -              .len = 2,
 -              .tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */
 -      };
 -      struct spi_transfer data_xfer = {
 -              .len = length,
 -              .tx_buf = data,
 -      };
 +      int ret;
  
        /* Range check the length. 2 bytes are used for the length fields.*/
        if (length > TX_FIFO_SIZE-2) {
                length = TX_FIFO_SIZE-2;
        }
  
 -      spi_message_init(&msg);
 -      spi_message_add_tail(&addr_xfer, &msg);
 -      spi_message_add_tail(&lengths_xfer, &msg);
 -      spi_message_add_tail(&data_xfer, &msg);
 -
        cmd = MRF24J40_WRITELONG(reg);
 -      mutex_lock(&devrec->buffer_mutex);
 -      devrec->buf[0] = cmd >> 8 & 0xff;
 -      devrec->buf[1] = cmd & 0xff;
 -      lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
 -      lengths[1] = length; /* Total length */
 -
 -      ret = spi_sync(devrec->spi, &msg);
 +      devrec->tx_hdr_buf[0] = cmd >> 8 & 0xff;
 +      devrec->tx_hdr_buf[1] = cmd & 0xff;
 +      devrec->tx_len_buf[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
 +      devrec->tx_len_buf[1] = length; /* Total length */
 +      devrec->tx_buf_trx.tx_buf = data;
 +      devrec->tx_buf_trx.len = length;
 +
 +      ret = spi_async(devrec->spi, &devrec->tx_msg);
        if (ret)
                dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
  
 -      mutex_unlock(&devrec->buffer_mutex);
 -      return ret;
 -}
 -
 -static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
 -                              u8 *data, u8 *len, u8 *lqi)
 -{
 -      u8 rx_len;
 -      u8 addr[2];
 -      u8 lqi_rssi[2];
 -      u16 cmd;
 -      int ret;
 -      struct spi_message msg;
 -      struct spi_transfer addr_xfer = {
 -              .len = 2,
 -              .tx_buf = &addr,
 -      };
 -      struct spi_transfer data_xfer = {
 -              .len = 0x0, /* set below */
 -              .rx_buf = data,
 -      };
 -      struct spi_transfer status_xfer = {
 -              .len = 2,
 -              .rx_buf = &lqi_rssi,
 -      };
 -
 -      /* Get the length of the data in the RX FIFO. The length in this
 -       * register exclues the 1-byte length field at the beginning. */
 -      ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len);
 -      if (ret)
 -              goto out;
 -
 -      /* Range check the RX FIFO length, accounting for the one-byte
 -       * length field at the beginning. */
 -      if (rx_len > RX_FIFO_SIZE-1) {
 -              dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n");
 -              rx_len = RX_FIFO_SIZE-1;
 -      }
 -
 -      if (rx_len > *len) {
 -              /* Passed in buffer wasn't big enough. Should never happen. */
 -              dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n");
 -              rx_len = *len;
 -      }
 -
 -      /* Set up the commands to read the data. */
 -      cmd = MRF24J40_READLONG(REG_RX_FIFO+1);
 -      addr[0] = cmd >> 8 & 0xff;
 -      addr[1] = cmd & 0xff;
 -      data_xfer.len = rx_len;
 -
 -      spi_message_init(&msg);
 -      spi_message_add_tail(&addr_xfer, &msg);
 -      spi_message_add_tail(&data_xfer, &msg);
 -      spi_message_add_tail(&status_xfer, &msg);
 -
 -      ret = spi_sync(devrec->spi, &msg);
 -      if (ret) {
 -              dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n");
 -              goto out;
 -      }
 -
 -      *lqi = lqi_rssi[0];
 -      *len = rx_len;
 -
 -#ifdef DEBUG
 -      print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
 -                     DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
 -      pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
 -               lqi_rssi[0], lqi_rssi[1]);
 -#endif
 -
 -out:
        return ret;
  }
  
  static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
  {
        struct mrf24j40 *devrec = hw->priv;
 -      u8 val;
 -      int ret = 0;
  
        dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
 +      devrec->tx_skb = skb;
  
 -      ret = write_tx_buf(devrec, 0x000, skb->data, skb->len);
 -      if (ret)
 -              goto err;
 -
 -      reinit_completion(&devrec->tx_complete);
 -
 -      /* Set TXNTRIG bit of TXNCON to send packet */
 -      ret = read_short_reg(devrec, REG_TXNCON, &val);
 -      if (ret)
 -              goto err;
 -      val |= 0x1;
 -      /* Set TXNACKREQ if the ACK bit is set in the packet. */
 -      if (skb->data[0] & IEEE802154_FC_ACK_REQ)
 -              val |= 0x4;
 -      write_short_reg(devrec, REG_TXNCON, val);
 -
 -      /* Wait for the device to send the TX complete interrupt. */
 -      ret = wait_for_completion_interruptible_timeout(
 -                                              &devrec->tx_complete,
 -                                              5 * HZ);
 -      if (ret == -ERESTARTSYS)
 -              goto err;
 -      if (ret == 0) {
 -              dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n");
 -              ret = -ETIMEDOUT;
 -              goto err;
 -      }
 -
 -      /* Check for send error from the device. */
 -      ret = read_short_reg(devrec, REG_TXSTAT, &val);
 -      if (ret)
 -              goto err;
 -      if (val & 0x1) {
 -              dev_dbg(printdev(devrec), "Error Sending. Retry count exceeded\n");
 -              ret = -ECOMM; /* TODO: Better error code ? */
 -      } else
 -              dev_dbg(printdev(devrec), "Packet Sent\n");
 -
 -err:
 -
 -      return ret;
 +      return write_tx_buf(devrec, 0x000, skb->data, skb->len);
  }
  
  static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
  static int mrf24j40_start(struct ieee802154_hw *hw)
  {
        struct mrf24j40 *devrec = hw->priv;
 -      u8 val;
 -      int ret;
  
        dev_dbg(printdev(devrec), "start\n");
  
 -      ret = read_short_reg(devrec, REG_INTCON, &val);
 -      if (ret)
 -              return ret;
 -      val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */
 -      write_short_reg(devrec, REG_INTCON, val);
 -
 -      return 0;
 +      /* Clear TXNIE and RXIE. Enable interrupts */
 +      return regmap_update_bits(devrec->regmap_short, REG_INTCON,
 +                                BIT_TXNIE | BIT_RXIE, 0);
  }
  
  static void mrf24j40_stop(struct ieee802154_hw *hw)
  {
        struct mrf24j40 *devrec = hw->priv;
 -      u8 val;
 -      int ret;
  
        dev_dbg(printdev(devrec), "stop\n");
  
 -      ret = read_short_reg(devrec, REG_INTCON, &val);
 -      if (ret)
 -              return;
 -      val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
 -      write_short_reg(devrec, REG_INTCON, val);
 +      /* Set TXNIE and RXIE. Disable Interrupts */
 +      regmap_update_bits(devrec->regmap_short, REG_INTCON,
 +                         BIT_TXNIE | BIT_TXNIE, BIT_TXNIE | BIT_TXNIE);
  }
  
  static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
        WARN_ON(channel > MRF24J40_CHAN_MAX);
  
        /* Set Channel TODO */
 -      val = (channel-11) << 4 | 0x03;
 -      write_long_reg(devrec, REG_RFCON0, val);
 +      val = (channel - 11) << RFCON0_CH_SHIFT | RFOPT_RECOMMEND;
 +      ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0,
 +                               RFCON0_CH_MASK, val);
 +      if (ret)
 +              return ret;
  
        /* RF Reset */
 -      ret = read_short_reg(devrec, REG_RFCTL, &val);
 +      ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST,
 +                               BIT_RFRST);
        if (ret)
                return ret;
 -      val |= 0x04;
 -      write_short_reg(devrec, REG_RFCTL, val);
 -      val &= ~0x04;
 -      write_short_reg(devrec, REG_RFCTL, val);
  
 -      udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
 +      ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST, 0);
 +      if (!ret)
 +              udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
  
 -      return 0;
 +      return ret;
  }
  
  static int mrf24j40_filter(struct ieee802154_hw *hw,
                addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
                addrl = le16_to_cpu(filt->short_addr) & 0xff;
  
 -              write_short_reg(devrec, REG_SADRH, addrh);
 -              write_short_reg(devrec, REG_SADRL, addrl);
 +              regmap_write(devrec->regmap_short, REG_SADRH, addrh);
 +              regmap_write(devrec->regmap_short, REG_SADRL, addrl);
                dev_dbg(printdev(devrec),
                        "Set short addr to %04hx\n", filt->short_addr);
        }
  
                memcpy(addr, &filt->ieee_addr, 8);
                for (i = 0; i < 8; i++)
 -                      write_short_reg(devrec, REG_EADR0 + i, addr[i]);
 +                      regmap_write(devrec->regmap_short, REG_EADR0 + i,
 +                                   addr[i]);
  
  #ifdef DEBUG
                pr_debug("Set long addr to: ");
  
                panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
                panidl = le16_to_cpu(filt->pan_id) & 0xff;
 -              write_short_reg(devrec, REG_PANIDH, panidh);
 -              write_short_reg(devrec, REG_PANIDL, panidl);
 +              regmap_write(devrec->regmap_short, REG_PANIDH, panidh);
 +              regmap_write(devrec->regmap_short, REG_PANIDL, panidl);
  
                dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
        }
                u8 val;
                int ret;
  
 -              ret = read_short_reg(devrec, REG_RXMCR, &val);
 -              if (ret)
 -                      return ret;
                if (filt->pan_coord)
 -                      val |= 0x8;
 +                      val = BIT_PANCOORD;
                else
 -                      val &= ~0x8;
 -              write_short_reg(devrec, REG_RXMCR, val);
 +                      val = 0;
 +              ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
 +                                       BIT_PANCOORD, val);
 +              if (ret)
 +                      return ret;
  
                /* REG_SLOTTED is maintained as default (unslotted/CSMA-CA).
                 * REG_ORDER is maintained as default (no beacon/superframe).
        return 0;
  }
  
 -static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
 +static void mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 *devrec)
  {
 -      u8 len = RX_FIFO_SIZE;
 -      u8 lqi = 0;
 -      u8 val;
 -      int ret = 0;
 -      int ret2;
 -      struct sk_buff *skb;
 +      int ret;
  
 -      /* Turn off reception of packets off the air. This prevents the
 -       * device from overwriting the buffer while we're reading it. */
 -      ret = read_short_reg(devrec, REG_BBREG1, &val);
 +      /* Turn back on reception of packets off the air. */
 +      devrec->rx_msg.complete = NULL;
 +      devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
 +      devrec->rx_buf[1] = 0x00; /* CLR RXDECINV */
 +      ret = spi_async(devrec->spi, &devrec->rx_msg);
        if (ret)
 -              goto out;
 -      val |= 4; /* SET RXDECINV */
 -      write_short_reg(devrec, REG_BBREG1, val);
 +              dev_err(printdev(devrec), "failed to unlock rx buffer\n");
 +}
 +
 +static void mrf24j40_handle_rx_read_buf_complete(void *context)
 +{
 +      struct mrf24j40 *devrec = context;
 +      u8 len = devrec->rx_buf[2];
 +      u8 rx_local_buf[RX_FIFO_SIZE];
 +      struct sk_buff *skb;
 +
 +      memcpy(rx_local_buf, devrec->rx_fifo_buf, len);
 +      mrf24j40_handle_rx_read_buf_unlock(devrec);
  
 -      skb = dev_alloc_skb(len);
 +      skb = dev_alloc_skb(IEEE802154_MTU);
        if (!skb) {
 -              ret = -ENOMEM;
 -              goto out;
 +              dev_err(printdev(devrec), "failed to allocate skb\n");
 +              return;
        }
  
 -      ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi);
 -      if (ret < 0) {
 -              dev_err(printdev(devrec), "Failure reading RX FIFO\n");
 -              kfree_skb(skb);
 -              ret = -EINVAL;
 -              goto out;
 +      memcpy(skb_put(skb, len), rx_local_buf, len);
 +      ieee802154_rx_irqsafe(devrec->hw, skb, 0);
 +
 +#ifdef DEBUG
 +       print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", DUMP_PREFIX_OFFSET, 16, 1,
 +                      rx_local_buf, len, 0);
 +       pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
 +                devrec->rx_lqi_buf[0], devrec->rx_lqi_buf[1]);
 +#endif
 +}
 +
 +static void mrf24j40_handle_rx_read_buf(void *context)
 +{
 +      struct mrf24j40 *devrec = context;
 +      u16 cmd;
 +      int ret;
 +
 +      /* if length is invalid read the full MTU */
 +      if (!ieee802154_is_valid_psdu_len(devrec->rx_buf[2]))
 +              devrec->rx_buf[2] = IEEE802154_MTU;
 +
 +      cmd = MRF24J40_READLONG(REG_RX_FIFO + 1);
 +      devrec->rx_addr_buf[0] = cmd >> 8 & 0xff;
 +      devrec->rx_addr_buf[1] = cmd & 0xff;
 +      devrec->rx_fifo_buf_trx.len = devrec->rx_buf[2];
 +      ret = spi_async(devrec->spi, &devrec->rx_buf_msg);
 +      if (ret) {
 +              dev_err(printdev(devrec), "failed to read rx buffer\n");
 +              mrf24j40_handle_rx_read_buf_unlock(devrec);
        }
 +}
  
 -      /* Cut off the checksum */
 -      skb_trim(skb, len-2);
 +static void mrf24j40_handle_rx_read_len(void *context)
 +{
 +      struct mrf24j40 *devrec = context;
 +      u16 cmd;
 +      int ret;
  
 -      /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
 -       * also from a workqueue).  I think irqsafe is not necessary here.
 -       * Can someone confirm? */
 -      ieee802154_rx_irqsafe(devrec->hw, skb, lqi);
 +      /* read the length of received frame */
 +      devrec->rx_msg.complete = mrf24j40_handle_rx_read_buf;
 +      devrec->rx_trx.len = 3;
 +      cmd = MRF24J40_READLONG(REG_RX_FIFO);
 +      devrec->rx_buf[0] = cmd >> 8 & 0xff;
 +      devrec->rx_buf[1] = cmd & 0xff;
  
 -      dev_dbg(printdev(devrec), "RX Handled\n");
 +      ret = spi_async(devrec->spi, &devrec->rx_msg);
 +      if (ret) {
 +              dev_err(printdev(devrec), "failed to read rx buffer length\n");
 +              mrf24j40_handle_rx_read_buf_unlock(devrec);
 +      }
 +}
  
 -out:
 -      /* Turn back on reception of packets off the air. */
 -      ret2 = read_short_reg(devrec, REG_BBREG1, &val);
 -      if (ret2)
 -              return ret2;
 -      val &= ~0x4; /* Clear RXDECINV */
 -      write_short_reg(devrec, REG_BBREG1, val);
 +static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
 +{
 +      /* Turn off reception of packets off the air. This prevents the
 +       * device from overwriting the buffer while we're reading it.
 +       */
 +      devrec->rx_msg.complete = mrf24j40_handle_rx_read_len;
 +      devrec->rx_trx.len = 2;
 +      devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
 +      devrec->rx_buf[1] = BIT_RXDECINV; /* SET RXDECINV */
 +
 +      return spi_async(devrec->spi, &devrec->rx_msg);
 +}
 +
 +static int
 +mrf24j40_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be,
 +                   u8 retries)
 +{
 +      struct mrf24j40 *devrec = hw->priv;
 +      u8 val;
 +
 +      /* min_be */
 +      val = min_be << TXMCR_MIN_BE_SHIFT;
 +      /* csma backoffs */
 +      val |= retries << TXMCR_CSMA_RETRIES_SHIFT;
 +
 +      return regmap_update_bits(devrec->regmap_short, REG_TXMCR,
 +                                TXMCR_MIN_BE_MASK | TXMCR_CSMA_RETRIES_MASK,
 +                                val);
 +}
 +
 +static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw,
 +                               const struct wpan_phy_cca *cca)
 +{
 +      struct mrf24j40 *devrec = hw->priv;
 +      u8 val;
 +
 +      /* mapping 802.15.4 to driver spec */
 +      switch (cca->mode) {
 +      case NL802154_CCA_ENERGY:
 +              val = 2;
 +              break;
 +      case NL802154_CCA_CARRIER:
 +              val = 1;
 +              break;
 +      case NL802154_CCA_ENERGY_CARRIER:
 +              switch (cca->opt) {
 +              case NL802154_CCA_OPT_ENERGY_CARRIER_AND:
 +                      val = 3;
 +                      break;
 +              default:
 +                      return -EINVAL;
 +              }
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      return regmap_update_bits(devrec->regmap_short, REG_BBREG2,
 +                                BBREG2_CCA_MODE_MASK,
 +                                val << BBREG2_CCA_MODE_SHIFT);
 +}
 +
 +/* array for representing ed levels */
 +static const s32 mrf24j40_ed_levels[] = {
 +      -9000, -8900, -8800, -8700, -8600, -8500, -8400, -8300, -8200, -8100,
 +      -8000, -7900, -7800, -7700, -7600, -7500, -7400, -7300, -7200, -7100,
 +      -7000, -6900, -6800, -6700, -6600, -6500, -6400, -6300, -6200, -6100,
 +      -6000, -5900, -5800, -5700, -5600, -5500, -5400, -5300, -5200, -5100,
 +      -5000, -4900, -4800, -4700, -4600, -4500, -4400, -4300, -4200, -4100,
 +      -4000, -3900, -3800, -3700, -3600, -3500
 +};
 +
 +/* map ed levels to register value */
 +static const s32 mrf24j40_ed_levels_map[][2] = {
 +      { -9000, 0 }, { -8900, 1 }, { -8800, 2 }, { -8700, 5 }, { -8600, 9 },
 +      { -8500, 13 }, { -8400, 18 }, { -8300, 23 }, { -8200, 27 },
 +      { -8100, 32 }, { -8000, 37 }, { -7900, 43 }, { -7800, 48 },
 +      { -7700, 53 }, { -7600, 58 }, { -7500, 63 }, { -7400, 68 },
 +      { -7300, 73 }, { -7200, 78 }, { -7100, 83 }, { -7000, 89 },
 +      { -6900, 95 }, { -6800, 100 }, { -6700, 107 }, { -6600, 111 },
 +      { -6500, 117 }, { -6400, 121 }, { -6300, 125 }, { -6200, 129 },
 +      { -6100, 133 }, { -6000, 138 }, { -5900, 143 }, { -5800, 148 },
 +      { -5700, 153 }, { -5600, 159 }, { -5500, 165 }, { -5400, 170 },
 +      { -5300, 176 }, { -5200, 183 }, { -5100, 188 }, { -5000, 193 },
 +      { -4900, 198 }, { -4800, 203 }, { -4700, 207 }, { -4600, 212 },
 +      { -4500, 216 }, { -4400, 221 }, { -4300, 225 }, { -4200, 228 },
 +      { -4100, 233 }, { -4000, 239 }, { -3900, 245 }, { -3800, 250 },
 +      { -3700, 253 }, { -3600, 254 }, { -3500, 255 },
 +};
 +
 +static int mrf24j40_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
 +{
 +      struct mrf24j40 *devrec = hw->priv;
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(mrf24j40_ed_levels_map); i++) {
 +              if (mrf24j40_ed_levels_map[i][0] == mbm)
 +                      return regmap_write(devrec->regmap_short, REG_CCAEDTH,
 +                                          mrf24j40_ed_levels_map[i][1]);
 +      }
 +
 +      return -EINVAL;
 +}
 +
 +static const s32 mrf24j40ma_powers[] = {
 +      0, -50, -120, -190, -280, -370, -490, -630, -1000, -1050, -1120, -1190,
 +      -1280, -1370, -1490, -1630, -2000, -2050, -2120, -2190, -2280, -2370,
 +      -2490, -2630, -3000, -3050, -3120, -3190, -3280, -3370, -3490, -3630,
 +};
 +
 +static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm)
 +{
 +      struct mrf24j40 *devrec = hw->priv;
 +      s32 small_scale;
 +      u8 val;
 +
 +      if (0 >= mbm && mbm > -1000) {
 +              val = TXPWRL_0 << TXPWRL_SHIFT;
 +              small_scale = mbm;
 +      } else if (-1000 >= mbm && mbm > -2000) {
 +              val = TXPWRL_10 << TXPWRL_SHIFT;
 +              small_scale = mbm + 1000;
 +      } else if (-2000 >= mbm && mbm > -3000) {
 +              val = TXPWRL_20 << TXPWRL_SHIFT;
 +              small_scale = mbm + 2000;
 +      } else if (-3000 >= mbm && mbm > -4000) {
 +              val = TXPWRL_30 << TXPWRL_SHIFT;
 +              small_scale = mbm + 3000;
 +      } else {
 +              return -EINVAL;
 +      }
 +
 +      switch (small_scale) {
 +      case 0:
 +              val |= (TXPWRS_0 << TXPWRS_SHIFT);
 +              break;
 +      case -50:
 +              val |= (TXPWRS_0_5 << TXPWRS_SHIFT);
 +              break;
 +      case -120:
 +              val |= (TXPWRS_1_2 << TXPWRS_SHIFT);
 +              break;
 +      case -190:
 +              val |= (TXPWRS_1_9 << TXPWRS_SHIFT);
 +              break;
 +      case -280:
 +              val |= (TXPWRS_2_8 << TXPWRS_SHIFT);
 +              break;
 +      case -370:
 +              val |= (TXPWRS_3_7 << TXPWRS_SHIFT);
 +              break;
 +      case -490:
 +              val |= (TXPWRS_4_9 << TXPWRS_SHIFT);
 +              break;
 +      case -630:
 +              val |= (TXPWRS_6_3 << TXPWRS_SHIFT);
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      return regmap_update_bits(devrec->regmap_long, REG_RFCON3,
 +                                TXPWRL_MASK | TXPWRS_MASK, val);
 +}
 +
 +static int mrf24j40_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
 +{
 +      struct mrf24j40 *devrec = hw->priv;
 +      int ret;
 +
 +      if (on) {
 +              /* set PROMI, ERRPKT and NOACKRSP */
 +              ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
 +                                       BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP,
 +                                       BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP);
 +      } else {
 +              /* clear PROMI, ERRPKT and NOACKRSP */
 +              ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
 +                                       BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP,
 +                                       0);
 +      }
  
        return ret;
  }
  
  static const struct ieee802154_ops mrf24j40_ops = {
        .owner = THIS_MODULE,
 -      .xmit_sync = mrf24j40_tx,
 +      .xmit_async = mrf24j40_tx,
        .ed = mrf24j40_ed,
        .start = mrf24j40_start,
        .stop = mrf24j40_stop,
        .set_channel = mrf24j40_set_channel,
        .set_hw_addr_filt = mrf24j40_filter,
 +      .set_csma_params = mrf24j40_csma_params,
 +      .set_cca_mode = mrf24j40_set_cca_mode,
 +      .set_cca_ed_level = mrf24j40_set_cca_ed_level,
 +      .set_txpower = mrf24j40_set_txpower,
 +      .set_promiscuous_mode = mrf24j40_set_promiscuous_mode,
  };
  
 -static irqreturn_t mrf24j40_isr(int irq, void *data)
 +static void mrf24j40_intstat_complete(void *context)
  {
 -      struct mrf24j40 *devrec = data;
 -      u8 intstat;
 -      int ret;
 +      struct mrf24j40 *devrec = context;
 +      u8 intstat = devrec->irq_buf[1];
  
 -      /* Read the interrupt status */
 -      ret = read_short_reg(devrec, REG_INTSTAT, &intstat);
 -      if (ret)
 -              goto out;
 +      enable_irq(devrec->spi->irq);
  
        /* Check for TX complete */
 -      if (intstat & 0x1)
 -              complete(&devrec->tx_complete);
 +      if (intstat & BIT_TXNIF)
 +              ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false);
  
        /* Check for Rx */
 -      if (intstat & 0x8)
 +      if (intstat & BIT_RXIF)
                mrf24j40_handle_rx(devrec);
 +}
 +
 +static irqreturn_t mrf24j40_isr(int irq, void *data)
 +{
 +      struct mrf24j40 *devrec = data;
 +      int ret;
 +
 +      disable_irq_nosync(irq);
 +
 +      devrec->irq_buf[0] = MRF24J40_READSHORT(REG_INTSTAT);
 +      /* Read the interrupt status */
 +      ret = spi_async(devrec->spi, &devrec->irq_msg);
 +      if (ret) {
 +              enable_irq(irq);
 +              return IRQ_NONE;
 +      }
  
 -out:
        return IRQ_HANDLED;
  }
  
  static int mrf24j40_hw_init(struct mrf24j40 *devrec)
  {
 +      u32 irq_type;
        int ret;
 -      u8 val;
  
        /* Initialize the device.
                From datasheet section 3.2: Initialization. */
 -      ret = write_short_reg(devrec, REG_SOFTRST, 0x07);
 +      ret = regmap_write(devrec->regmap_short, REG_SOFTRST, 0x07);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_PACON2, 0x98);
 +      ret = regmap_write(devrec->regmap_short, REG_PACON2, 0x98);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_TXSTBL, 0x95);
 +      ret = regmap_write(devrec->regmap_short, REG_TXSTBL, 0x95);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_RFCON0, 0x03);
 +      ret = regmap_write(devrec->regmap_long, REG_RFCON0, 0x03);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_RFCON1, 0x01);
 +      ret = regmap_write(devrec->regmap_long, REG_RFCON1, 0x01);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_RFCON2, 0x80);
 +      ret = regmap_write(devrec->regmap_long, REG_RFCON2, 0x80);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_RFCON6, 0x90);
 +      ret = regmap_write(devrec->regmap_long, REG_RFCON6, 0x90);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_RFCON7, 0x80);
 +      ret = regmap_write(devrec->regmap_long, REG_RFCON7, 0x80);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_RFCON8, 0x10);
 +      ret = regmap_write(devrec->regmap_long, REG_RFCON8, 0x10);
        if (ret)
                goto err_ret;
  
 -      ret = write_long_reg(devrec, REG_SLPCON1, 0x21);
 +      ret = regmap_write(devrec->regmap_long, REG_SLPCON1, 0x21);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_BBREG2, 0x80);
 +      ret = regmap_write(devrec->regmap_short, REG_BBREG2, 0x80);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_CCAEDTH, 0x60);
 +      ret = regmap_write(devrec->regmap_short, REG_CCAEDTH, 0x60);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_BBREG6, 0x40);
 +      ret = regmap_write(devrec->regmap_short, REG_BBREG6, 0x40);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_RFCTL, 0x04);
 +      ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x04);
        if (ret)
                goto err_ret;
  
 -      ret = write_short_reg(devrec, REG_RFCTL, 0x0);
 +      ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x0);
        if (ret)
                goto err_ret;
  
        udelay(192);
  
        /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
 -      ret = read_short_reg(devrec, REG_RXMCR, &val);
 -      if (ret)
 -              goto err_ret;
 -
 -      val &= ~0x3; /* Clear RX mode (normal) */
 -
 -      ret = write_short_reg(devrec, REG_RXMCR, val);
 +      ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x03, 0x00);
        if (ret)
                goto err_ret;
  
                /* Enable external amplifier.
                 * From MRF24J40MC datasheet section 1.3: Operation.
                 */
 -              read_long_reg(devrec, REG_TESTMODE, &val);
 -              val |= 0x7; /* Configure GPIO 0-2 to control amplifier */
 -              write_long_reg(devrec, REG_TESTMODE, val);
 +              regmap_update_bits(devrec->regmap_long, REG_TESTMODE, 0x07,
 +                                 0x07);
  
 -              read_short_reg(devrec, REG_TRISGPIO, &val);
 -              val |= 0x8; /* Set GPIO3 as output. */
 -              write_short_reg(devrec, REG_TRISGPIO, val);
 +              /* Set GPIO3 as output. */
 +              regmap_update_bits(devrec->regmap_short, REG_TRISGPIO, 0x08,
 +                                 0x08);
  
 -              read_short_reg(devrec, REG_GPIO, &val);
 -              val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */
 -              write_short_reg(devrec, REG_GPIO, val);
 +              /* Set GPIO3 HIGH to enable U5 voltage regulator */
 +              regmap_update_bits(devrec->regmap_short, REG_GPIO, 0x08, 0x08);
  
                /* Reduce TX pwr to meet FCC requirements.
                 * From MRF24J40MC datasheet section 3.1.1
                 */
 -              write_long_reg(devrec, REG_RFCON3, 0x28);
 +              regmap_write(devrec->regmap_long, REG_RFCON3, 0x28);
 +      }
 +
 +      irq_type = irq_get_trigger_type(devrec->spi->irq);
 +      if (irq_type == IRQ_TYPE_EDGE_RISING ||
 +          irq_type == IRQ_TYPE_EDGE_FALLING)
 +              dev_warn(&devrec->spi->dev,
 +                       "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n");
 +      switch (irq_type) {
 +      case IRQ_TYPE_EDGE_RISING:
 +      case IRQ_TYPE_LEVEL_HIGH:
 +              /* set interrupt polarity to rising */
 +              ret = regmap_update_bits(devrec->regmap_long, REG_SLPCON0,
 +                                       BIT_INTEDGE, BIT_INTEDGE);
 +              if (ret)
 +                      goto err_ret;
 +              break;
 +      default:
 +              /* default is falling edge */
 +              break;
        }
  
        return 0;
@@@ -1170,178 -720,67 +1170,178 @@@ err_ret
        return ret;
  }
  
 -static int mrf24j40_probe(struct spi_device *spi)
 +static void
 +mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec)
  {
 -      int ret = -ENOMEM;
 -      struct mrf24j40 *devrec;
 +      spi_message_init(&devrec->tx_msg);
 +      devrec->tx_msg.context = devrec;
 +      devrec->tx_msg.complete = write_tx_buf_complete;
 +      devrec->tx_hdr_trx.len = 2;
 +      devrec->tx_hdr_trx.tx_buf = devrec->tx_hdr_buf;
 +      spi_message_add_tail(&devrec->tx_hdr_trx, &devrec->tx_msg);
 +      devrec->tx_len_trx.len = 2;
 +      devrec->tx_len_trx.tx_buf = devrec->tx_len_buf;
 +      spi_message_add_tail(&devrec->tx_len_trx, &devrec->tx_msg);
 +      spi_message_add_tail(&devrec->tx_buf_trx, &devrec->tx_msg);
 +
 +      spi_message_init(&devrec->tx_post_msg);
 +      devrec->tx_post_msg.context = devrec;
 +      devrec->tx_post_trx.len = 2;
 +      devrec->tx_post_trx.tx_buf = devrec->tx_post_buf;
 +      spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg);
 +}
  
 -      dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
 +static void
 +mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec)
 +{
 +      spi_message_init(&devrec->rx_msg);
 +      devrec->rx_msg.context = devrec;
 +      devrec->rx_trx.len = 2;
 +      devrec->rx_trx.tx_buf = devrec->rx_buf;
 +      devrec->rx_trx.rx_buf = devrec->rx_buf;
 +      spi_message_add_tail(&devrec->rx_trx, &devrec->rx_msg);
 +
 +      spi_message_init(&devrec->rx_buf_msg);
 +      devrec->rx_buf_msg.context = devrec;
 +      devrec->rx_buf_msg.complete = mrf24j40_handle_rx_read_buf_complete;
 +      devrec->rx_addr_trx.len = 2;
 +      devrec->rx_addr_trx.tx_buf = devrec->rx_addr_buf;
 +      spi_message_add_tail(&devrec->rx_addr_trx, &devrec->rx_buf_msg);
 +      devrec->rx_fifo_buf_trx.rx_buf = devrec->rx_fifo_buf;
 +      spi_message_add_tail(&devrec->rx_fifo_buf_trx, &devrec->rx_buf_msg);
 +      devrec->rx_lqi_trx.len = 2;
 +      devrec->rx_lqi_trx.rx_buf = devrec->rx_lqi_buf;
 +      spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg);
 +}
  
 -      devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL);
 -      if (!devrec)
 -              goto err_ret;
 -      devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL);
 -      if (!devrec->buf)
 -              goto err_ret;
 +static void
 +mrf24j40_setup_irq_spi_messages(struct mrf24j40 *devrec)
 +{
 +      spi_message_init(&devrec->irq_msg);
 +      devrec->irq_msg.context = devrec;
 +      devrec->irq_msg.complete = mrf24j40_intstat_complete;
 +      devrec->irq_trx.len = 2;
 +      devrec->irq_trx.tx_buf = devrec->irq_buf;
 +      devrec->irq_trx.rx_buf = devrec->irq_buf;
 +      spi_message_add_tail(&devrec->irq_trx, &devrec->irq_msg);
 +}
 +
 +static void  mrf24j40_phy_setup(struct mrf24j40 *devrec)
 +{
 +      ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr);
 +      devrec->hw->phy->current_channel = 11;
 +
 +      /* mrf24j40 supports max_minbe 0 - 3 */
 +      devrec->hw->phy->supported.max_minbe = 3;
 +      /* datasheet doesn't say anything about max_be, but we have min_be
 +       * So we assume the max_be default.
 +       */
 +      devrec->hw->phy->supported.min_maxbe = 5;
 +      devrec->hw->phy->supported.max_maxbe = 5;
 +
 +      devrec->hw->phy->cca.mode = NL802154_CCA_CARRIER;
 +      devrec->hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) |
 +                                             BIT(NL802154_CCA_CARRIER) |
 +                                             BIT(NL802154_CCA_ENERGY_CARRIER);
 +      devrec->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND);
 +
 +      devrec->hw->phy->cca_ed_level = -6900;
 +      devrec->hw->phy->supported.cca_ed_levels = mrf24j40_ed_levels;
 +      devrec->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(mrf24j40_ed_levels);
 +
 +      switch (spi_get_device_id(devrec->spi)->driver_data) {
 +      case MRF24J40:
 +      case MRF24J40MA:
 +              devrec->hw->phy->supported.tx_powers = mrf24j40ma_powers;
 +              devrec->hw->phy->supported.tx_powers_size = ARRAY_SIZE(mrf24j40ma_powers);
 +              devrec->hw->phy->flags |= WPAN_PHY_FLAG_TXPOWER;
 +              break;
 +      default:
 +              break;
 +      }
 +}
  
 -      spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
 -      if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
 -              spi->max_speed_hz = MAX_SPI_SPEED_HZ;
 +static int mrf24j40_probe(struct spi_device *spi)
 +{
 +      int ret = -ENOMEM, irq_type;
 +      struct ieee802154_hw *hw;
 +      struct mrf24j40 *devrec;
  
 -      mutex_init(&devrec->buffer_mutex);
 -      init_completion(&devrec->tx_complete);
 -      devrec->spi = spi;
 -      spi_set_drvdata(spi, devrec);
 +      dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
  
        /* Register with the 802154 subsystem */
  
 -      devrec->hw = ieee802154_alloc_hw(0, &mrf24j40_ops);
 -      if (!devrec->hw)
 +      hw = ieee802154_alloc_hw(sizeof(*devrec), &mrf24j40_ops);
 +      if (!hw)
                goto err_ret;
  
 -      devrec->hw->priv = devrec;
 -      devrec->hw->parent = &devrec->spi->dev;
 +      devrec = hw->priv;
 +      devrec->spi = spi;
 +      spi_set_drvdata(spi, devrec);
 +      devrec->hw = hw;
 +      devrec->hw->parent = &spi->dev;
        devrec->hw->phy->supported.channels[0] = CHANNEL_MASK;
 -      devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT;
 +      devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
 +                          IEEE802154_HW_CSMA_PARAMS |
 +                          IEEE802154_HW_PROMISCUOUS;
 +
 +      devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE |
 +                               WPAN_PHY_FLAG_CCA_ED_LEVEL;
 +
 +      mrf24j40_setup_tx_spi_messages(devrec);
 +      mrf24j40_setup_rx_spi_messages(devrec);
 +      mrf24j40_setup_irq_spi_messages(devrec);
 +
 +      devrec->regmap_short = devm_regmap_init_spi(spi,
 +                                                  &mrf24j40_short_regmap);
 +      if (IS_ERR(devrec->regmap_short)) {
 +              ret = PTR_ERR(devrec->regmap_short);
 +              dev_err(&spi->dev, "Failed to allocate short register map: %d\n",
 +                      ret);
 +              goto err_register_device;
 +      }
  
 -      dev_dbg(printdev(devrec), "registered mrf24j40\n");
 -      ret = ieee802154_register_hw(devrec->hw);
 -      if (ret)
 +      devrec->regmap_long = devm_regmap_init(&spi->dev,
 +                                             &mrf24j40_long_regmap_bus,
 +                                             spi, &mrf24j40_long_regmap);
 +      if (IS_ERR(devrec->regmap_long)) {
 +              ret = PTR_ERR(devrec->regmap_long);
 +              dev_err(&spi->dev, "Failed to allocate long register map: %d\n",
 +                      ret);
                goto err_register_device;
 +      }
 +
 +      if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) {
 +              dev_warn(&spi->dev, "spi clock above possible maximum: %d",
 +                       MAX_SPI_SPEED_HZ);
 +              return -EINVAL;
 +      }
  
        ret = mrf24j40_hw_init(devrec);
        if (ret)
 -              goto err_hw_init;
 +              goto err_register_device;
  
 -      ret = devm_request_threaded_irq(&spi->dev,
 -                                      spi->irq,
 -                                      NULL,
 -                                      mrf24j40_isr,
 -                                      IRQF_TRIGGER_LOW|IRQF_ONESHOT,
 -                                      dev_name(&spi->dev),
 -                                      devrec);
 +      mrf24j40_phy_setup(devrec);
  
 +      /* request IRQF_TRIGGER_LOW as fallback default */
 +      irq_type = irq_get_trigger_type(spi->irq);
 +      if (!irq_type)
 +              irq_type = IRQF_TRIGGER_LOW;
 +
 +      ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr,
 +                             irq_type, dev_name(&spi->dev), devrec);
        if (ret) {
                dev_err(printdev(devrec), "Unable to get IRQ");
 -              goto err_irq;
 +              goto err_register_device;
        }
  
 +      dev_dbg(printdev(devrec), "registered mrf24j40\n");
 +      ret = ieee802154_register_hw(devrec->hw);
 +      if (ret)
 +              goto err_register_device;
 +
        return 0;
  
 -err_irq:
 -err_hw_init:
 -      ieee802154_unregister_hw(devrec->hw);
  err_register_device:
        ieee802154_free_hw(devrec->hw);
  err_ret:
@@@ -1362,14 -801,6 +1362,14 @@@ static int mrf24j40_remove(struct spi_d
        return 0;
  }
  
 +static const struct of_device_id mrf24j40_of_match[] = {
 +      { .compatible = "microchip,mrf24j40", .data = (void *)MRF24J40 },
 +      { .compatible = "microchip,mrf24j40ma", .data = (void *)MRF24J40MA },
 +      { .compatible = "microchip,mrf24j40mc", .data = (void *)MRF24J40MC },
 +      { },
 +};
 +MODULE_DEVICE_TABLE(of, mrf24j40_of_match);
 +
  static const struct spi_device_id mrf24j40_ids[] = {
        { "mrf24j40", MRF24J40 },
        { "mrf24j40ma", MRF24J40MA },
@@@ -1380,9 -811,7 +1380,8 @@@ MODULE_DEVICE_TABLE(spi, mrf24j40_ids)
  
  static struct spi_driver mrf24j40_driver = {
        .driver = {
 +              .of_match_table = of_match_ptr(mrf24j40_of_match),
                .name = "mrf24j40",
-               .owner = THIS_MODULE,
        },
        .id_table = mrf24j40_ids,
        .probe = mrf24j40_probe,
diff --combined drivers/nfc/st-nci/spi.c
index cf7ad8121e1139b9c14376fbf2afaf113ab00cf3,2bb5851eef41cee9350f875ec504592c448765fc..d6519bb9dba5100dd8a8fdb199b318d479247cab
  #include <linux/interrupt.h>
  #include <linux/delay.h>
  #include <linux/nfc.h>
 +#include <net/nfc/nci.h>
  #include <linux/platform_data/st-nci.h>
  
 -#include "ndlc.h"
 +#include "st-nci.h"
  
  #define DRIVER_DESC "NCI NFC driver for ST_NCI"
  
@@@ -51,13 -50,16 +51,13 @@@ struct st_nci_spi_phy 
        struct spi_device *spi_dev;
        struct llt_ndlc *ndlc;
  
 +      bool irq_active;
 +
        unsigned int gpio_reset;
        unsigned int irq_polarity;
 -};
  
 -#define SPI_DUMP_SKB(info, skb)                                       \
 -do {                                                          \
 -      pr_debug("%s:\n", info);                                \
 -      print_hex_dump(KERN_DEBUG, "spi: ", DUMP_PREFIX_OFFSET, \
 -                     16, 1, (skb)->data, (skb)->len, 0);      \
 -} while (0)
 +      struct st_nci_se_status se_status;
 +};
  
  static int st_nci_spi_enable(void *phy_id)
  {
        gpio_set_value(phy->gpio_reset, 1);
        usleep_range(80000, 85000);
  
 -      if (phy->ndlc->powered == 0)
 +      if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
                enable_irq(phy->spi_dev->irq);
 +              phy->irq_active = true;
 +      }
  
        return 0;
  }
@@@ -81,7 -81,6 +81,7 @@@ static void st_nci_spi_disable(void *ph
        struct st_nci_spi_phy *phy = phy_id;
  
        disable_irq_nosync(phy->spi_dev->irq);
 +      phy->irq_active = false;
  }
  
  /*
@@@ -95,14 -94,15 +95,14 @@@ static int st_nci_spi_write(void *phy_i
        struct st_nci_spi_phy *phy = phy_id;
        struct spi_device *dev = phy->spi_dev;
        struct sk_buff *skb_rx;
 -      u8 buf[ST_NCI_SPI_MAX_SIZE];
 +      u8 buf[ST_NCI_SPI_MAX_SIZE + NCI_DATA_HDR_SIZE +
 +             ST_NCI_FRAME_HEADROOM + ST_NCI_FRAME_TAILROOM];
        struct spi_transfer spi_xfer = {
                .tx_buf = skb->data,
                .rx_buf = buf,
                .len = skb->len,
        };
  
 -      SPI_DUMP_SKB("st_nci_spi_write", skb);
 -
        if (phy->ndlc->hard_fault != 0)
                return phy->ndlc->hard_fault;
  
@@@ -179,6 -179,8 +179,6 @@@ static int st_nci_spi_read(struct st_nc
        skb_put(*skb, len);
        memcpy((*skb)->data + ST_NCI_SPI_MIN_SIZE, buf, len);
  
 -      SPI_DUMP_SKB("spi frame read", *skb);
 -
        return 0;
  }
  
@@@ -256,11 -258,6 +256,11 @@@ static int st_nci_spi_of_request_resour
  
        phy->irq_polarity = irq_get_trigger_type(dev->irq);
  
 +      phy->se_status.is_ese_present =
 +                              of_property_read_bool(pp, "ese-present");
 +      phy->se_status.is_uicc_present =
 +                              of_property_read_bool(pp, "uicc-present");
 +
        return 0;
  }
  #else
@@@ -293,9 -290,6 +293,9 @@@ static int st_nci_spi_request_resources
                return r;
        }
  
 +      phy->se_status.is_ese_present = pdata->is_ese_present;
 +      phy->se_status.is_uicc_present = pdata->is_uicc_present;
 +
        return 0;
  }
  
@@@ -346,13 -340,12 +346,13 @@@ static int st_nci_spi_probe(struct spi_
  
        r = ndlc_probe(phy, &spi_phy_ops, &dev->dev,
                        ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
 -                      &phy->ndlc);
 +                      &phy->ndlc, &phy->se_status);
        if (r < 0) {
                nfc_err(&dev->dev, "Unable to register ndlc layer\n");
                return r;
        }
  
 +      phy->irq_active = true;
        r = devm_request_threaded_irq(&dev->dev, dev->irq, NULL,
                                st_nci_irq_thread_fn,
                                phy->irq_polarity | IRQF_ONESHOT,
@@@ -384,7 -377,6 +384,6 @@@ MODULE_DEVICE_TABLE(of, of_st_nci_spi_m
  
  static struct spi_driver st_nci_spi_driver = {
        .driver = {
-               .owner = THIS_MODULE,
                .name = ST_NCI_SPI_DRIVER_NAME,
                .of_match_table = of_match_ptr(of_st_nci_spi_match),
        },
diff --combined drivers/nfc/trf7970a.c
index 123aa981c9d87844932b769cd3949ef6a1416a4c,4036788c78b6edda97d00e83240b77d82958d8c2..f857feb2b573e7bb98e008f44527ed762d82b7a8
@@@ -2211,12 -2211,6 +2211,12 @@@ static const struct dev_pm_ops trf7970a
                        trf7970a_pm_runtime_resume, NULL)
  };
  
 +static const struct of_device_id trf7970a_of_match[] = {
 +      { .compatible = "ti,trf7970a", },
 +      { /* sentinel */ },
 +};
 +MODULE_DEVICE_TABLE(of, trf7970a_of_match);
 +
  static const struct spi_device_id trf7970a_id_table[] = {
        { "trf7970a", 0 },
        { }
@@@ -2229,8 -2223,6 +2229,7 @@@ static struct spi_driver trf7970a_spi_d
        .id_table       = trf7970a_id_table,
        .driver         = {
                .name   = "trf7970a",
-               .owner  = THIS_MODULE,
 +              .of_match_table = of_match_ptr(trf7970a_of_match),
                .pm     = &trf7970a_pm_ops,
        },
  };
index 405b643189fd5cac9148e45e5f9d1c0d4bd94b90,5a0e77305827a4083b9da82bfa4c18d37012ef8d..b2e6237ae913722e67eaf342d2302b85504d836c
@@@ -612,8 -612,7 +612,8 @@@ static int spinand_erase_block(struct s
  
  #ifdef CONFIG_MTD_SPINAND_ONDIEECC
  static int spinand_write_page_hwecc(struct mtd_info *mtd,
 -              struct nand_chip *chip, const uint8_t *buf, int oob_required)
 +              struct nand_chip *chip, const uint8_t *buf, int oob_required,
 +              int page)
  {
        const uint8_t *p = buf;
        int eccsize = chip->ecc.size;
@@@ -913,7 -912,8 +913,7 @@@ static int spinand_probe(struct spi_dev
        dev_set_drvdata(&spi_nand->dev, mtd);
  
        mtd->priv = chip;
 -      mtd->name = dev_name(&spi_nand->dev);
 -      mtd->owner = THIS_MODULE;
 +      mtd->dev.parent = &spi_nand->dev;
        mtd->oobsize = 64;
  
        if (nand_scan(mtd, 1))
@@@ -948,7 -948,6 +948,6 @@@ static const struct of_device_id spinan
  static struct spi_driver spinand_driver = {
        .driver = {
                .name           = "mt29f",
-               .owner          = THIS_MODULE,
                .of_match_table = spinand_dt,
        },
        .probe          = spinand_probe,
index 431f95da1de1f9b0eff5bab82ac2daa07da200dd,8199a3de0024eaf84c14ce652f58e0c9af30e3ba..23c28573bdb7057356c569cb0d6054cd041611b0
@@@ -16,7 -16,6 +16,7 @@@
  
  static int ad193x_spi_probe(struct spi_device *spi)
  {
 +      const struct spi_device_id *id = spi_get_device_id(spi);
        struct regmap_config config;
  
        config = ad193x_regmap_config;
@@@ -25,8 -24,7 +25,8 @@@
        config.read_flag_mask = 0x09;
        config.write_flag_mask = 0x08;
  
 -      return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config));
 +      return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config),
 +                          (enum ad193x_type)id->driver_data);
  }
  
  static int ad193x_spi_remove(struct spi_device *spi)
        return 0;
  }
  
 +static const struct spi_device_id ad193x_spi_id[] = {
 +      { "ad193x", AD193X },
 +      { "ad1933", AD1933 },
 +      { "ad1934", AD1934 },
 +      { "ad1938", AD193X },
 +      { "ad1939", AD193X },
 +      { "adau1328", AD193X },
 +      { }
 +};
 +MODULE_DEVICE_TABLE(spi, ad193x_spi_id);
 +
  static struct spi_driver ad193x_spi_driver = {
        .driver = {
                .name   = "ad193x",
-               .owner  = THIS_MODULE,
        },
        .probe          = ad193x_spi_probe,
        .remove         = ad193x_spi_remove,
 +      .id_table       = ad193x_spi_id,
  };
  module_spi_driver(ad193x_spi_driver);
  
index 07cf1bd7913a8dfe4667e310fcb44536f8e4004c,15bd547e3c84885751f86d8e6728e0a1d96a7788..4bcf5f8ece50f3681948a9fbc47b85400d9a8b51
@@@ -132,7 -132,7 +132,7 @@@ static int wm8731_put_deemph(struct snd
  {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 -      int deemph = ucontrol->value.integer.value[0];
 +      unsigned int deemph = ucontrol->value.integer.value[0];
        int ret = 0;
  
        if (deemph > 1)
@@@ -718,7 -718,6 +718,6 @@@ static int wm8731_spi_remove(struct spi
  static struct spi_driver wm8731_spi_driver = {
        .driver = {
                .name   = "wm8731",
-               .owner  = THIS_MODULE,
                .of_match_table = wm8731_of_match,
        },
        .probe          = wm8731_spi_probe,