Merge branch 'at86rf230-next'
Alexander Aring says: ==================== at86rf230 cleanup this is the first patch series to cleanup the at86rf230 driver. Later I want to implement regmap and a asynchron spi handling for transmit and receiving frames. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
16b463061c
@ -0,0 +1,23 @@
|
||||
* AT86RF230 IEEE 802.15.4 *
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "atmel,at86rf230", "atmel,at86rf231",
|
||||
"atmel,at86rf233" or "atmel,at86rf212"
|
||||
- spi-max-frequency: maximal bus speed, should be set to 7500000 depends
|
||||
sync or async operation mode
|
||||
- reg: the chipselect index
|
||||
- interrupts: the interrupt generated by the device
|
||||
|
||||
Optional properties:
|
||||
- reset-gpio: GPIO spec for the rstn pin
|
||||
- sleep-gpio: GPIO spec for the slp_tr pin
|
||||
|
||||
Example:
|
||||
|
||||
at86rf231@0 {
|
||||
compatible = "atmel,at86rf231";
|
||||
spi-max-frequency = <7500000>;
|
||||
reg = <0>;
|
||||
interrupts = <19 1>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
};
|
@ -23,6 +23,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
@ -692,10 +693,7 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
|
||||
if (rc < 0)
|
||||
goto err_rx;
|
||||
|
||||
rc = at86rf230_start(dev);
|
||||
|
||||
return rc;
|
||||
|
||||
return at86rf230_start(dev);
|
||||
err_rx:
|
||||
at86rf230_start(dev);
|
||||
err:
|
||||
@ -963,33 +961,24 @@ static irqreturn_t at86rf230_isr_level(int irq, void *data)
|
||||
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);
|
||||
}
|
||||
|
||||
static int at86rf230_hw_init(struct at86rf230_local *lp)
|
||||
{
|
||||
struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data;
|
||||
int rc, irq_pol;
|
||||
u8 status;
|
||||
int rc, irq_pol, irq_type;
|
||||
u8 dvdd;
|
||||
u8 csma_seed[2];
|
||||
|
||||
rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
irq_type = irq_get_trigger_type(lp->spi->irq);
|
||||
/* configure irq polarity, defaults to high active */
|
||||
if (pdata->irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
|
||||
if (irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
|
||||
irq_pol = IRQ_ACTIVE_LOW;
|
||||
else
|
||||
irq_pol = IRQ_ACTIVE_HIGH;
|
||||
|
||||
rc = at86rf230_irq_polarity(lp, irq_pol);
|
||||
rc = at86rf230_write_subreg(lp, SR_IRQ_POLARITY, irq_pol);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1017,10 +1006,10 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
|
||||
/* Wait the next SLEEP cycle */
|
||||
msleep(100);
|
||||
|
||||
rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
|
||||
rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &dvdd);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (!status) {
|
||||
if (!dvdd) {
|
||||
dev_err(&lp->spi->dev, "DVDD error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1032,7 +1021,6 @@ static struct at86rf230_platform_data *
|
||||
at86rf230_get_pdata(struct spi_device *spi)
|
||||
{
|
||||
struct at86rf230_platform_data *pdata;
|
||||
const char *irq_type;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF) || !spi->dev.of_node)
|
||||
return spi->dev.platform_data;
|
||||
@ -1044,19 +1032,6 @@ at86rf230_get_pdata(struct spi_device *spi)
|
||||
pdata->rstn = of_get_named_gpio(spi->dev.of_node, "reset-gpio", 0);
|
||||
pdata->slp_tr = of_get_named_gpio(spi->dev.of_node, "sleep-gpio", 0);
|
||||
|
||||
pdata->irq_type = IRQF_TRIGGER_RISING;
|
||||
of_property_read_string(spi->dev.of_node, "irq-type", &irq_type);
|
||||
if (!strcmp(irq_type, "level-high"))
|
||||
pdata->irq_type = IRQF_TRIGGER_HIGH;
|
||||
else if (!strcmp(irq_type, "level-low"))
|
||||
pdata->irq_type = IRQF_TRIGGER_LOW;
|
||||
else if (!strcmp(irq_type, "edge-rising"))
|
||||
pdata->irq_type = IRQF_TRIGGER_RISING;
|
||||
else if (!strcmp(irq_type, "edge-falling"))
|
||||
pdata->irq_type = IRQF_TRIGGER_FALLING;
|
||||
else
|
||||
dev_warn(&spi->dev, "wrong irq-type specified using edge-rising\n");
|
||||
|
||||
spi->dev.platform_data = pdata;
|
||||
done:
|
||||
return pdata;
|
||||
@ -1071,7 +1046,7 @@ static int at86rf230_probe(struct spi_device *spi)
|
||||
u8 part = 0, version = 0, status;
|
||||
irq_handler_t irq_handler;
|
||||
work_func_t irq_worker;
|
||||
int rc;
|
||||
int rc, irq_type;
|
||||
const char *chip;
|
||||
struct ieee802154_ops *ops = NULL;
|
||||
|
||||
@ -1087,27 +1062,17 @@ static int at86rf230_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->rstn)) {
|
||||
rc = gpio_request(pdata->rstn, "rstn");
|
||||
rc = devm_gpio_request_one(&spi->dev, pdata->rstn,
|
||||
GPIOF_OUT_INIT_HIGH, "rstn");
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->slp_tr)) {
|
||||
rc = gpio_request(pdata->slp_tr, "slp_tr");
|
||||
rc = devm_gpio_request_one(&spi->dev, pdata->slp_tr,
|
||||
GPIOF_OUT_INIT_LOW, "slp_tr");
|
||||
if (rc)
|
||||
goto err_slp_tr;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->rstn)) {
|
||||
rc = gpio_direction_output(pdata->rstn, 1);
|
||||
if (rc)
|
||||
goto err_gpio_dir;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->slp_tr)) {
|
||||
rc = gpio_direction_output(pdata->slp_tr, 0);
|
||||
if (rc)
|
||||
goto err_gpio_dir;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Reset */
|
||||
@ -1121,13 +1086,12 @@ static int at86rf230_probe(struct spi_device *spi)
|
||||
|
||||
rc = __at86rf230_detect_device(spi, &man_id, &part, &version);
|
||||
if (rc < 0)
|
||||
goto err_gpio_dir;
|
||||
return rc;
|
||||
|
||||
if (man_id != 0x001f) {
|
||||
dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
|
||||
man_id >> 8, man_id & 0xFF);
|
||||
rc = -EINVAL;
|
||||
goto err_gpio_dir;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (part) {
|
||||
@ -1154,16 +1118,12 @@ static int at86rf230_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version);
|
||||
if (!ops) {
|
||||
rc = -ENOTSUPP;
|
||||
goto err_gpio_dir;
|
||||
}
|
||||
if (!ops)
|
||||
return -ENOTSUPP;
|
||||
|
||||
dev = ieee802154_alloc_device(sizeof(*lp), ops);
|
||||
if (!dev) {
|
||||
rc = -ENOMEM;
|
||||
goto err_gpio_dir;
|
||||
}
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
lp = dev->priv;
|
||||
lp->dev = dev;
|
||||
@ -1176,7 +1136,8 @@ static int at86rf230_probe(struct spi_device *spi)
|
||||
dev->extra_tx_headroom = 0;
|
||||
dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
|
||||
|
||||
if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
|
||||
irq_type = irq_get_trigger_type(spi->irq);
|
||||
if (irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
|
||||
irq_worker = at86rf230_irqwork;
|
||||
irq_handler = at86rf230_isr;
|
||||
} else {
|
||||
@ -1202,75 +1163,65 @@ static int at86rf230_probe(struct spi_device *spi)
|
||||
if (rc)
|
||||
goto err_hw_init;
|
||||
|
||||
rc = request_irq(spi->irq, irq_handler,
|
||||
IRQF_SHARED | pdata->irq_type,
|
||||
dev_name(&spi->dev), lp);
|
||||
if (rc)
|
||||
goto err_hw_init;
|
||||
|
||||
/* Read irq status register to reset irq line */
|
||||
rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
|
||||
if (rc)
|
||||
goto err_irq;
|
||||
goto err_hw_init;
|
||||
|
||||
rc = devm_request_irq(&spi->dev, spi->irq, irq_handler, IRQF_SHARED,
|
||||
dev_name(&spi->dev), lp);
|
||||
if (rc)
|
||||
goto err_hw_init;
|
||||
|
||||
rc = ieee802154_register_device(lp->dev);
|
||||
if (rc)
|
||||
goto err_irq;
|
||||
goto err_hw_init;
|
||||
|
||||
return rc;
|
||||
|
||||
err_irq:
|
||||
free_irq(spi->irq, lp);
|
||||
err_hw_init:
|
||||
flush_work(&lp->irqwork);
|
||||
spi_set_drvdata(spi, NULL);
|
||||
mutex_destroy(&lp->bmux);
|
||||
ieee802154_free_device(lp->dev);
|
||||
|
||||
err_gpio_dir:
|
||||
if (gpio_is_valid(pdata->slp_tr))
|
||||
gpio_free(pdata->slp_tr);
|
||||
err_slp_tr:
|
||||
if (gpio_is_valid(pdata->rstn))
|
||||
gpio_free(pdata->rstn);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int at86rf230_remove(struct spi_device *spi)
|
||||
{
|
||||
struct at86rf230_local *lp = spi_get_drvdata(spi);
|
||||
struct at86rf230_platform_data *pdata = spi->dev.platform_data;
|
||||
|
||||
/* mask all at86rf230 irq's */
|
||||
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
|
||||
ieee802154_unregister_device(lp->dev);
|
||||
|
||||
free_irq(spi->irq, lp);
|
||||
flush_work(&lp->irqwork);
|
||||
|
||||
if (gpio_is_valid(pdata->slp_tr))
|
||||
gpio_free(pdata->slp_tr);
|
||||
if (gpio_is_valid(pdata->rstn))
|
||||
gpio_free(pdata->rstn);
|
||||
|
||||
mutex_destroy(&lp->bmux);
|
||||
ieee802154_free_device(lp->dev);
|
||||
|
||||
dev_dbg(&spi->dev, "unregistered at86rf230\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static struct of_device_id at86rf230_of_match[] = {
|
||||
static const struct of_device_id at86rf230_of_match[] = {
|
||||
{ .compatible = "atmel,at86rf230", },
|
||||
{ .compatible = "atmel,at86rf231", },
|
||||
{ .compatible = "atmel,at86rf233", },
|
||||
{ .compatible = "atmel,at86rf212", },
|
||||
{ },
|
||||
};
|
||||
#endif
|
||||
MODULE_DEVICE_TABLE(of, at86rf230_of_match);
|
||||
|
||||
static const struct spi_device_id at86rf230_device_id[] = {
|
||||
{ .name = "at86rf230", },
|
||||
{ .name = "at86rf231", },
|
||||
{ .name = "at86rf233", },
|
||||
{ .name = "at86rf212", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, at86rf230_device_id);
|
||||
|
||||
static struct spi_driver at86rf230_driver = {
|
||||
.id_table = at86rf230_device_id,
|
||||
.driver = {
|
||||
.of_match_table = of_match_ptr(at86rf230_of_match),
|
||||
.name = "at86rf230",
|
||||
|
@ -26,20 +26,6 @@ struct at86rf230_platform_data {
|
||||
int rstn;
|
||||
int slp_tr;
|
||||
int dig2;
|
||||
|
||||
/* Setting the irq_type will configure the driver to request
|
||||
* the platform irq trigger type according to the given value
|
||||
* and configure the interrupt polarity of the device to the
|
||||
* corresponding polarity.
|
||||
*
|
||||
* Allowed values are: IRQF_TRIGGER_RISING, IRQF_TRIGGER_FALLING,
|
||||
* IRQF_TRIGGER_HIGH and IRQF_TRIGGER_LOW
|
||||
*
|
||||
* Setting it to 0, the driver does not touch the trigger type
|
||||
* configuration of the interrupt and sets the interrupt polarity
|
||||
* of the device to high active (the default value).
|
||||
*/
|
||||
int irq_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user