diff options
author | Alexander Aring <alex.aring@gmail.com> | 2014-07-02 18:20:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 00:29:24 -0400 |
commit | c8ee0f56c833d70a03f06bf809089423dd190ee8 (patch) | |
tree | 45b0d6fbb1878d9b79d485458a4633c9a808b975 /drivers/net/ieee802154 | |
parent | f76014f770ff2d4e26c82e4e3a5b0928dee1969b (diff) |
at86rf230: rework detect device handling
This patch drops the current lowlevel spi calls for the detect device
function instead we handle this via regmap. Also put the detection of
in a seperate function and set all device specific attributes while detection.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ieee802154')
-rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 183 |
1 files changed, 76 insertions, 107 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index e3697038bd6d..7d96cd410edb 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c | |||
@@ -410,57 +410,6 @@ static struct regmap_config at86rf230_regmap_spi_config = { | |||
410 | }; | 410 | }; |
411 | 411 | ||
412 | static int | 412 | static int |
413 | __at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part, | ||
414 | u8 *version) | ||
415 | { | ||
416 | u8 data[4]; | ||
417 | u8 *buf = kmalloc(2, GFP_KERNEL); | ||
418 | int status; | ||
419 | struct spi_message msg; | ||
420 | struct spi_transfer xfer = { | ||
421 | .len = 2, | ||
422 | .tx_buf = buf, | ||
423 | .rx_buf = buf, | ||
424 | }; | ||
425 | u8 reg; | ||
426 | |||
427 | if (!buf) | ||
428 | return -ENOMEM; | ||
429 | |||
430 | for (reg = RG_PART_NUM; reg <= RG_MAN_ID_1; reg++) { | ||
431 | buf[0] = (reg & CMD_REG_MASK) | CMD_REG; | ||
432 | buf[1] = 0xff; | ||
433 | dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]); | ||
434 | spi_message_init(&msg); | ||
435 | spi_message_add_tail(&xfer, &msg); | ||
436 | |||
437 | status = spi_sync(spi, &msg); | ||
438 | dev_vdbg(&spi->dev, "status = %d\n", status); | ||
439 | if (msg.status) | ||
440 | status = msg.status; | ||
441 | |||
442 | dev_vdbg(&spi->dev, "status = %d\n", status); | ||
443 | dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]); | ||
444 | dev_vdbg(&spi->dev, "buf[1] = %02x\n", buf[1]); | ||
445 | |||
446 | if (status == 0) | ||
447 | data[reg - RG_PART_NUM] = buf[1]; | ||
448 | else | ||
449 | break; | ||
450 | } | ||
451 | |||
452 | if (status == 0) { | ||
453 | *part = data[0]; | ||
454 | *version = data[1]; | ||
455 | *man_id = (data[3] << 8) | data[2]; | ||
456 | } | ||
457 | |||
458 | kfree(buf); | ||
459 | |||
460 | return status; | ||
461 | } | ||
462 | |||
463 | static int | ||
464 | at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len) | 413 | at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len) |
465 | { | 414 | { |
466 | u8 *buf = lp->buf; | 415 | u8 *buf = lp->buf; |
@@ -1080,18 +1029,87 @@ done: | |||
1080 | return pdata; | 1029 | return pdata; |
1081 | } | 1030 | } |
1082 | 1031 | ||
1032 | static int | ||
1033 | at86rf230_detect_device(struct at86rf230_local *lp) | ||
1034 | { | ||
1035 | unsigned int part, version, val; | ||
1036 | u16 man_id = 0; | ||
1037 | const char *chip; | ||
1038 | int rc; | ||
1039 | |||
1040 | rc = __at86rf230_read(lp, RG_MAN_ID_0, &val); | ||
1041 | if (rc) | ||
1042 | return rc; | ||
1043 | man_id |= val; | ||
1044 | |||
1045 | rc = __at86rf230_read(lp, RG_MAN_ID_1, &val); | ||
1046 | if (rc) | ||
1047 | return rc; | ||
1048 | man_id |= (val << 8); | ||
1049 | |||
1050 | rc = __at86rf230_read(lp, RG_PART_NUM, &part); | ||
1051 | if (rc) | ||
1052 | return rc; | ||
1053 | |||
1054 | rc = __at86rf230_read(lp, RG_PART_NUM, &version); | ||
1055 | if (rc) | ||
1056 | return rc; | ||
1057 | |||
1058 | if (man_id != 0x001f) { | ||
1059 | dev_err(&lp->spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n", | ||
1060 | man_id >> 8, man_id & 0xFF); | ||
1061 | return -EINVAL; | ||
1062 | } | ||
1063 | |||
1064 | lp->part = part; | ||
1065 | lp->vers = version; | ||
1066 | lp->dev->extra_tx_headroom = 0; | ||
1067 | lp->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK | | ||
1068 | IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA; | ||
1069 | |||
1070 | switch (part) { | ||
1071 | case 2: | ||
1072 | chip = "at86rf230"; | ||
1073 | rc = -ENOTSUPP; | ||
1074 | break; | ||
1075 | case 3: | ||
1076 | chip = "at86rf231"; | ||
1077 | lp->dev->phy->channels_supported[0] = 0x7FFF800; | ||
1078 | break; | ||
1079 | case 7: | ||
1080 | chip = "at86rf212"; | ||
1081 | if (version == 1) { | ||
1082 | lp->dev->flags |= IEEE802154_HW_LBT; | ||
1083 | lp->dev->phy->channels_supported[0] = 0x00007FF; | ||
1084 | lp->dev->phy->channels_supported[2] = 0x00007FF; | ||
1085 | } else { | ||
1086 | rc = -ENOTSUPP; | ||
1087 | } | ||
1088 | break; | ||
1089 | case 11: | ||
1090 | chip = "at86rf233"; | ||
1091 | lp->dev->phy->channels_supported[0] = 0x7FFF800; | ||
1092 | break; | ||
1093 | default: | ||
1094 | chip = "unkown"; | ||
1095 | rc = -ENOTSUPP; | ||
1096 | break; | ||
1097 | } | ||
1098 | |||
1099 | dev_info(&lp->spi->dev, "Detected %s chip version %d\n", chip, version); | ||
1100 | |||
1101 | return rc; | ||
1102 | } | ||
1103 | |||
1083 | static int at86rf230_probe(struct spi_device *spi) | 1104 | static int at86rf230_probe(struct spi_device *spi) |
1084 | { | 1105 | { |
1085 | struct at86rf230_platform_data *pdata; | 1106 | struct at86rf230_platform_data *pdata; |
1086 | struct ieee802154_dev *dev; | 1107 | struct ieee802154_dev *dev; |
1087 | struct at86rf230_local *lp; | 1108 | struct at86rf230_local *lp; |
1088 | u16 man_id = 0; | ||
1089 | u8 part = 0, version = 0; | ||
1090 | unsigned int status; | 1109 | unsigned int status; |
1091 | irq_handler_t irq_handler; | 1110 | irq_handler_t irq_handler; |
1092 | work_func_t irq_worker; | 1111 | work_func_t irq_worker; |
1093 | int rc, irq_type; | 1112 | int rc, irq_type; |
1094 | const char *chip; | ||
1095 | 1113 | ||
1096 | if (!spi->irq) { | 1114 | if (!spi->irq) { |
1097 | dev_err(&spi->dev, "no IRQ specified\n"); | 1115 | dev_err(&spi->dev, "no IRQ specified\n"); |
@@ -1133,54 +1151,8 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1133 | 1151 | ||
1134 | lp = dev->priv; | 1152 | lp = dev->priv; |
1135 | lp->dev = dev; | 1153 | lp->dev = dev; |
1136 | lp->part = part; | ||
1137 | lp->vers = version; | ||
1138 | |||
1139 | lp->spi = spi; | 1154 | lp->spi = spi; |
1140 | |||
1141 | dev->parent = &spi->dev; | 1155 | dev->parent = &spi->dev; |
1142 | dev->extra_tx_headroom = 0; | ||
1143 | dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK | | ||
1144 | IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA; | ||
1145 | |||
1146 | rc = __at86rf230_detect_device(spi, &man_id, &part, &version); | ||
1147 | if (rc < 0) | ||
1148 | goto free_dev; | ||
1149 | |||
1150 | if (man_id != 0x001f) { | ||
1151 | dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n", | ||
1152 | man_id >> 8, man_id & 0xFF); | ||
1153 | return -EINVAL; | ||
1154 | } | ||
1155 | |||
1156 | switch (part) { | ||
1157 | case 2: | ||
1158 | chip = "at86rf230"; | ||
1159 | rc = -ENOTSUPP; | ||
1160 | /* FIXME: should be easy to support; */ | ||
1161 | break; | ||
1162 | case 3: | ||
1163 | chip = "at86rf231"; | ||
1164 | break; | ||
1165 | case 7: | ||
1166 | chip = "at86rf212"; | ||
1167 | if (version == 1) | ||
1168 | dev->flags |= IEEE802154_HW_LBT; | ||
1169 | else | ||
1170 | rc = -ENOTSUPP; | ||
1171 | break; | ||
1172 | case 11: | ||
1173 | chip = "at86rf233"; | ||
1174 | break; | ||
1175 | default: | ||
1176 | chip = "UNKNOWN"; | ||
1177 | rc = -ENOTSUPP; | ||
1178 | break; | ||
1179 | } | ||
1180 | |||
1181 | dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version); | ||
1182 | if (rc < 0) | ||
1183 | goto free_dev; | ||
1184 | 1156 | ||
1185 | lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); | 1157 | lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); |
1186 | if (IS_ERR(lp->regmap)) { | 1158 | if (IS_ERR(lp->regmap)) { |
@@ -1190,6 +1162,10 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1190 | goto free_dev; | 1162 | goto free_dev; |
1191 | } | 1163 | } |
1192 | 1164 | ||
1165 | rc = at86rf230_detect_device(lp); | ||
1166 | if (rc < 0) | ||
1167 | goto free_dev; | ||
1168 | |||
1193 | irq_type = irq_get_trigger_type(spi->irq); | 1169 | irq_type = irq_get_trigger_type(spi->irq); |
1194 | if (!irq_type) | 1170 | if (!irq_type) |
1195 | irq_type = IRQF_TRIGGER_RISING; | 1171 | irq_type = IRQF_TRIGGER_RISING; |
@@ -1208,13 +1184,6 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1208 | 1184 | ||
1209 | spi_set_drvdata(spi, lp); | 1185 | spi_set_drvdata(spi, lp); |
1210 | 1186 | ||
1211 | if (is_rf212(lp)) { | ||
1212 | dev->phy->channels_supported[0] = 0x00007FF; | ||
1213 | dev->phy->channels_supported[2] = 0x00007FF; | ||
1214 | } else { | ||
1215 | dev->phy->channels_supported[0] = 0x7FFF800; | ||
1216 | } | ||
1217 | |||
1218 | rc = at86rf230_hw_init(lp); | 1187 | rc = at86rf230_hw_init(lp); |
1219 | if (rc) | 1188 | if (rc) |
1220 | goto err_hw_init; | 1189 | goto err_hw_init; |