diff options
Diffstat (limited to 'drivers/net/ieee802154/at86rf230.c')
-rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 133 |
1 files changed, 42 insertions, 91 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index e36f194673a4..4517b149ed07 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/irq.h> | ||
26 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
27 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
@@ -692,10 +693,7 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) | |||
692 | if (rc < 0) | 693 | if (rc < 0) |
693 | goto err_rx; | 694 | goto err_rx; |
694 | 695 | ||
695 | rc = at86rf230_start(dev); | 696 | return at86rf230_start(dev); |
696 | |||
697 | return rc; | ||
698 | |||
699 | err_rx: | 697 | err_rx: |
700 | at86rf230_start(dev); | 698 | at86rf230_start(dev); |
701 | err: | 699 | err: |
@@ -963,33 +961,24 @@ static irqreturn_t at86rf230_isr_level(int irq, void *data) | |||
963 | return at86rf230_isr(irq, data); | 961 | return at86rf230_isr(irq, data); |
964 | } | 962 | } |
965 | 963 | ||
966 | static int at86rf230_irq_polarity(struct at86rf230_local *lp, int pol) | ||
967 | { | ||
968 | return at86rf230_write_subreg(lp, SR_IRQ_POLARITY, pol); | ||
969 | } | ||
970 | |||
971 | static int at86rf230_hw_init(struct at86rf230_local *lp) | 964 | static int at86rf230_hw_init(struct at86rf230_local *lp) |
972 | { | 965 | { |
973 | struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data; | 966 | int rc, irq_pol, irq_type; |
974 | int rc, irq_pol; | 967 | u8 dvdd; |
975 | u8 status; | ||
976 | u8 csma_seed[2]; | 968 | u8 csma_seed[2]; |
977 | 969 | ||
978 | rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status); | ||
979 | if (rc) | ||
980 | return rc; | ||
981 | |||
982 | rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF); | 970 | rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF); |
983 | if (rc) | 971 | if (rc) |
984 | return rc; | 972 | return rc; |
985 | 973 | ||
974 | irq_type = irq_get_trigger_type(lp->spi->irq); | ||
986 | /* configure irq polarity, defaults to high active */ | 975 | /* configure irq polarity, defaults to high active */ |
987 | if (pdata->irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) | 976 | if (irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) |
988 | irq_pol = IRQ_ACTIVE_LOW; | 977 | irq_pol = IRQ_ACTIVE_LOW; |
989 | else | 978 | else |
990 | irq_pol = IRQ_ACTIVE_HIGH; | 979 | irq_pol = IRQ_ACTIVE_HIGH; |
991 | 980 | ||
992 | rc = at86rf230_irq_polarity(lp, irq_pol); | 981 | rc = at86rf230_write_subreg(lp, SR_IRQ_POLARITY, irq_pol); |
993 | if (rc) | 982 | if (rc) |
994 | return rc; | 983 | return rc; |
995 | 984 | ||
@@ -1017,10 +1006,10 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) | |||
1017 | /* Wait the next SLEEP cycle */ | 1006 | /* Wait the next SLEEP cycle */ |
1018 | msleep(100); | 1007 | msleep(100); |
1019 | 1008 | ||
1020 | rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status); | 1009 | rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &dvdd); |
1021 | if (rc) | 1010 | if (rc) |
1022 | return rc; | 1011 | return rc; |
1023 | if (!status) { | 1012 | if (!dvdd) { |
1024 | dev_err(&lp->spi->dev, "DVDD error\n"); | 1013 | dev_err(&lp->spi->dev, "DVDD error\n"); |
1025 | return -EINVAL; | 1014 | return -EINVAL; |
1026 | } | 1015 | } |
@@ -1032,7 +1021,6 @@ static struct at86rf230_platform_data * | |||
1032 | at86rf230_get_pdata(struct spi_device *spi) | 1021 | at86rf230_get_pdata(struct spi_device *spi) |
1033 | { | 1022 | { |
1034 | struct at86rf230_platform_data *pdata; | 1023 | struct at86rf230_platform_data *pdata; |
1035 | const char *irq_type; | ||
1036 | 1024 | ||
1037 | if (!IS_ENABLED(CONFIG_OF) || !spi->dev.of_node) | 1025 | if (!IS_ENABLED(CONFIG_OF) || !spi->dev.of_node) |
1038 | return spi->dev.platform_data; | 1026 | return spi->dev.platform_data; |
@@ -1044,19 +1032,6 @@ at86rf230_get_pdata(struct spi_device *spi) | |||
1044 | pdata->rstn = of_get_named_gpio(spi->dev.of_node, "reset-gpio", 0); | 1032 | pdata->rstn = of_get_named_gpio(spi->dev.of_node, "reset-gpio", 0); |
1045 | pdata->slp_tr = of_get_named_gpio(spi->dev.of_node, "sleep-gpio", 0); | 1033 | pdata->slp_tr = of_get_named_gpio(spi->dev.of_node, "sleep-gpio", 0); |
1046 | 1034 | ||
1047 | pdata->irq_type = IRQF_TRIGGER_RISING; | ||
1048 | of_property_read_string(spi->dev.of_node, "irq-type", &irq_type); | ||
1049 | if (!strcmp(irq_type, "level-high")) | ||
1050 | pdata->irq_type = IRQF_TRIGGER_HIGH; | ||
1051 | else if (!strcmp(irq_type, "level-low")) | ||
1052 | pdata->irq_type = IRQF_TRIGGER_LOW; | ||
1053 | else if (!strcmp(irq_type, "edge-rising")) | ||
1054 | pdata->irq_type = IRQF_TRIGGER_RISING; | ||
1055 | else if (!strcmp(irq_type, "edge-falling")) | ||
1056 | pdata->irq_type = IRQF_TRIGGER_FALLING; | ||
1057 | else | ||
1058 | dev_warn(&spi->dev, "wrong irq-type specified using edge-rising\n"); | ||
1059 | |||
1060 | spi->dev.platform_data = pdata; | 1035 | spi->dev.platform_data = pdata; |
1061 | done: | 1036 | done: |
1062 | return pdata; | 1037 | return pdata; |
@@ -1071,7 +1046,7 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1071 | u8 part = 0, version = 0, status; | 1046 | u8 part = 0, version = 0, status; |
1072 | irq_handler_t irq_handler; | 1047 | irq_handler_t irq_handler; |
1073 | work_func_t irq_worker; | 1048 | work_func_t irq_worker; |
1074 | int rc; | 1049 | int rc, irq_type; |
1075 | const char *chip; | 1050 | const char *chip; |
1076 | struct ieee802154_ops *ops = NULL; | 1051 | struct ieee802154_ops *ops = NULL; |
1077 | 1052 | ||
@@ -1087,27 +1062,17 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1087 | } | 1062 | } |
1088 | 1063 | ||
1089 | if (gpio_is_valid(pdata->rstn)) { | 1064 | if (gpio_is_valid(pdata->rstn)) { |
1090 | rc = gpio_request(pdata->rstn, "rstn"); | 1065 | rc = devm_gpio_request_one(&spi->dev, pdata->rstn, |
1066 | GPIOF_OUT_INIT_HIGH, "rstn"); | ||
1091 | if (rc) | 1067 | if (rc) |
1092 | return rc; | 1068 | return rc; |
1093 | } | 1069 | } |
1094 | 1070 | ||
1095 | if (gpio_is_valid(pdata->slp_tr)) { | 1071 | if (gpio_is_valid(pdata->slp_tr)) { |
1096 | rc = gpio_request(pdata->slp_tr, "slp_tr"); | 1072 | rc = devm_gpio_request_one(&spi->dev, pdata->slp_tr, |
1097 | if (rc) | 1073 | GPIOF_OUT_INIT_LOW, "slp_tr"); |
1098 | goto err_slp_tr; | ||
1099 | } | ||
1100 | |||
1101 | if (gpio_is_valid(pdata->rstn)) { | ||
1102 | rc = gpio_direction_output(pdata->rstn, 1); | ||
1103 | if (rc) | ||
1104 | goto err_gpio_dir; | ||
1105 | } | ||
1106 | |||
1107 | if (gpio_is_valid(pdata->slp_tr)) { | ||
1108 | rc = gpio_direction_output(pdata->slp_tr, 0); | ||
1109 | if (rc) | 1074 | if (rc) |
1110 | goto err_gpio_dir; | 1075 | return rc; |
1111 | } | 1076 | } |
1112 | 1077 | ||
1113 | /* Reset */ | 1078 | /* Reset */ |
@@ -1121,13 +1086,12 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1121 | 1086 | ||
1122 | rc = __at86rf230_detect_device(spi, &man_id, &part, &version); | 1087 | rc = __at86rf230_detect_device(spi, &man_id, &part, &version); |
1123 | if (rc < 0) | 1088 | if (rc < 0) |
1124 | goto err_gpio_dir; | 1089 | return rc; |
1125 | 1090 | ||
1126 | if (man_id != 0x001f) { | 1091 | if (man_id != 0x001f) { |
1127 | dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n", | 1092 | dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n", |
1128 | man_id >> 8, man_id & 0xFF); | 1093 | man_id >> 8, man_id & 0xFF); |
1129 | rc = -EINVAL; | 1094 | return -EINVAL; |
1130 | goto err_gpio_dir; | ||
1131 | } | 1095 | } |
1132 | 1096 | ||
1133 | switch (part) { | 1097 | switch (part) { |
@@ -1154,16 +1118,12 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1154 | } | 1118 | } |
1155 | 1119 | ||
1156 | dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version); | 1120 | dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version); |
1157 | if (!ops) { | 1121 | if (!ops) |
1158 | rc = -ENOTSUPP; | 1122 | return -ENOTSUPP; |
1159 | goto err_gpio_dir; | ||
1160 | } | ||
1161 | 1123 | ||
1162 | dev = ieee802154_alloc_device(sizeof(*lp), ops); | 1124 | dev = ieee802154_alloc_device(sizeof(*lp), ops); |
1163 | if (!dev) { | 1125 | if (!dev) |
1164 | rc = -ENOMEM; | 1126 | return -ENOMEM; |
1165 | goto err_gpio_dir; | ||
1166 | } | ||
1167 | 1127 | ||
1168 | lp = dev->priv; | 1128 | lp = dev->priv; |
1169 | lp->dev = dev; | 1129 | lp->dev = dev; |
@@ -1176,7 +1136,8 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1176 | dev->extra_tx_headroom = 0; | 1136 | dev->extra_tx_headroom = 0; |
1177 | dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK; | 1137 | dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK; |
1178 | 1138 | ||
1179 | if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { | 1139 | irq_type = irq_get_trigger_type(spi->irq); |
1140 | if (irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { | ||
1180 | irq_worker = at86rf230_irqwork; | 1141 | irq_worker = at86rf230_irqwork; |
1181 | irq_handler = at86rf230_isr; | 1142 | irq_handler = at86rf230_isr; |
1182 | } else { | 1143 | } else { |
@@ -1202,75 +1163,65 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1202 | if (rc) | 1163 | if (rc) |
1203 | goto err_hw_init; | 1164 | goto err_hw_init; |
1204 | 1165 | ||
1205 | rc = request_irq(spi->irq, irq_handler, | 1166 | /* Read irq status register to reset irq line */ |
1206 | IRQF_SHARED | pdata->irq_type, | 1167 | rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status); |
1207 | dev_name(&spi->dev), lp); | ||
1208 | if (rc) | 1168 | if (rc) |
1209 | goto err_hw_init; | 1169 | goto err_hw_init; |
1210 | 1170 | ||
1211 | /* Read irq status register to reset irq line */ | 1171 | rc = devm_request_irq(&spi->dev, spi->irq, irq_handler, IRQF_SHARED, |
1212 | rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status); | 1172 | dev_name(&spi->dev), lp); |
1213 | if (rc) | 1173 | if (rc) |
1214 | goto err_irq; | 1174 | goto err_hw_init; |
1215 | 1175 | ||
1216 | rc = ieee802154_register_device(lp->dev); | 1176 | rc = ieee802154_register_device(lp->dev); |
1217 | if (rc) | 1177 | if (rc) |
1218 | goto err_irq; | 1178 | goto err_hw_init; |
1219 | 1179 | ||
1220 | return rc; | 1180 | return rc; |
1221 | 1181 | ||
1222 | err_irq: | ||
1223 | free_irq(spi->irq, lp); | ||
1224 | err_hw_init: | 1182 | err_hw_init: |
1225 | flush_work(&lp->irqwork); | 1183 | flush_work(&lp->irqwork); |
1226 | spi_set_drvdata(spi, NULL); | ||
1227 | mutex_destroy(&lp->bmux); | 1184 | mutex_destroy(&lp->bmux); |
1228 | ieee802154_free_device(lp->dev); | 1185 | ieee802154_free_device(lp->dev); |
1229 | 1186 | ||
1230 | err_gpio_dir: | ||
1231 | if (gpio_is_valid(pdata->slp_tr)) | ||
1232 | gpio_free(pdata->slp_tr); | ||
1233 | err_slp_tr: | ||
1234 | if (gpio_is_valid(pdata->rstn)) | ||
1235 | gpio_free(pdata->rstn); | ||
1236 | return rc; | 1187 | return rc; |
1237 | } | 1188 | } |
1238 | 1189 | ||
1239 | static int at86rf230_remove(struct spi_device *spi) | 1190 | static int at86rf230_remove(struct spi_device *spi) |
1240 | { | 1191 | { |
1241 | struct at86rf230_local *lp = spi_get_drvdata(spi); | 1192 | struct at86rf230_local *lp = spi_get_drvdata(spi); |
1242 | struct at86rf230_platform_data *pdata = spi->dev.platform_data; | ||
1243 | 1193 | ||
1244 | /* mask all at86rf230 irq's */ | 1194 | /* mask all at86rf230 irq's */ |
1245 | at86rf230_write_subreg(lp, SR_IRQ_MASK, 0); | 1195 | at86rf230_write_subreg(lp, SR_IRQ_MASK, 0); |
1246 | ieee802154_unregister_device(lp->dev); | 1196 | ieee802154_unregister_device(lp->dev); |
1247 | |||
1248 | free_irq(spi->irq, lp); | ||
1249 | flush_work(&lp->irqwork); | 1197 | flush_work(&lp->irqwork); |
1250 | |||
1251 | if (gpio_is_valid(pdata->slp_tr)) | ||
1252 | gpio_free(pdata->slp_tr); | ||
1253 | if (gpio_is_valid(pdata->rstn)) | ||
1254 | gpio_free(pdata->rstn); | ||
1255 | |||
1256 | mutex_destroy(&lp->bmux); | 1198 | mutex_destroy(&lp->bmux); |
1257 | ieee802154_free_device(lp->dev); | 1199 | ieee802154_free_device(lp->dev); |
1258 | |||
1259 | dev_dbg(&spi->dev, "unregistered at86rf230\n"); | 1200 | dev_dbg(&spi->dev, "unregistered at86rf230\n"); |
1201 | |||
1260 | return 0; | 1202 | return 0; |
1261 | } | 1203 | } |
1262 | 1204 | ||
1263 | #if IS_ENABLED(CONFIG_OF) | 1205 | static const struct of_device_id at86rf230_of_match[] = { |
1264 | static struct of_device_id at86rf230_of_match[] = { | ||
1265 | { .compatible = "atmel,at86rf230", }, | 1206 | { .compatible = "atmel,at86rf230", }, |
1266 | { .compatible = "atmel,at86rf231", }, | 1207 | { .compatible = "atmel,at86rf231", }, |
1267 | { .compatible = "atmel,at86rf233", }, | 1208 | { .compatible = "atmel,at86rf233", }, |
1268 | { .compatible = "atmel,at86rf212", }, | 1209 | { .compatible = "atmel,at86rf212", }, |
1269 | { }, | 1210 | { }, |
1270 | }; | 1211 | }; |
1271 | #endif | 1212 | MODULE_DEVICE_TABLE(of, at86rf230_of_match); |
1213 | |||
1214 | static const struct spi_device_id at86rf230_device_id[] = { | ||
1215 | { .name = "at86rf230", }, | ||
1216 | { .name = "at86rf231", }, | ||
1217 | { .name = "at86rf233", }, | ||
1218 | { .name = "at86rf212", }, | ||
1219 | { }, | ||
1220 | }; | ||
1221 | MODULE_DEVICE_TABLE(spi, at86rf230_device_id); | ||
1272 | 1222 | ||
1273 | static struct spi_driver at86rf230_driver = { | 1223 | static struct spi_driver at86rf230_driver = { |
1224 | .id_table = at86rf230_device_id, | ||
1274 | .driver = { | 1225 | .driver = { |
1275 | .of_match_table = of_match_ptr(at86rf230_of_match), | 1226 | .of_match_table = of_match_ptr(at86rf230_of_match), |
1276 | .name = "at86rf230", | 1227 | .name = "at86rf230", |