|
@@ -51,7 +51,7 @@ struct at86rf230_local {
|
|
|
struct ieee802154_dev *dev;
|
|
|
|
|
|
spinlock_t lock;
|
|
|
- bool irq_disabled;
|
|
|
+ bool irq_busy;
|
|
|
bool is_tx;
|
|
|
};
|
|
|
|
|
@@ -547,7 +547,7 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
|
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock(&lp->lock);
|
|
|
- if (lp->irq_disabled) {
|
|
|
+ if (lp->irq_busy) {
|
|
|
spin_unlock(&lp->lock);
|
|
|
return -EBUSY;
|
|
|
}
|
|
@@ -708,8 +708,16 @@ static void at86rf230_irqwork(struct work_struct *work)
|
|
|
}
|
|
|
|
|
|
spin_lock_irqsave(&lp->lock, flags);
|
|
|
- lp->irq_disabled = 0;
|
|
|
+ lp->irq_busy = 0;
|
|
|
spin_unlock_irqrestore(&lp->lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+static void at86rf230_irqwork_level(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct at86rf230_local *lp =
|
|
|
+ container_of(work, struct at86rf230_local, irqwork);
|
|
|
+
|
|
|
+ at86rf230_irqwork(work);
|
|
|
|
|
|
enable_irq(lp->spi->irq);
|
|
|
}
|
|
@@ -718,10 +726,8 @@ static irqreturn_t at86rf230_isr(int irq, void *data)
|
|
|
{
|
|
|
struct at86rf230_local *lp = data;
|
|
|
|
|
|
- disable_irq_nosync(irq);
|
|
|
-
|
|
|
spin_lock(&lp->lock);
|
|
|
- lp->irq_disabled = 1;
|
|
|
+ lp->irq_busy = 1;
|
|
|
spin_unlock(&lp->lock);
|
|
|
|
|
|
schedule_work(&lp->irqwork);
|
|
@@ -729,6 +735,13 @@ static irqreturn_t at86rf230_isr(int irq, void *data)
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+static irqreturn_t at86rf230_isr_level(int irq, void *data)
|
|
|
+{
|
|
|
+ disable_irq_nosync(irq);
|
|
|
+
|
|
|
+ return at86rf230_isr(irq, data);
|
|
|
+}
|
|
|
+
|
|
|
static int at86rf230_irq_polarity(struct at86rf230_local *lp, int pol)
|
|
|
{
|
|
|
return at86rf230_write_subreg(lp, SR_IRQ_POLARITY, pol);
|
|
@@ -766,12 +779,7 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, 0xff); /* IRQ_TRX_UR |
|
|
|
- * IRQ_CCA_ED |
|
|
|
- * IRQ_TRX_END |
|
|
|
- * IRQ_PLL_UNL |
|
|
|
- * IRQ_PLL_LOCK
|
|
|
- */
|
|
|
+ rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, IRQ_TRX_END);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
@@ -831,7 +839,9 @@ static int at86rf230_probe(struct spi_device *spi)
|
|
|
struct at86rf230_platform_data *pdata;
|
|
|
struct ieee802154_dev *dev;
|
|
|
struct at86rf230_local *lp;
|
|
|
- u8 man_id_0, man_id_1;
|
|
|
+ u8 man_id_0, man_id_1, status;
|
|
|
+ irq_handler_t irq_handler;
|
|
|
+ work_func_t irq_worker;
|
|
|
int rc, supported = 0;
|
|
|
const char *chip;
|
|
|
|
|
@@ -861,8 +871,16 @@ static int at86rf230_probe(struct spi_device *spi)
|
|
|
dev->phy->channels_supported[0] = 0x7FFF800;
|
|
|
dev->flags = IEEE802154_HW_OMIT_CKSUM;
|
|
|
|
|
|
+ if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
|
|
|
+ irq_worker = at86rf230_irqwork;
|
|
|
+ irq_handler = at86rf230_isr;
|
|
|
+ } else {
|
|
|
+ irq_worker = at86rf230_irqwork_level;
|
|
|
+ irq_handler = at86rf230_isr_level;
|
|
|
+ }
|
|
|
+
|
|
|
mutex_init(&lp->bmux);
|
|
|
- INIT_WORK(&lp->irqwork, at86rf230_irqwork);
|
|
|
+ INIT_WORK(&lp->irqwork, irq_worker);
|
|
|
spin_lock_init(&lp->lock);
|
|
|
init_completion(&lp->tx_complete);
|
|
|
|
|
@@ -943,12 +961,17 @@ static int at86rf230_probe(struct spi_device *spi)
|
|
|
if (rc)
|
|
|
goto err_gpio_dir;
|
|
|
|
|
|
- rc = request_irq(spi->irq, at86rf230_isr,
|
|
|
+ rc = request_irq(spi->irq, irq_handler,
|
|
|
IRQF_SHARED | pdata->irq_type,
|
|
|
dev_name(&spi->dev), lp);
|
|
|
if (rc)
|
|
|
goto err_gpio_dir;
|
|
|
|
|
|
+ /* Read irq status register to reset irq line */
|
|
|
+ rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
|
|
|
+ if (rc)
|
|
|
+ goto err_irq;
|
|
|
+
|
|
|
rc = ieee802154_register_device(lp->dev);
|
|
|
if (rc)
|
|
|
goto err_irq;
|