Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ieee802154: Add NXP MCR20A IEEE 802.15.4 transceiver driver

The MCR20AVHM transceiver (or MCR20A) is a low power,
high-performance 2.4 GHz, IEEE 802.15.4 compliant transceiver.

This driver implements a subset of ieee802154_ops.
It has no support for CSMA due to lack of hardware support.
It has currently no support for its proprietary Dual-PAN feature.

https://www.nxp.com/docs/en/reference-manual/MCR20RM.pdf

Signed-off-by: Xue Liu <liuxuenetmail@gmail.com>
Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>

authored by

Xue Liu and committed by
Stefan Schmidt
8c6ad9cc 962d0ca2

+1923
+11
drivers/net/ieee802154/Kconfig
··· 104 104 exposes a debugfs node for each CA8210 instance which allows 105 105 direct use of the Cascoda API, exposing the 802.15.4 MAC 106 106 management entities. 107 + 108 + config IEEE802154_MCR20A 109 + tristate "MCR20A transceiver driver" 110 + depends on IEEE802154_DRIVERS && MAC802154 111 + depends on SPI 112 + ---help--- 113 + Say Y here to enable the MCR20A SPI 802.15.4 wireless 114 + controller. 115 + 116 + This driver can also be built as a module. To do so, say M here. 117 + the module will be called 'mcr20a'.
+1
drivers/net/ieee802154/Makefile
··· 6 6 obj-$(CONFIG_IEEE802154_ATUSB) += atusb.o 7 7 obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o 8 8 obj-$(CONFIG_IEEE802154_CA8210) += ca8210.o 9 + obj-$(CONFIG_IEEE802154_MCR20A) += mcr20a.o
+1413
drivers/net/ieee802154/mcr20a.c
··· 1 + /* 2 + * Driver for NXP MCR20A 802.15.4 Wireless-PAN Networking controller 3 + * 4 + * Copyright (C) 2018 Xue Liu <liuxuenetmail@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 8 + * as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + */ 16 + #include <linux/kernel.h> 17 + #include <linux/module.h> 18 + #include <linux/gpio.h> 19 + #include <linux/spi/spi.h> 20 + #include <linux/workqueue.h> 21 + #include <linux/interrupt.h> 22 + #include <linux/skbuff.h> 23 + #include <linux/of_gpio.h> 24 + #include <linux/regmap.h> 25 + #include <linux/ieee802154.h> 26 + #include <linux/debugfs.h> 27 + 28 + #include <net/mac802154.h> 29 + #include <net/cfg802154.h> 30 + 31 + #include <linux/device.h> 32 + 33 + #include "mcr20a.h" 34 + 35 + #define SPI_COMMAND_BUFFER 3 36 + 37 + #define REGISTER_READ BIT(7) 38 + #define REGISTER_WRITE (0 << 7) 39 + #define REGISTER_ACCESS (0 << 6) 40 + #define PACKET_BUFF_BURST_ACCESS BIT(6) 41 + #define PACKET_BUFF_BYTE_ACCESS BIT(5) 42 + 43 + #define MCR20A_WRITE_REG(x) (x) 44 + #define MCR20A_READ_REG(x) (REGISTER_READ | (x)) 45 + #define MCR20A_BURST_READ_PACKET_BUF (0xC0) 46 + #define MCR20A_BURST_WRITE_PACKET_BUF (0x40) 47 + 48 + #define MCR20A_CMD_REG 0x80 49 + #define MCR20A_CMD_REG_MASK 0x3f 50 + #define MCR20A_CMD_WRITE 0x40 51 + #define MCR20A_CMD_FB 0x20 52 + 53 + /* Number of Interrupt Request Status Register */ 54 + #define MCR20A_IRQSTS_NUM 2 /* only IRQ_STS1 and IRQ_STS2 */ 55 + 56 + /* MCR20A CCA Type */ 57 + enum { 58 + MCR20A_CCA_ED, // energy detect - CCA bit not active, 59 + // not to be used for T and CCCA sequences 60 + MCR20A_CCA_MODE1, // energy detect - CCA bit ACTIVE 61 + MCR20A_CCA_MODE2, // 802.15.4 compliant signal detect - CCA bit ACTIVE 62 + MCR20A_CCA_MODE3 63 + }; 64 + 65 + enum { 66 + MCR20A_XCVSEQ_IDLE = 0x00, 67 + MCR20A_XCVSEQ_RX = 0x01, 68 + MCR20A_XCVSEQ_TX = 0x02, 69 + MCR20A_XCVSEQ_CCA = 0x03, 70 + MCR20A_XCVSEQ_TR = 0x04, 71 + MCR20A_XCVSEQ_CCCA = 0x05, 72 + }; 73 + 74 + /* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */ 75 + #define MCR20A_MIN_CHANNEL (11) 76 + #define MCR20A_MAX_CHANNEL (26) 77 + #define MCR20A_CHANNEL_SPACING (5) 78 + 79 + /* MCR20A CCA Threshold constans */ 80 + #define MCR20A_MIN_CCA_THRESHOLD (0x6EU) 81 + #define MCR20A_MAX_CCA_THRESHOLD (0x00U) 82 + 83 + /* version 0C */ 84 + #define MCR20A_OVERWRITE_VERSION (0x0C) 85 + 86 + /* MCR20A PLL configurations */ 87 + static const u8 PLL_INT[16] = { 88 + /* 2405 */ 0x0B, /* 2410 */ 0x0B, /* 2415 */ 0x0B, 89 + /* 2420 */ 0x0B, /* 2425 */ 0x0B, /* 2430 */ 0x0B, 90 + /* 2435 */ 0x0C, /* 2440 */ 0x0C, /* 2445 */ 0x0C, 91 + /* 2450 */ 0x0C, /* 2455 */ 0x0C, /* 2460 */ 0x0C, 92 + /* 2465 */ 0x0D, /* 2470 */ 0x0D, /* 2475 */ 0x0D, 93 + /* 2480 */ 0x0D 94 + }; 95 + 96 + static const u8 PLL_FRAC[16] = { 97 + /* 2405 */ 0x28, /* 2410 */ 0x50, /* 2415 */ 0x78, 98 + /* 2420 */ 0xA0, /* 2425 */ 0xC8, /* 2430 */ 0xF0, 99 + /* 2435 */ 0x18, /* 2440 */ 0x40, /* 2445 */ 0x68, 100 + /* 2450 */ 0x90, /* 2455 */ 0xB8, /* 2460 */ 0xE0, 101 + /* 2465 */ 0x08, /* 2470 */ 0x30, /* 2475 */ 0x58, 102 + /* 2480 */ 0x80 103 + }; 104 + 105 + static const struct reg_sequence mar20a_iar_overwrites[] = { 106 + { IAR_MISC_PAD_CTRL, 0x02 }, 107 + { IAR_VCO_CTRL1, 0xB3 }, 108 + { IAR_VCO_CTRL2, 0x07 }, 109 + { IAR_PA_TUNING, 0x71 }, 110 + { IAR_CHF_IBUF, 0x2F }, 111 + { IAR_CHF_QBUF, 0x2F }, 112 + { IAR_CHF_IRIN, 0x24 }, 113 + { IAR_CHF_QRIN, 0x24 }, 114 + { IAR_CHF_IL, 0x24 }, 115 + { IAR_CHF_QL, 0x24 }, 116 + { IAR_CHF_CC1, 0x32 }, 117 + { IAR_CHF_CCL, 0x1D }, 118 + { IAR_CHF_CC2, 0x2D }, 119 + { IAR_CHF_IROUT, 0x24 }, 120 + { IAR_CHF_QROUT, 0x24 }, 121 + { IAR_PA_CAL, 0x28 }, 122 + { IAR_AGC_THR1, 0x55 }, 123 + { IAR_AGC_THR2, 0x2D }, 124 + { IAR_ATT_RSSI1, 0x5F }, 125 + { IAR_ATT_RSSI2, 0x8F }, 126 + { IAR_RSSI_OFFSET, 0x61 }, 127 + { IAR_CHF_PMA_GAIN, 0x03 }, 128 + { IAR_CCA1_THRESH, 0x50 }, 129 + { IAR_CORR_NVAL, 0x13 }, 130 + { IAR_ACKDELAY, 0x3D }, 131 + }; 132 + 133 + #define MCR20A_VALID_CHANNELS (0x07FFF800) 134 + 135 + struct mcr20a_platform_data { 136 + int rst_gpio; 137 + }; 138 + 139 + #define MCR20A_MAX_BUF (127) 140 + 141 + #define printdev(X) (&X->spi->dev) 142 + 143 + /* regmap information for Direct Access Register (DAR) access */ 144 + #define MCR20A_DAR_WRITE 0x01 145 + #define MCR20A_DAR_READ 0x00 146 + #define MCR20A_DAR_NUMREGS 0x3F 147 + 148 + /* regmap information for Indirect Access Register (IAR) access */ 149 + #define MCR20A_IAR_ACCESS 0x80 150 + #define MCR20A_IAR_NUMREGS 0xBEFF 151 + 152 + /* Read/Write SPI Commands for DAR and IAR registers. */ 153 + #define MCR20A_READSHORT(reg) ((reg) << 1) 154 + #define MCR20A_WRITESHORT(reg) ((reg) << 1 | 1) 155 + #define MCR20A_READLONG(reg) (1 << 15 | (reg) << 5) 156 + #define MCR20A_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4) 157 + 158 + /* Type definitions for link configuration of instantiable layers */ 159 + #define MCR20A_PHY_INDIRECT_QUEUE_SIZE (12) 160 + 161 + static bool 162 + mcr20a_dar_writeable(struct device *dev, unsigned int reg) 163 + { 164 + switch (reg) { 165 + case DAR_IRQ_STS1: 166 + case DAR_IRQ_STS2: 167 + case DAR_IRQ_STS3: 168 + case DAR_PHY_CTRL1: 169 + case DAR_PHY_CTRL2: 170 + case DAR_PHY_CTRL3: 171 + case DAR_PHY_CTRL4: 172 + case DAR_SRC_CTRL: 173 + case DAR_SRC_ADDRS_SUM_LSB: 174 + case DAR_SRC_ADDRS_SUM_MSB: 175 + case DAR_T3CMP_LSB: 176 + case DAR_T3CMP_MSB: 177 + case DAR_T3CMP_USB: 178 + case DAR_T2PRIMECMP_LSB: 179 + case DAR_T2PRIMECMP_MSB: 180 + case DAR_T1CMP_LSB: 181 + case DAR_T1CMP_MSB: 182 + case DAR_T1CMP_USB: 183 + case DAR_T2CMP_LSB: 184 + case DAR_T2CMP_MSB: 185 + case DAR_T2CMP_USB: 186 + case DAR_T4CMP_LSB: 187 + case DAR_T4CMP_MSB: 188 + case DAR_T4CMP_USB: 189 + case DAR_PLL_INT0: 190 + case DAR_PLL_FRAC0_LSB: 191 + case DAR_PLL_FRAC0_MSB: 192 + case DAR_PA_PWR: 193 + /* no DAR_ACM */ 194 + case DAR_OVERWRITE_VER: 195 + case DAR_CLK_OUT_CTRL: 196 + case DAR_PWR_MODES: 197 + return true; 198 + default: 199 + return false; 200 + } 201 + } 202 + 203 + static bool 204 + mcr20a_dar_readable(struct device *dev, unsigned int reg) 205 + { 206 + bool rc; 207 + 208 + /* all writeable are also readable */ 209 + rc = mcr20a_dar_writeable(dev, reg); 210 + if (rc) 211 + return rc; 212 + 213 + /* readonly regs */ 214 + switch (reg) { 215 + case DAR_RX_FRM_LEN: 216 + case DAR_CCA1_ED_FNL: 217 + case DAR_EVENT_TMR_LSB: 218 + case DAR_EVENT_TMR_MSB: 219 + case DAR_EVENT_TMR_USB: 220 + case DAR_TIMESTAMP_LSB: 221 + case DAR_TIMESTAMP_MSB: 222 + case DAR_TIMESTAMP_USB: 223 + case DAR_SEQ_STATE: 224 + case DAR_LQI_VALUE: 225 + case DAR_RSSI_CCA_CONT: 226 + return true; 227 + default: 228 + return false; 229 + } 230 + } 231 + 232 + static bool 233 + mcr20a_dar_volatile(struct device *dev, unsigned int reg) 234 + { 235 + /* can be changed during runtime */ 236 + switch (reg) { 237 + case DAR_IRQ_STS1: 238 + case DAR_IRQ_STS2: 239 + case DAR_IRQ_STS3: 240 + /* use them in spi_async and regmap so it's volatile */ 241 + return true; 242 + default: 243 + return false; 244 + } 245 + } 246 + 247 + static bool 248 + mcr20a_dar_precious(struct device *dev, unsigned int reg) 249 + { 250 + /* don't clear irq line on read */ 251 + switch (reg) { 252 + case DAR_IRQ_STS1: 253 + case DAR_IRQ_STS2: 254 + case DAR_IRQ_STS3: 255 + return true; 256 + default: 257 + return false; 258 + } 259 + } 260 + 261 + static const struct regmap_config mcr20a_dar_regmap = { 262 + .name = "mcr20a_dar", 263 + .reg_bits = 8, 264 + .val_bits = 8, 265 + .write_flag_mask = REGISTER_ACCESS | REGISTER_WRITE, 266 + .read_flag_mask = REGISTER_ACCESS | REGISTER_READ, 267 + .cache_type = REGCACHE_RBTREE, 268 + .writeable_reg = mcr20a_dar_writeable, 269 + .readable_reg = mcr20a_dar_readable, 270 + .volatile_reg = mcr20a_dar_volatile, 271 + .precious_reg = mcr20a_dar_precious, 272 + .fast_io = true, 273 + .can_multi_write = true, 274 + }; 275 + 276 + static bool 277 + mcr20a_iar_writeable(struct device *dev, unsigned int reg) 278 + { 279 + switch (reg) { 280 + case IAR_XTAL_TRIM: 281 + case IAR_PMC_LP_TRIM: 282 + case IAR_MACPANID0_LSB: 283 + case IAR_MACPANID0_MSB: 284 + case IAR_MACSHORTADDRS0_LSB: 285 + case IAR_MACSHORTADDRS0_MSB: 286 + case IAR_MACLONGADDRS0_0: 287 + case IAR_MACLONGADDRS0_8: 288 + case IAR_MACLONGADDRS0_16: 289 + case IAR_MACLONGADDRS0_24: 290 + case IAR_MACLONGADDRS0_32: 291 + case IAR_MACLONGADDRS0_40: 292 + case IAR_MACLONGADDRS0_48: 293 + case IAR_MACLONGADDRS0_56: 294 + case IAR_RX_FRAME_FILTER: 295 + case IAR_PLL_INT1: 296 + case IAR_PLL_FRAC1_LSB: 297 + case IAR_PLL_FRAC1_MSB: 298 + case IAR_MACPANID1_LSB: 299 + case IAR_MACPANID1_MSB: 300 + case IAR_MACSHORTADDRS1_LSB: 301 + case IAR_MACSHORTADDRS1_MSB: 302 + case IAR_MACLONGADDRS1_0: 303 + case IAR_MACLONGADDRS1_8: 304 + case IAR_MACLONGADDRS1_16: 305 + case IAR_MACLONGADDRS1_24: 306 + case IAR_MACLONGADDRS1_32: 307 + case IAR_MACLONGADDRS1_40: 308 + case IAR_MACLONGADDRS1_48: 309 + case IAR_MACLONGADDRS1_56: 310 + case IAR_DUAL_PAN_CTRL: 311 + case IAR_DUAL_PAN_DWELL: 312 + case IAR_CCA1_THRESH: 313 + case IAR_CCA1_ED_OFFSET_COMP: 314 + case IAR_LQI_OFFSET_COMP: 315 + case IAR_CCA_CTRL: 316 + case IAR_CCA2_CORR_PEAKS: 317 + case IAR_CCA2_CORR_THRESH: 318 + case IAR_TMR_PRESCALE: 319 + case IAR_ANT_PAD_CTRL: 320 + case IAR_MISC_PAD_CTRL: 321 + case IAR_BSM_CTRL: 322 + case IAR_RNG: 323 + case IAR_RX_WTR_MARK: 324 + case IAR_SOFT_RESET: 325 + case IAR_TXDELAY: 326 + case IAR_ACKDELAY: 327 + case IAR_CORR_NVAL: 328 + case IAR_ANT_AGC_CTRL: 329 + case IAR_AGC_THR1: 330 + case IAR_AGC_THR2: 331 + case IAR_PA_CAL: 332 + case IAR_ATT_RSSI1: 333 + case IAR_ATT_RSSI2: 334 + case IAR_RSSI_OFFSET: 335 + case IAR_XTAL_CTRL: 336 + case IAR_CHF_PMA_GAIN: 337 + case IAR_CHF_IBUF: 338 + case IAR_CHF_QBUF: 339 + case IAR_CHF_IRIN: 340 + case IAR_CHF_QRIN: 341 + case IAR_CHF_IL: 342 + case IAR_CHF_QL: 343 + case IAR_CHF_CC1: 344 + case IAR_CHF_CCL: 345 + case IAR_CHF_CC2: 346 + case IAR_CHF_IROUT: 347 + case IAR_CHF_QROUT: 348 + case IAR_PA_TUNING: 349 + case IAR_VCO_CTRL1: 350 + case IAR_VCO_CTRL2: 351 + return true; 352 + default: 353 + return false; 354 + } 355 + } 356 + 357 + static bool 358 + mcr20a_iar_readable(struct device *dev, unsigned int reg) 359 + { 360 + bool rc; 361 + 362 + /* all writeable are also readable */ 363 + rc = mcr20a_iar_writeable(dev, reg); 364 + if (rc) 365 + return rc; 366 + 367 + /* readonly regs */ 368 + switch (reg) { 369 + case IAR_PART_ID: 370 + case IAR_DUAL_PAN_STS: 371 + case IAR_RX_BYTE_COUNT: 372 + case IAR_FILTERFAIL_CODE1: 373 + case IAR_FILTERFAIL_CODE2: 374 + case IAR_RSSI: 375 + return true; 376 + default: 377 + return false; 378 + } 379 + } 380 + 381 + static bool 382 + mcr20a_iar_volatile(struct device *dev, unsigned int reg) 383 + { 384 + /* can be changed during runtime */ 385 + switch (reg) { 386 + case IAR_DUAL_PAN_STS: 387 + case IAR_RX_BYTE_COUNT: 388 + case IAR_FILTERFAIL_CODE1: 389 + case IAR_FILTERFAIL_CODE2: 390 + case IAR_RSSI: 391 + return true; 392 + default: 393 + return false; 394 + } 395 + } 396 + 397 + static const struct regmap_config mcr20a_iar_regmap = { 398 + .name = "mcr20a_iar", 399 + .reg_bits = 16, 400 + .val_bits = 8, 401 + .write_flag_mask = REGISTER_ACCESS | REGISTER_WRITE | IAR_INDEX, 402 + .read_flag_mask = REGISTER_ACCESS | REGISTER_READ | IAR_INDEX, 403 + .cache_type = REGCACHE_RBTREE, 404 + .writeable_reg = mcr20a_iar_writeable, 405 + .readable_reg = mcr20a_iar_readable, 406 + .volatile_reg = mcr20a_iar_volatile, 407 + .fast_io = true, 408 + }; 409 + 410 + struct mcr20a_local { 411 + struct spi_device *spi; 412 + 413 + struct ieee802154_hw *hw; 414 + struct mcr20a_platform_data *pdata; 415 + struct regmap *regmap_dar; 416 + struct regmap *regmap_iar; 417 + 418 + u8 *buf; 419 + 420 + bool is_tx; 421 + 422 + /* for writing tx buffer */ 423 + struct spi_message tx_buf_msg; 424 + u8 tx_header[1]; 425 + /* burst buffer write command */ 426 + struct spi_transfer tx_xfer_header; 427 + u8 tx_len[1]; 428 + /* len of tx packet */ 429 + struct spi_transfer tx_xfer_len; 430 + /* data of tx packet */ 431 + struct spi_transfer tx_xfer_buf; 432 + struct sk_buff *tx_skb; 433 + 434 + /* for read length rxfifo */ 435 + struct spi_message reg_msg; 436 + u8 reg_cmd[1]; 437 + u8 reg_data[MCR20A_IRQSTS_NUM]; 438 + struct spi_transfer reg_xfer_cmd; 439 + struct spi_transfer reg_xfer_data; 440 + 441 + /* receive handling */ 442 + struct spi_message rx_buf_msg; 443 + u8 rx_header[1]; 444 + struct spi_transfer rx_xfer_header; 445 + u8 rx_lqi[1]; 446 + struct spi_transfer rx_xfer_lqi; 447 + u8 rx_buf[MCR20A_MAX_BUF]; 448 + struct spi_transfer rx_xfer_buf; 449 + 450 + /* isr handling for reading intstat */ 451 + struct spi_message irq_msg; 452 + u8 irq_header[1]; 453 + u8 irq_data[MCR20A_IRQSTS_NUM]; 454 + struct spi_transfer irq_xfer_data; 455 + struct spi_transfer irq_xfer_header; 456 + }; 457 + 458 + static void 459 + mcr20a_write_tx_buf_complete(void *context) 460 + { 461 + struct mcr20a_local *lp = context; 462 + int ret; 463 + 464 + dev_dbg(printdev(lp), "%s\n", __func__); 465 + 466 + lp->reg_msg.complete = NULL; 467 + lp->reg_cmd[0] = MCR20A_WRITE_REG(DAR_PHY_CTRL1); 468 + lp->reg_data[0] = MCR20A_XCVSEQ_TX; 469 + lp->reg_xfer_data.len = 1; 470 + 471 + ret = spi_async(lp->spi, &lp->reg_msg); 472 + if (ret) 473 + dev_err(printdev(lp), "failed to set SEQ TX\n"); 474 + } 475 + 476 + static int 477 + mcr20a_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) 478 + { 479 + struct mcr20a_local *lp = hw->priv; 480 + 481 + dev_dbg(printdev(lp), "%s\n", __func__); 482 + 483 + lp->tx_skb = skb; 484 + 485 + print_hex_dump_debug("mcr20a tx: ", DUMP_PREFIX_OFFSET, 16, 1, 486 + skb->data, skb->len, 0); 487 + 488 + lp->is_tx = 1; 489 + 490 + lp->reg_msg.complete = NULL; 491 + lp->reg_cmd[0] = MCR20A_WRITE_REG(DAR_PHY_CTRL1); 492 + lp->reg_data[0] = MCR20A_XCVSEQ_IDLE; 493 + lp->reg_xfer_data.len = 1; 494 + 495 + return spi_async(lp->spi, &lp->reg_msg); 496 + } 497 + 498 + static int 499 + mcr20a_ed(struct ieee802154_hw *hw, u8 *level) 500 + { 501 + WARN_ON(!level); 502 + *level = 0xbe; 503 + return 0; 504 + } 505 + 506 + static int 507 + mcr20a_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) 508 + { 509 + struct mcr20a_local *lp = hw->priv; 510 + int ret; 511 + 512 + dev_dbg(printdev(lp), "%s\n", __func__); 513 + 514 + /* freqency = ((PLL_INT+64) + (PLL_FRAC/65536)) * 32 MHz */ 515 + ret = regmap_write(lp->regmap_dar, DAR_PLL_INT0, PLL_INT[channel - 11]); 516 + if (ret) 517 + return ret; 518 + ret = regmap_write(lp->regmap_dar, DAR_PLL_FRAC0_LSB, 0x00); 519 + if (ret) 520 + return ret; 521 + ret = regmap_write(lp->regmap_dar, DAR_PLL_FRAC0_MSB, 522 + PLL_FRAC[channel - 11]); 523 + if (ret) 524 + return ret; 525 + 526 + return 0; 527 + } 528 + 529 + static int 530 + mcr20a_start(struct ieee802154_hw *hw) 531 + { 532 + struct mcr20a_local *lp = hw->priv; 533 + int ret; 534 + 535 + dev_dbg(printdev(lp), "%s\n", __func__); 536 + 537 + /* No slotted operation */ 538 + dev_dbg(printdev(lp), "no slotted operation\n"); 539 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL1, 540 + DAR_PHY_CTRL1_SLOTTED, 0x0); 541 + 542 + /* enable irq */ 543 + enable_irq(lp->spi->irq); 544 + 545 + /* Unmask SEQ interrupt */ 546 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL2, 547 + DAR_PHY_CTRL2_SEQMSK, 0x0); 548 + 549 + /* Start the RX sequence */ 550 + dev_dbg(printdev(lp), "start the RX sequence\n"); 551 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL1, 552 + DAR_PHY_CTRL1_XCVSEQ_MASK, MCR20A_XCVSEQ_RX); 553 + 554 + return 0; 555 + } 556 + 557 + static void 558 + mcr20a_stop(struct ieee802154_hw *hw) 559 + { 560 + struct mcr20a_local *lp = hw->priv; 561 + 562 + dev_dbg(printdev(lp), "%s\n", __func__); 563 + 564 + /* stop all running sequence */ 565 + regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL1, 566 + DAR_PHY_CTRL1_XCVSEQ_MASK, MCR20A_XCVSEQ_IDLE); 567 + 568 + /* disable irq */ 569 + disable_irq(lp->spi->irq); 570 + } 571 + 572 + static int 573 + mcr20a_set_hw_addr_filt(struct ieee802154_hw *hw, 574 + struct ieee802154_hw_addr_filt *filt, 575 + unsigned long changed) 576 + { 577 + struct mcr20a_local *lp = hw->priv; 578 + 579 + dev_dbg(printdev(lp), "%s\n", __func__); 580 + 581 + if (changed & IEEE802154_AFILT_SADDR_CHANGED) { 582 + u16 addr = le16_to_cpu(filt->short_addr); 583 + 584 + regmap_write(lp->regmap_iar, IAR_MACSHORTADDRS0_LSB, addr); 585 + regmap_write(lp->regmap_iar, IAR_MACSHORTADDRS0_MSB, addr >> 8); 586 + } 587 + 588 + if (changed & IEEE802154_AFILT_PANID_CHANGED) { 589 + u16 pan = le16_to_cpu(filt->pan_id); 590 + 591 + regmap_write(lp->regmap_iar, IAR_MACPANID0_LSB, pan); 592 + regmap_write(lp->regmap_iar, IAR_MACPANID0_MSB, pan >> 8); 593 + } 594 + 595 + if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) { 596 + u8 addr[8], i; 597 + 598 + memcpy(addr, &filt->ieee_addr, 8); 599 + for (i = 0; i < 8; i++) 600 + regmap_write(lp->regmap_iar, 601 + IAR_MACLONGADDRS0_0 + i, addr[i]); 602 + } 603 + 604 + if (changed & IEEE802154_AFILT_PANC_CHANGED) { 605 + if (filt->pan_coord) { 606 + regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL4, 607 + DAR_PHY_CTRL4_PANCORDNTR0, 0x10); 608 + } else { 609 + regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL4, 610 + DAR_PHY_CTRL4_PANCORDNTR0, 0x00); 611 + } 612 + } 613 + 614 + return 0; 615 + } 616 + 617 + /* -30 dBm to 10 dBm */ 618 + #define MCR20A_MAX_TX_POWERS 0x14 619 + static const s32 mcr20a_powers[MCR20A_MAX_TX_POWERS + 1] = { 620 + -3000, -2800, -2600, -2400, -2200, -2000, -1800, -1600, -1400, 621 + -1200, -1000, -800, -600, -400, -200, 0, 200, 400, 600, 800, 1000 622 + }; 623 + 624 + static int 625 + mcr20a_set_txpower(struct ieee802154_hw *hw, s32 mbm) 626 + { 627 + struct mcr20a_local *lp = hw->priv; 628 + u32 i; 629 + 630 + dev_dbg(printdev(lp), "%s(%d)\n", __func__, mbm); 631 + 632 + for (i = 0; i < lp->hw->phy->supported.tx_powers_size; i++) { 633 + if (lp->hw->phy->supported.tx_powers[i] == mbm) 634 + return regmap_write(lp->regmap_dar, DAR_PA_PWR, 635 + ((i + 8) & 0x1F)); 636 + } 637 + 638 + return -EINVAL; 639 + } 640 + 641 + #define MCR20A_MAX_ED_LEVELS MCR20A_MIN_CCA_THRESHOLD 642 + static s32 mcr20a_ed_levels[MCR20A_MAX_ED_LEVELS + 1]; 643 + 644 + static int 645 + mcr20a_set_cca_mode(struct ieee802154_hw *hw, 646 + const struct wpan_phy_cca *cca) 647 + { 648 + struct mcr20a_local *lp = hw->priv; 649 + unsigned int cca_mode = 0xff; 650 + bool cca_mode_and = false; 651 + int ret; 652 + 653 + dev_dbg(printdev(lp), "%s\n", __func__); 654 + 655 + /* mapping 802.15.4 to driver spec */ 656 + switch (cca->mode) { 657 + case NL802154_CCA_ENERGY: 658 + cca_mode = MCR20A_CCA_MODE1; 659 + break; 660 + case NL802154_CCA_CARRIER: 661 + cca_mode = MCR20A_CCA_MODE2; 662 + break; 663 + case NL802154_CCA_ENERGY_CARRIER: 664 + switch (cca->opt) { 665 + case NL802154_CCA_OPT_ENERGY_CARRIER_AND: 666 + cca_mode = MCR20A_CCA_MODE3; 667 + cca_mode_and = true; 668 + break; 669 + case NL802154_CCA_OPT_ENERGY_CARRIER_OR: 670 + cca_mode = MCR20A_CCA_MODE3; 671 + cca_mode_and = false; 672 + break; 673 + default: 674 + return -EINVAL; 675 + } 676 + break; 677 + default: 678 + return -EINVAL; 679 + } 680 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL4, 681 + DAR_PHY_CTRL4_CCATYPE_MASK, 682 + cca_mode << DAR_PHY_CTRL4_CCATYPE_SHIFT); 683 + if (ret < 0) 684 + return ret; 685 + 686 + if (cca_mode == MCR20A_CCA_MODE3) { 687 + if (cca_mode_and) { 688 + ret = regmap_update_bits(lp->regmap_iar, IAR_CCA_CTRL, 689 + IAR_CCA_CTRL_CCA3_AND_NOT_OR, 690 + 0x08); 691 + } else { 692 + ret = regmap_update_bits(lp->regmap_iar, 693 + IAR_CCA_CTRL, 694 + IAR_CCA_CTRL_CCA3_AND_NOT_OR, 695 + 0x00); 696 + } 697 + if (ret < 0) 698 + return ret; 699 + } 700 + 701 + return ret; 702 + } 703 + 704 + static int 705 + mcr20a_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) 706 + { 707 + struct mcr20a_local *lp = hw->priv; 708 + u32 i; 709 + 710 + dev_dbg(printdev(lp), "%s\n", __func__); 711 + 712 + for (i = 0; i < hw->phy->supported.cca_ed_levels_size; i++) { 713 + if (hw->phy->supported.cca_ed_levels[i] == mbm) 714 + return regmap_write(lp->regmap_iar, IAR_CCA1_THRESH, i); 715 + } 716 + 717 + return 0; 718 + } 719 + 720 + static int 721 + mcr20a_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on) 722 + { 723 + struct mcr20a_local *lp = hw->priv; 724 + int ret; 725 + u8 rx_frame_filter_reg = 0x0; 726 + u8 val; 727 + 728 + dev_dbg(printdev(lp), "%s(%d)\n", __func__, on); 729 + 730 + if (on) { 731 + /* All frame types accepted*/ 732 + val |= DAR_PHY_CTRL4_PROMISCUOUS; 733 + rx_frame_filter_reg &= ~(IAR_RX_FRAME_FLT_FRM_VER); 734 + rx_frame_filter_reg |= (IAR_RX_FRAME_FLT_ACK_FT | 735 + IAR_RX_FRAME_FLT_NS_FT); 736 + 737 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL4, 738 + DAR_PHY_CTRL4_PROMISCUOUS, 739 + DAR_PHY_CTRL4_PROMISCUOUS); 740 + if (ret < 0) 741 + return ret; 742 + 743 + ret = regmap_write(lp->regmap_iar, IAR_RX_FRAME_FILTER, 744 + rx_frame_filter_reg); 745 + if (ret < 0) 746 + return ret; 747 + } else { 748 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL4, 749 + DAR_PHY_CTRL4_PROMISCUOUS, 0x0); 750 + if (ret < 0) 751 + return ret; 752 + 753 + ret = regmap_write(lp->regmap_iar, IAR_RX_FRAME_FILTER, 754 + IAR_RX_FRAME_FLT_FRM_VER | 755 + IAR_RX_FRAME_FLT_BEACON_FT | 756 + IAR_RX_FRAME_FLT_DATA_FT | 757 + IAR_RX_FRAME_FLT_CMD_FT); 758 + if (ret < 0) 759 + return ret; 760 + } 761 + 762 + return 0; 763 + } 764 + 765 + static const struct ieee802154_ops mcr20a_hw_ops = { 766 + .owner = THIS_MODULE, 767 + .xmit_async = mcr20a_xmit, 768 + .ed = mcr20a_ed, 769 + .set_channel = mcr20a_set_channel, 770 + .start = mcr20a_start, 771 + .stop = mcr20a_stop, 772 + .set_hw_addr_filt = mcr20a_set_hw_addr_filt, 773 + .set_txpower = mcr20a_set_txpower, 774 + .set_cca_mode = mcr20a_set_cca_mode, 775 + .set_cca_ed_level = mcr20a_set_cca_ed_level, 776 + .set_promiscuous_mode = mcr20a_set_promiscuous_mode, 777 + }; 778 + 779 + static int 780 + mcr20a_request_rx(struct mcr20a_local *lp) 781 + { 782 + dev_dbg(printdev(lp), "%s\n", __func__); 783 + 784 + /* Start the RX sequence */ 785 + regmap_update_bits_async(lp->regmap_dar, DAR_PHY_CTRL1, 786 + DAR_PHY_CTRL1_XCVSEQ_MASK, MCR20A_XCVSEQ_RX); 787 + 788 + return 0; 789 + } 790 + 791 + static void 792 + mcr20a_handle_rx_read_buf_complete(void *context) 793 + { 794 + struct mcr20a_local *lp = context; 795 + u8 len = lp->reg_data[0] & DAR_RX_FRAME_LENGTH_MASK; 796 + struct sk_buff *skb; 797 + 798 + dev_dbg(printdev(lp), "%s\n", __func__); 799 + 800 + dev_dbg(printdev(lp), "RX is done\n"); 801 + 802 + if (!ieee802154_is_valid_psdu_len(len)) { 803 + dev_vdbg(&lp->spi->dev, "corrupted frame received\n"); 804 + len = IEEE802154_MTU; 805 + } 806 + 807 + len = len - 2; /* get rid of frame check field */ 808 + 809 + skb = dev_alloc_skb(len); 810 + if (!skb) 811 + return; 812 + 813 + memcpy(skb_put(skb, len), lp->rx_buf, len); 814 + ieee802154_rx_irqsafe(lp->hw, skb, lp->rx_lqi[0]); 815 + 816 + print_hex_dump_debug("mcr20a rx: ", DUMP_PREFIX_OFFSET, 16, 1, 817 + lp->rx_buf, len, 0); 818 + pr_debug("mcr20a rx: lqi: %02hhx\n", lp->rx_lqi[0]); 819 + 820 + /* start RX sequence */ 821 + mcr20a_request_rx(lp); 822 + } 823 + 824 + static void 825 + mcr20a_handle_rx_read_len_complete(void *context) 826 + { 827 + struct mcr20a_local *lp = context; 828 + u8 len; 829 + int ret; 830 + 831 + dev_dbg(printdev(lp), "%s\n", __func__); 832 + 833 + /* get the length of received frame */ 834 + len = lp->reg_data[0] & DAR_RX_FRAME_LENGTH_MASK; 835 + dev_dbg(printdev(lp), "frame len : %d\n", len); 836 + 837 + /* prepare to read the rx buf */ 838 + lp->rx_buf_msg.complete = mcr20a_handle_rx_read_buf_complete; 839 + lp->rx_header[0] = MCR20A_BURST_READ_PACKET_BUF; 840 + lp->rx_xfer_buf.len = len; 841 + 842 + ret = spi_async(lp->spi, &lp->rx_buf_msg); 843 + if (ret) 844 + dev_err(printdev(lp), "failed to read rx buffer length\n"); 845 + } 846 + 847 + static int 848 + mcr20a_handle_rx(struct mcr20a_local *lp) 849 + { 850 + dev_dbg(printdev(lp), "%s\n", __func__); 851 + lp->reg_msg.complete = mcr20a_handle_rx_read_len_complete; 852 + lp->reg_cmd[0] = MCR20A_READ_REG(DAR_RX_FRM_LEN); 853 + lp->reg_xfer_data.len = 1; 854 + 855 + return spi_async(lp->spi, &lp->reg_msg); 856 + } 857 + 858 + static int 859 + mcr20a_handle_tx_complete(struct mcr20a_local *lp) 860 + { 861 + dev_dbg(printdev(lp), "%s\n", __func__); 862 + 863 + ieee802154_xmit_complete(lp->hw, lp->tx_skb, false); 864 + 865 + return mcr20a_request_rx(lp); 866 + } 867 + 868 + static int 869 + mcr20a_handle_tx(struct mcr20a_local *lp) 870 + { 871 + int ret; 872 + 873 + dev_dbg(printdev(lp), "%s\n", __func__); 874 + 875 + /* write tx buffer */ 876 + lp->tx_header[0] = MCR20A_BURST_WRITE_PACKET_BUF; 877 + /* add 2 bytes of FCS */ 878 + lp->tx_len[0] = lp->tx_skb->len + 2; 879 + lp->tx_xfer_buf.tx_buf = lp->tx_skb->data; 880 + /* add 1 byte psduLength */ 881 + lp->tx_xfer_buf.len = lp->tx_skb->len + 1; 882 + 883 + ret = spi_async(lp->spi, &lp->tx_buf_msg); 884 + if (ret) { 885 + dev_err(printdev(lp), "SPI write Failed for TX buf\n"); 886 + return ret; 887 + } 888 + 889 + return 0; 890 + } 891 + 892 + static void 893 + mcr20a_irq_clean_complete(void *context) 894 + { 895 + struct mcr20a_local *lp = context; 896 + u8 seq_state = lp->irq_data[DAR_IRQ_STS1] & DAR_PHY_CTRL1_XCVSEQ_MASK; 897 + 898 + dev_dbg(printdev(lp), "%s\n", __func__); 899 + 900 + enable_irq(lp->spi->irq); 901 + 902 + dev_dbg(printdev(lp), "IRQ STA1 (%02x) STA2 (%02x)\n", 903 + lp->irq_data[DAR_IRQ_STS1], lp->irq_data[DAR_IRQ_STS2]); 904 + 905 + switch (seq_state) { 906 + /* TX IRQ, RX IRQ and SEQ IRQ */ 907 + case (0x03): 908 + if (lp->is_tx) { 909 + lp->is_tx = 0; 910 + dev_dbg(printdev(lp), "TX is done. No ACK\n"); 911 + mcr20a_handle_tx_complete(lp); 912 + } 913 + break; 914 + case (0x05): 915 + /* rx is starting */ 916 + dev_dbg(printdev(lp), "RX is starting\n"); 917 + mcr20a_handle_rx(lp); 918 + break; 919 + case (0x07): 920 + if (lp->is_tx) { 921 + /* tx is done */ 922 + lp->is_tx = 0; 923 + dev_dbg(printdev(lp), "TX is done. Get ACK\n"); 924 + mcr20a_handle_tx_complete(lp); 925 + } else { 926 + /* rx is starting */ 927 + dev_dbg(printdev(lp), "RX is starting\n"); 928 + mcr20a_handle_rx(lp); 929 + } 930 + break; 931 + case (0x01): 932 + if (lp->is_tx) { 933 + dev_dbg(printdev(lp), "TX is starting\n"); 934 + mcr20a_handle_tx(lp); 935 + } else { 936 + dev_dbg(printdev(lp), "MCR20A is stop\n"); 937 + } 938 + break; 939 + } 940 + } 941 + 942 + static void mcr20a_irq_status_complete(void *context) 943 + { 944 + int ret; 945 + struct mcr20a_local *lp = context; 946 + 947 + dev_dbg(printdev(lp), "%s\n", __func__); 948 + regmap_update_bits_async(lp->regmap_dar, DAR_PHY_CTRL1, 949 + DAR_PHY_CTRL1_XCVSEQ_MASK, MCR20A_XCVSEQ_IDLE); 950 + 951 + lp->reg_msg.complete = mcr20a_irq_clean_complete; 952 + lp->reg_cmd[0] = MCR20A_WRITE_REG(DAR_IRQ_STS1); 953 + memcpy(lp->reg_data, lp->irq_data, MCR20A_IRQSTS_NUM); 954 + lp->reg_xfer_data.len = MCR20A_IRQSTS_NUM; 955 + 956 + ret = spi_async(lp->spi, &lp->reg_msg); 957 + 958 + if (ret) 959 + dev_err(printdev(lp), "failed to clean irq status\n"); 960 + } 961 + 962 + static irqreturn_t mcr20a_irq_isr(int irq, void *data) 963 + { 964 + struct mcr20a_local *lp = data; 965 + int ret; 966 + 967 + disable_irq_nosync(irq); 968 + 969 + lp->irq_header[0] = MCR20A_READ_REG(DAR_IRQ_STS1); 970 + /* read IRQSTSx */ 971 + ret = spi_async(lp->spi, &lp->irq_msg); 972 + if (ret) { 973 + enable_irq(irq); 974 + return IRQ_NONE; 975 + } 976 + 977 + return IRQ_HANDLED; 978 + } 979 + 980 + static int mcr20a_get_platform_data(struct spi_device *spi, 981 + struct mcr20a_platform_data *pdata) 982 + { 983 + int ret = 0; 984 + 985 + if (!spi->dev.of_node) 986 + return -EINVAL; 987 + 988 + pdata->rst_gpio = of_get_named_gpio(spi->dev.of_node, "rst_b-gpio", 0); 989 + dev_dbg(&spi->dev, "rst_b-gpio: %d\n", pdata->rst_gpio); 990 + 991 + return ret; 992 + } 993 + 994 + static void mcr20a_hw_setup(struct mcr20a_local *lp) 995 + { 996 + u8 i; 997 + struct ieee802154_hw *hw = lp->hw; 998 + struct wpan_phy *phy = lp->hw->phy; 999 + 1000 + dev_dbg(printdev(lp), "%s\n", __func__); 1001 + 1002 + phy->symbol_duration = 16; 1003 + phy->lifs_period = 40; 1004 + phy->sifs_period = 12; 1005 + 1006 + hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | 1007 + IEEE802154_HW_AFILT | 1008 + IEEE802154_HW_PROMISCUOUS; 1009 + 1010 + phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL | 1011 + WPAN_PHY_FLAG_CCA_MODE; 1012 + 1013 + phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) | 1014 + BIT(NL802154_CCA_CARRIER) | BIT(NL802154_CCA_ENERGY_CARRIER); 1015 + phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND) | 1016 + BIT(NL802154_CCA_OPT_ENERGY_CARRIER_OR); 1017 + 1018 + /* initiating cca_ed_levels */ 1019 + for (i = MCR20A_MAX_CCA_THRESHOLD; i < MCR20A_MIN_CCA_THRESHOLD + 1; 1020 + ++i) { 1021 + mcr20a_ed_levels[i] = -i * 100; 1022 + } 1023 + 1024 + phy->supported.cca_ed_levels = mcr20a_ed_levels; 1025 + phy->supported.cca_ed_levels_size = ARRAY_SIZE(mcr20a_ed_levels); 1026 + 1027 + phy->cca.mode = NL802154_CCA_ENERGY; 1028 + 1029 + phy->supported.channels[0] = MCR20A_VALID_CHANNELS; 1030 + phy->current_page = 0; 1031 + /* MCR20A default reset value */ 1032 + phy->current_channel = 20; 1033 + phy->symbol_duration = 16; 1034 + phy->supported.tx_powers = mcr20a_powers; 1035 + phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers); 1036 + phy->cca_ed_level = phy->supported.cca_ed_levels[75]; 1037 + phy->transmit_power = phy->supported.tx_powers[0x0F]; 1038 + } 1039 + 1040 + static void 1041 + mcr20a_setup_tx_spi_messages(struct mcr20a_local *lp) 1042 + { 1043 + spi_message_init(&lp->tx_buf_msg); 1044 + lp->tx_buf_msg.context = lp; 1045 + lp->tx_buf_msg.complete = mcr20a_write_tx_buf_complete; 1046 + 1047 + lp->tx_xfer_header.len = 1; 1048 + lp->tx_xfer_header.tx_buf = lp->tx_header; 1049 + 1050 + lp->tx_xfer_len.len = 1; 1051 + lp->tx_xfer_len.tx_buf = lp->tx_len; 1052 + 1053 + spi_message_add_tail(&lp->tx_xfer_header, &lp->tx_buf_msg); 1054 + spi_message_add_tail(&lp->tx_xfer_len, &lp->tx_buf_msg); 1055 + spi_message_add_tail(&lp->tx_xfer_buf, &lp->tx_buf_msg); 1056 + } 1057 + 1058 + static void 1059 + mcr20a_setup_rx_spi_messages(struct mcr20a_local *lp) 1060 + { 1061 + spi_message_init(&lp->reg_msg); 1062 + lp->reg_msg.context = lp; 1063 + 1064 + lp->reg_xfer_cmd.len = 1; 1065 + lp->reg_xfer_cmd.tx_buf = lp->reg_cmd; 1066 + lp->reg_xfer_cmd.rx_buf = lp->reg_cmd; 1067 + 1068 + lp->reg_xfer_data.rx_buf = lp->reg_data; 1069 + lp->reg_xfer_data.tx_buf = lp->reg_data; 1070 + 1071 + spi_message_add_tail(&lp->reg_xfer_cmd, &lp->reg_msg); 1072 + spi_message_add_tail(&lp->reg_xfer_data, &lp->reg_msg); 1073 + 1074 + spi_message_init(&lp->rx_buf_msg); 1075 + lp->rx_buf_msg.context = lp; 1076 + lp->rx_buf_msg.complete = mcr20a_handle_rx_read_buf_complete; 1077 + lp->rx_xfer_header.len = 1; 1078 + lp->rx_xfer_header.tx_buf = lp->rx_header; 1079 + lp->rx_xfer_header.rx_buf = lp->rx_header; 1080 + 1081 + lp->rx_xfer_buf.rx_buf = lp->rx_buf; 1082 + 1083 + lp->rx_xfer_lqi.len = 1; 1084 + lp->rx_xfer_lqi.rx_buf = lp->rx_lqi; 1085 + 1086 + spi_message_add_tail(&lp->rx_xfer_header, &lp->rx_buf_msg); 1087 + spi_message_add_tail(&lp->rx_xfer_buf, &lp->rx_buf_msg); 1088 + spi_message_add_tail(&lp->rx_xfer_lqi, &lp->rx_buf_msg); 1089 + } 1090 + 1091 + static void 1092 + mcr20a_setup_irq_spi_messages(struct mcr20a_local *lp) 1093 + { 1094 + spi_message_init(&lp->irq_msg); 1095 + lp->irq_msg.context = lp; 1096 + lp->irq_msg.complete = mcr20a_irq_status_complete; 1097 + lp->irq_xfer_header.len = 1; 1098 + lp->irq_xfer_header.tx_buf = lp->irq_header; 1099 + lp->irq_xfer_header.rx_buf = lp->irq_header; 1100 + 1101 + lp->irq_xfer_data.len = MCR20A_IRQSTS_NUM; 1102 + lp->irq_xfer_data.rx_buf = lp->irq_data; 1103 + 1104 + spi_message_add_tail(&lp->irq_xfer_header, &lp->irq_msg); 1105 + spi_message_add_tail(&lp->irq_xfer_data, &lp->irq_msg); 1106 + } 1107 + 1108 + static int 1109 + mcr20a_phy_init(struct mcr20a_local *lp) 1110 + { 1111 + u8 index; 1112 + unsigned int phy_reg = 0; 1113 + int ret; 1114 + 1115 + dev_dbg(printdev(lp), "%s\n", __func__); 1116 + 1117 + /* Disable Tristate on COCO MISO for SPI reads */ 1118 + ret = regmap_write(lp->regmap_iar, IAR_MISC_PAD_CTRL, 0x02); 1119 + if (ret) 1120 + goto err_ret; 1121 + 1122 + /* Clear all PP IRQ bits in IRQSTS1 to avoid unexpected interrupts 1123 + * immediately after init 1124 + */ 1125 + ret = regmap_write(lp->regmap_dar, DAR_IRQ_STS1, 0xEF); 1126 + if (ret) 1127 + goto err_ret; 1128 + 1129 + /* Clear all PP IRQ bits in IRQSTS2 */ 1130 + ret = regmap_write(lp->regmap_dar, DAR_IRQ_STS2, 1131 + DAR_IRQSTS2_ASM_IRQ | DAR_IRQSTS2_PB_ERR_IRQ | 1132 + DAR_IRQSTS2_WAKE_IRQ); 1133 + if (ret) 1134 + goto err_ret; 1135 + 1136 + /* Disable all timer interrupts */ 1137 + ret = regmap_write(lp->regmap_dar, DAR_IRQ_STS3, 0xFF); 1138 + if (ret) 1139 + goto err_ret; 1140 + 1141 + /* PHY_CTRL1 : default HW settings + AUTOACK enabled */ 1142 + ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL1, 1143 + DAR_PHY_CTRL1_AUTOACK, DAR_PHY_CTRL1_AUTOACK); 1144 + 1145 + /* PHY_CTRL2 : disable all interrupts */ 1146 + ret = regmap_write(lp->regmap_dar, DAR_PHY_CTRL2, 0xFF); 1147 + if (ret) 1148 + goto err_ret; 1149 + 1150 + /* PHY_CTRL3 : disable all timers and remaining interrupts */ 1151 + ret = regmap_write(lp->regmap_dar, DAR_PHY_CTRL3, 1152 + DAR_PHY_CTRL3_ASM_MSK | DAR_PHY_CTRL3_PB_ERR_MSK | 1153 + DAR_PHY_CTRL3_WAKE_MSK); 1154 + if (ret) 1155 + goto err_ret; 1156 + 1157 + /* SRC_CTRL : enable Acknowledge Frame Pending and 1158 + * Source Address Matching Enable 1159 + */ 1160 + ret = regmap_write(lp->regmap_dar, DAR_SRC_CTRL, 1161 + DAR_SRC_CTRL_ACK_FRM_PND | 1162 + (DAR_SRC_CTRL_INDEX << DAR_SRC_CTRL_INDEX_SHIFT)); 1163 + if (ret) 1164 + goto err_ret; 1165 + 1166 + /* RX_FRAME_FILTER */ 1167 + /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets */ 1168 + ret = regmap_write(lp->regmap_iar, IAR_RX_FRAME_FILTER, 1169 + IAR_RX_FRAME_FLT_FRM_VER | 1170 + IAR_RX_FRAME_FLT_BEACON_FT | 1171 + IAR_RX_FRAME_FLT_DATA_FT | 1172 + IAR_RX_FRAME_FLT_CMD_FT); 1173 + if (ret) 1174 + goto err_ret; 1175 + 1176 + dev_info(printdev(lp), "MCR20A DAR overwrites version: 0x%02x\n", 1177 + MCR20A_OVERWRITE_VERSION); 1178 + 1179 + /* Overwrites direct registers */ 1180 + ret = regmap_write(lp->regmap_dar, DAR_OVERWRITE_VER, 1181 + MCR20A_OVERWRITE_VERSION); 1182 + if (ret) 1183 + goto err_ret; 1184 + 1185 + /* Overwrites indirect registers */ 1186 + ret = regmap_multi_reg_write(lp->regmap_iar, mar20a_iar_overwrites, 1187 + ARRAY_SIZE(mar20a_iar_overwrites)); 1188 + if (ret) 1189 + goto err_ret; 1190 + 1191 + /* Clear HW indirect queue */ 1192 + dev_dbg(printdev(lp), "clear HW indirect queue\n"); 1193 + for (index = 0; index < MCR20A_PHY_INDIRECT_QUEUE_SIZE; index++) { 1194 + phy_reg = (u8)(((index & DAR_SRC_CTRL_INDEX) << 1195 + DAR_SRC_CTRL_INDEX_SHIFT) 1196 + | (DAR_SRC_CTRL_SRCADDR_EN) 1197 + | (DAR_SRC_CTRL_INDEX_DISABLE)); 1198 + ret = regmap_write(lp->regmap_dar, DAR_SRC_CTRL, phy_reg); 1199 + if (ret) 1200 + goto err_ret; 1201 + phy_reg = 0; 1202 + } 1203 + 1204 + /* Assign HW Indirect hash table to PAN0 */ 1205 + ret = regmap_read(lp->regmap_iar, IAR_DUAL_PAN_CTRL, &phy_reg); 1206 + if (ret) 1207 + goto err_ret; 1208 + 1209 + /* Clear current lvl */ 1210 + phy_reg &= ~IAR_DUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_MSK; 1211 + 1212 + /* Set new lvl */ 1213 + phy_reg |= MCR20A_PHY_INDIRECT_QUEUE_SIZE << 1214 + IAR_DUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_SHIFT; 1215 + ret = regmap_write(lp->regmap_iar, IAR_DUAL_PAN_CTRL, phy_reg); 1216 + if (ret) 1217 + goto err_ret; 1218 + 1219 + /* Set CCA threshold to -75 dBm */ 1220 + ret = regmap_write(lp->regmap_iar, IAR_CCA1_THRESH, 0x4B); 1221 + if (ret) 1222 + goto err_ret; 1223 + 1224 + /* Set prescaller to obtain 1 symbol (16us) timebase */ 1225 + ret = regmap_write(lp->regmap_iar, IAR_TMR_PRESCALE, 0x05); 1226 + if (ret) 1227 + goto err_ret; 1228 + 1229 + /* Enable autodoze mode. */ 1230 + ret = regmap_update_bits(lp->regmap_dar, DAR_PWR_MODES, 1231 + DAR_PWR_MODES_AUTODOZE, 1232 + DAR_PWR_MODES_AUTODOZE); 1233 + if (ret) 1234 + goto err_ret; 1235 + 1236 + /* Disable clk_out */ 1237 + ret = regmap_update_bits(lp->regmap_dar, DAR_CLK_OUT_CTRL, 1238 + DAR_CLK_OUT_CTRL_EN, 0x0); 1239 + if (ret) 1240 + goto err_ret; 1241 + 1242 + return 0; 1243 + 1244 + err_ret: 1245 + return ret; 1246 + } 1247 + 1248 + static int 1249 + mcr20a_probe(struct spi_device *spi) 1250 + { 1251 + struct ieee802154_hw *hw; 1252 + struct mcr20a_local *lp; 1253 + struct mcr20a_platform_data *pdata; 1254 + int irq_type; 1255 + int ret = -ENOMEM; 1256 + 1257 + dev_dbg(&spi->dev, "%s\n", __func__); 1258 + 1259 + if (!spi->irq) { 1260 + dev_err(&spi->dev, "no IRQ specified\n"); 1261 + return -EINVAL; 1262 + } 1263 + 1264 + pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); 1265 + if (!pdata) 1266 + return -ENOMEM; 1267 + 1268 + /* set mcr20a platform data */ 1269 + ret = mcr20a_get_platform_data(spi, pdata); 1270 + if (ret < 0) { 1271 + dev_crit(&spi->dev, "mcr20a_get_platform_data failed.\n"); 1272 + return ret; 1273 + } 1274 + 1275 + /* init reset gpio */ 1276 + if (gpio_is_valid(pdata->rst_gpio)) { 1277 + ret = devm_gpio_request_one(&spi->dev, pdata->rst_gpio, 1278 + GPIOF_OUT_INIT_HIGH, "reset"); 1279 + if (ret) 1280 + return ret; 1281 + } 1282 + 1283 + /* reset mcr20a */ 1284 + if (gpio_is_valid(pdata->rst_gpio)) { 1285 + usleep_range(10, 20); 1286 + gpio_set_value_cansleep(pdata->rst_gpio, 0); 1287 + usleep_range(10, 20); 1288 + gpio_set_value_cansleep(pdata->rst_gpio, 1); 1289 + usleep_range(120, 240); 1290 + } 1291 + 1292 + /* allocate ieee802154_hw and private data */ 1293 + hw = ieee802154_alloc_hw(sizeof(*lp), &mcr20a_hw_ops); 1294 + if (!hw) { 1295 + dev_crit(&spi->dev, "ieee802154_alloc_hw failed\n"); 1296 + return -ENOMEM; 1297 + } 1298 + 1299 + /* init mcr20a local data */ 1300 + lp = hw->priv; 1301 + lp->hw = hw; 1302 + lp->spi = spi; 1303 + lp->spi->dev.platform_data = pdata; 1304 + lp->pdata = pdata; 1305 + 1306 + /* init ieee802154_hw */ 1307 + hw->parent = &spi->dev; 1308 + ieee802154_random_extended_addr(&hw->phy->perm_extended_addr); 1309 + 1310 + /* init buf */ 1311 + lp->buf = devm_kzalloc(&spi->dev, SPI_COMMAND_BUFFER, GFP_KERNEL); 1312 + 1313 + if (!lp->buf) 1314 + return -ENOMEM; 1315 + 1316 + mcr20a_setup_tx_spi_messages(lp); 1317 + mcr20a_setup_rx_spi_messages(lp); 1318 + mcr20a_setup_irq_spi_messages(lp); 1319 + 1320 + /* setup regmap */ 1321 + lp->regmap_dar = devm_regmap_init_spi(spi, &mcr20a_dar_regmap); 1322 + if (IS_ERR(lp->regmap_dar)) { 1323 + ret = PTR_ERR(lp->regmap_dar); 1324 + dev_err(&spi->dev, "Failed to allocate dar map: %d\n", 1325 + ret); 1326 + goto free_dev; 1327 + } 1328 + 1329 + lp->regmap_iar = devm_regmap_init_spi(spi, &mcr20a_iar_regmap); 1330 + if (IS_ERR(lp->regmap_iar)) { 1331 + ret = PTR_ERR(lp->regmap_iar); 1332 + dev_err(&spi->dev, "Failed to allocate iar map: %d\n", ret); 1333 + goto free_dev; 1334 + } 1335 + 1336 + mcr20a_hw_setup(lp); 1337 + 1338 + spi_set_drvdata(spi, lp); 1339 + 1340 + ret = mcr20a_phy_init(lp); 1341 + if (ret < 0) { 1342 + dev_crit(&spi->dev, "mcr20a_phy_init failed\n"); 1343 + goto free_dev; 1344 + } 1345 + 1346 + irq_type = irq_get_trigger_type(spi->irq); 1347 + if (!irq_type) 1348 + irq_type = IRQF_TRIGGER_FALLING; 1349 + 1350 + ret = devm_request_irq(&spi->dev, spi->irq, mcr20a_irq_isr, 1351 + irq_type, dev_name(&spi->dev), lp); 1352 + if (ret) { 1353 + dev_err(&spi->dev, "could not request_irq for mcr20a\n"); 1354 + ret = -ENODEV; 1355 + goto free_dev; 1356 + } 1357 + 1358 + /* disable_irq by default and wait for starting hardware */ 1359 + disable_irq(spi->irq); 1360 + 1361 + ret = ieee802154_register_hw(hw); 1362 + if (ret) { 1363 + dev_crit(&spi->dev, "ieee802154_register_hw failed\n"); 1364 + goto free_dev; 1365 + } 1366 + 1367 + return ret; 1368 + 1369 + free_dev: 1370 + ieee802154_free_hw(lp->hw); 1371 + 1372 + return ret; 1373 + } 1374 + 1375 + static int mcr20a_remove(struct spi_device *spi) 1376 + { 1377 + struct mcr20a_local *lp = spi_get_drvdata(spi); 1378 + 1379 + dev_dbg(&spi->dev, "%s\n", __func__); 1380 + 1381 + ieee802154_unregister_hw(lp->hw); 1382 + ieee802154_free_hw(lp->hw); 1383 + 1384 + return 0; 1385 + } 1386 + 1387 + static const struct of_device_id mcr20a_of_match[] = { 1388 + { .compatible = "nxp,mcr20a", }, 1389 + { }, 1390 + }; 1391 + MODULE_DEVICE_TABLE(of, mcr20a_of_match); 1392 + 1393 + static const struct spi_device_id mcr20a_device_id[] = { 1394 + { .name = "mcr20a", }, 1395 + { }, 1396 + }; 1397 + MODULE_DEVICE_TABLE(spi, mcr20a_device_id); 1398 + 1399 + static struct spi_driver mcr20a_driver = { 1400 + .id_table = mcr20a_device_id, 1401 + .driver = { 1402 + .of_match_table = of_match_ptr(mcr20a_of_match), 1403 + .name = "mcr20a", 1404 + }, 1405 + .probe = mcr20a_probe, 1406 + .remove = mcr20a_remove, 1407 + }; 1408 + 1409 + module_spi_driver(mcr20a_driver); 1410 + 1411 + MODULE_DESCRIPTION("MCR20A Transceiver Driver"); 1412 + MODULE_LICENSE("GPL v2"); 1413 + MODULE_AUTHOR("Xue Liu <liuxuenetmail@gmail>");
+498
drivers/net/ieee802154/mcr20a.h
··· 1 + /* 2 + * Driver for NXP MCR20A 802.15.4 Wireless-PAN Networking controller 3 + * 4 + * Copyright (C) 2018 Xue Liu <liuxuenetmail@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 8 + * as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + */ 16 + #ifndef _MCR20A_H 17 + #define _MCR20A_H 18 + 19 + /* Direct Accress Register */ 20 + #define DAR_IRQ_STS1 0x00 21 + #define DAR_IRQ_STS2 0x01 22 + #define DAR_IRQ_STS3 0x02 23 + #define DAR_PHY_CTRL1 0x03 24 + #define DAR_PHY_CTRL2 0x04 25 + #define DAR_PHY_CTRL3 0x05 26 + #define DAR_RX_FRM_LEN 0x06 27 + #define DAR_PHY_CTRL4 0x07 28 + #define DAR_SRC_CTRL 0x08 29 + #define DAR_SRC_ADDRS_SUM_LSB 0x09 30 + #define DAR_SRC_ADDRS_SUM_MSB 0x0A 31 + #define DAR_CCA1_ED_FNL 0x0B 32 + #define DAR_EVENT_TMR_LSB 0x0C 33 + #define DAR_EVENT_TMR_MSB 0x0D 34 + #define DAR_EVENT_TMR_USB 0x0E 35 + #define DAR_TIMESTAMP_LSB 0x0F 36 + #define DAR_TIMESTAMP_MSB 0x10 37 + #define DAR_TIMESTAMP_USB 0x11 38 + #define DAR_T3CMP_LSB 0x12 39 + #define DAR_T3CMP_MSB 0x13 40 + #define DAR_T3CMP_USB 0x14 41 + #define DAR_T2PRIMECMP_LSB 0x15 42 + #define DAR_T2PRIMECMP_MSB 0x16 43 + #define DAR_T1CMP_LSB 0x17 44 + #define DAR_T1CMP_MSB 0x18 45 + #define DAR_T1CMP_USB 0x19 46 + #define DAR_T2CMP_LSB 0x1A 47 + #define DAR_T2CMP_MSB 0x1B 48 + #define DAR_T2CMP_USB 0x1C 49 + #define DAR_T4CMP_LSB 0x1D 50 + #define DAR_T4CMP_MSB 0x1E 51 + #define DAR_T4CMP_USB 0x1F 52 + #define DAR_PLL_INT0 0x20 53 + #define DAR_PLL_FRAC0_LSB 0x21 54 + #define DAR_PLL_FRAC0_MSB 0x22 55 + #define DAR_PA_PWR 0x23 56 + #define DAR_SEQ_STATE 0x24 57 + #define DAR_LQI_VALUE 0x25 58 + #define DAR_RSSI_CCA_CONT 0x26 59 + /*------------------ 0x27 */ 60 + #define DAR_ASM_CTRL1 0x28 61 + #define DAR_ASM_CTRL2 0x29 62 + #define DAR_ASM_DATA_0 0x2A 63 + #define DAR_ASM_DATA_1 0x2B 64 + #define DAR_ASM_DATA_2 0x2C 65 + #define DAR_ASM_DATA_3 0x2D 66 + #define DAR_ASM_DATA_4 0x2E 67 + #define DAR_ASM_DATA_5 0x2F 68 + #define DAR_ASM_DATA_6 0x30 69 + #define DAR_ASM_DATA_7 0x31 70 + #define DAR_ASM_DATA_8 0x32 71 + #define DAR_ASM_DATA_9 0x33 72 + #define DAR_ASM_DATA_A 0x34 73 + #define DAR_ASM_DATA_B 0x35 74 + #define DAR_ASM_DATA_C 0x36 75 + #define DAR_ASM_DATA_D 0x37 76 + #define DAR_ASM_DATA_E 0x38 77 + #define DAR_ASM_DATA_F 0x39 78 + /*----------------------- 0x3A */ 79 + #define DAR_OVERWRITE_VER 0x3B 80 + #define DAR_CLK_OUT_CTRL 0x3C 81 + #define DAR_PWR_MODES 0x3D 82 + #define IAR_INDEX 0x3E 83 + #define IAR_DATA 0x3F 84 + 85 + /* Indirect Resgister Memory */ 86 + #define IAR_PART_ID 0x00 87 + #define IAR_XTAL_TRIM 0x01 88 + #define IAR_PMC_LP_TRIM 0x02 89 + #define IAR_MACPANID0_LSB 0x03 90 + #define IAR_MACPANID0_MSB 0x04 91 + #define IAR_MACSHORTADDRS0_LSB 0x05 92 + #define IAR_MACSHORTADDRS0_MSB 0x06 93 + #define IAR_MACLONGADDRS0_0 0x07 94 + #define IAR_MACLONGADDRS0_8 0x08 95 + #define IAR_MACLONGADDRS0_16 0x09 96 + #define IAR_MACLONGADDRS0_24 0x0A 97 + #define IAR_MACLONGADDRS0_32 0x0B 98 + #define IAR_MACLONGADDRS0_40 0x0C 99 + #define IAR_MACLONGADDRS0_48 0x0D 100 + #define IAR_MACLONGADDRS0_56 0x0E 101 + #define IAR_RX_FRAME_FILTER 0x0F 102 + #define IAR_PLL_INT1 0x10 103 + #define IAR_PLL_FRAC1_LSB 0x11 104 + #define IAR_PLL_FRAC1_MSB 0x12 105 + #define IAR_MACPANID1_LSB 0x13 106 + #define IAR_MACPANID1_MSB 0x14 107 + #define IAR_MACSHORTADDRS1_LSB 0x15 108 + #define IAR_MACSHORTADDRS1_MSB 0x16 109 + #define IAR_MACLONGADDRS1_0 0x17 110 + #define IAR_MACLONGADDRS1_8 0x18 111 + #define IAR_MACLONGADDRS1_16 0x19 112 + #define IAR_MACLONGADDRS1_24 0x1A 113 + #define IAR_MACLONGADDRS1_32 0x1B 114 + #define IAR_MACLONGADDRS1_40 0x1C 115 + #define IAR_MACLONGADDRS1_48 0x1D 116 + #define IAR_MACLONGADDRS1_56 0x1E 117 + #define IAR_DUAL_PAN_CTRL 0x1F 118 + #define IAR_DUAL_PAN_DWELL 0x20 119 + #define IAR_DUAL_PAN_STS 0x21 120 + #define IAR_CCA1_THRESH 0x22 121 + #define IAR_CCA1_ED_OFFSET_COMP 0x23 122 + #define IAR_LQI_OFFSET_COMP 0x24 123 + #define IAR_CCA_CTRL 0x25 124 + #define IAR_CCA2_CORR_PEAKS 0x26 125 + #define IAR_CCA2_CORR_THRESH 0x27 126 + #define IAR_TMR_PRESCALE 0x28 127 + /*-------------------- 0x29 */ 128 + #define IAR_GPIO_DATA 0x2A 129 + #define IAR_GPIO_DIR 0x2B 130 + #define IAR_GPIO_PUL_EN 0x2C 131 + #define IAR_GPIO_PUL_SEL 0x2D 132 + #define IAR_GPIO_DS 0x2E 133 + /*------------------ 0x2F */ 134 + #define IAR_ANT_PAD_CTRL 0x30 135 + #define IAR_MISC_PAD_CTRL 0x31 136 + #define IAR_BSM_CTRL 0x32 137 + /*------------------- 0x33 */ 138 + #define IAR_RNG 0x34 139 + #define IAR_RX_BYTE_COUNT 0x35 140 + #define IAR_RX_WTR_MARK 0x36 141 + #define IAR_SOFT_RESET 0x37 142 + #define IAR_TXDELAY 0x38 143 + #define IAR_ACKDELAY 0x39 144 + #define IAR_SEQ_MGR_CTRL 0x3A 145 + #define IAR_SEQ_MGR_STS 0x3B 146 + #define IAR_SEQ_T_STS 0x3C 147 + #define IAR_ABORT_STS 0x3D 148 + #define IAR_CCCA_BUSY_CNT 0x3E 149 + #define IAR_SRC_ADDR_CHECKSUM1 0x3F 150 + #define IAR_SRC_ADDR_CHECKSUM2 0x40 151 + #define IAR_SRC_TBL_VALID1 0x41 152 + #define IAR_SRC_TBL_VALID2 0x42 153 + #define IAR_FILTERFAIL_CODE1 0x43 154 + #define IAR_FILTERFAIL_CODE2 0x44 155 + #define IAR_SLOT_PRELOAD 0x45 156 + /*-------------------- 0x46 */ 157 + #define IAR_CORR_VT 0x47 158 + #define IAR_SYNC_CTRL 0x48 159 + #define IAR_PN_LSB_0 0x49 160 + #define IAR_PN_LSB_1 0x4A 161 + #define IAR_PN_MSB_0 0x4B 162 + #define IAR_PN_MSB_1 0x4C 163 + #define IAR_CORR_NVAL 0x4D 164 + #define IAR_TX_MODE_CTRL 0x4E 165 + #define IAR_SNF_THR 0x4F 166 + #define IAR_FAD_THR 0x50 167 + #define IAR_ANT_AGC_CTRL 0x51 168 + #define IAR_AGC_THR1 0x52 169 + #define IAR_AGC_THR2 0x53 170 + #define IAR_AGC_HYS 0x54 171 + #define IAR_AFC 0x55 172 + /*------------------- 0x56 */ 173 + /*------------------- 0x57 */ 174 + #define IAR_PHY_STS 0x58 175 + #define IAR_RX_MAX_CORR 0x59 176 + #define IAR_RX_MAX_PREAMBLE 0x5A 177 + #define IAR_RSSI 0x5B 178 + /*------------------- 0x5C */ 179 + /*------------------- 0x5D */ 180 + #define IAR_PLL_DIG_CTRL 0x5E 181 + #define IAR_VCO_CAL 0x5F 182 + #define IAR_VCO_BEST_DIFF 0x60 183 + #define IAR_VCO_BIAS 0x61 184 + #define IAR_KMOD_CTRL 0x62 185 + #define IAR_KMOD_CAL 0x63 186 + #define IAR_PA_CAL 0x64 187 + #define IAR_PA_PWRCAL 0x65 188 + #define IAR_ATT_RSSI1 0x66 189 + #define IAR_ATT_RSSI2 0x67 190 + #define IAR_RSSI_OFFSET 0x68 191 + #define IAR_RSSI_SLOPE 0x69 192 + #define IAR_RSSI_CAL1 0x6A 193 + #define IAR_RSSI_CAL2 0x6B 194 + /*------------------- 0x6C */ 195 + /*------------------- 0x6D */ 196 + #define IAR_XTAL_CTRL 0x6E 197 + #define IAR_XTAL_COMP_MIN 0x6F 198 + #define IAR_XTAL_COMP_MAX 0x70 199 + #define IAR_XTAL_GM 0x71 200 + /*------------------- 0x72 */ 201 + /*------------------- 0x73 */ 202 + #define IAR_LNA_TUNE 0x74 203 + #define IAR_LNA_AGCGAIN 0x75 204 + /*------------------- 0x76 */ 205 + /*------------------- 0x77 */ 206 + #define IAR_CHF_PMA_GAIN 0x78 207 + #define IAR_CHF_IBUF 0x79 208 + #define IAR_CHF_QBUF 0x7A 209 + #define IAR_CHF_IRIN 0x7B 210 + #define IAR_CHF_QRIN 0x7C 211 + #define IAR_CHF_IL 0x7D 212 + #define IAR_CHF_QL 0x7E 213 + #define IAR_CHF_CC1 0x7F 214 + #define IAR_CHF_CCL 0x80 215 + #define IAR_CHF_CC2 0x81 216 + #define IAR_CHF_IROUT 0x82 217 + #define IAR_CHF_QROUT 0x83 218 + /*------------------- 0x84 */ 219 + /*------------------- 0x85 */ 220 + #define IAR_RSSI_CTRL 0x86 221 + /*------------------- 0x87 */ 222 + /*------------------- 0x88 */ 223 + #define IAR_PA_BIAS 0x89 224 + #define IAR_PA_TUNING 0x8A 225 + /*------------------- 0x8B */ 226 + /*------------------- 0x8C */ 227 + #define IAR_PMC_HP_TRIM 0x8D 228 + #define IAR_VREGA_TRIM 0x8E 229 + /*------------------- 0x8F */ 230 + /*------------------- 0x90 */ 231 + #define IAR_VCO_CTRL1 0x91 232 + #define IAR_VCO_CTRL2 0x92 233 + /*------------------- 0x93 */ 234 + /*------------------- 0x94 */ 235 + #define IAR_ANA_SPARE_OUT1 0x95 236 + #define IAR_ANA_SPARE_OUT2 0x96 237 + #define IAR_ANA_SPARE_IN 0x97 238 + #define IAR_MISCELLANEOUS 0x98 239 + /*------------------- 0x99 */ 240 + #define IAR_SEQ_MGR_OVRD0 0x9A 241 + #define IAR_SEQ_MGR_OVRD1 0x9B 242 + #define IAR_SEQ_MGR_OVRD2 0x9C 243 + #define IAR_SEQ_MGR_OVRD3 0x9D 244 + #define IAR_SEQ_MGR_OVRD4 0x9E 245 + #define IAR_SEQ_MGR_OVRD5 0x9F 246 + #define IAR_SEQ_MGR_OVRD6 0xA0 247 + #define IAR_SEQ_MGR_OVRD7 0xA1 248 + /*------------------- 0xA2 */ 249 + #define IAR_TESTMODE_CTRL 0xA3 250 + #define IAR_DTM_CTRL1 0xA4 251 + #define IAR_DTM_CTRL2 0xA5 252 + #define IAR_ATM_CTRL1 0xA6 253 + #define IAR_ATM_CTRL2 0xA7 254 + #define IAR_ATM_CTRL3 0xA8 255 + /*------------------- 0xA9 */ 256 + #define IAR_LIM_FE_TEST_CTRL 0xAA 257 + #define IAR_CHF_TEST_CTRL 0xAB 258 + #define IAR_VCO_TEST_CTRL 0xAC 259 + #define IAR_PLL_TEST_CTRL 0xAD 260 + #define IAR_PA_TEST_CTRL 0xAE 261 + #define IAR_PMC_TEST_CTRL 0xAF 262 + #define IAR_SCAN_DTM_PROTECT_1 0xFE 263 + #define IAR_SCAN_DTM_PROTECT_0 0xFF 264 + 265 + /* IRQSTS1 bits */ 266 + #define DAR_IRQSTS1_RX_FRM_PEND BIT(7) 267 + #define DAR_IRQSTS1_PLL_UNLOCK_IRQ BIT(6) 268 + #define DAR_IRQSTS1_FILTERFAIL_IRQ BIT(5) 269 + #define DAR_IRQSTS1_RXWTRMRKIRQ BIT(4) 270 + #define DAR_IRQSTS1_CCAIRQ BIT(3) 271 + #define DAR_IRQSTS1_RXIRQ BIT(2) 272 + #define DAR_IRQSTS1_TXIRQ BIT(1) 273 + #define DAR_IRQSTS1_SEQIRQ BIT(0) 274 + 275 + /* IRQSTS2 bits */ 276 + #define DAR_IRQSTS2_CRCVALID BIT(7) 277 + #define DAR_IRQSTS2_CCA BIT(6) 278 + #define DAR_IRQSTS2_SRCADDR BIT(5) 279 + #define DAR_IRQSTS2_PI BIT(4) 280 + #define DAR_IRQSTS2_TMRSTATUS BIT(3) 281 + #define DAR_IRQSTS2_ASM_IRQ BIT(2) 282 + #define DAR_IRQSTS2_PB_ERR_IRQ BIT(1) 283 + #define DAR_IRQSTS2_WAKE_IRQ BIT(0) 284 + 285 + /* IRQSTS3 bits */ 286 + #define DAR_IRQSTS3_TMR4MSK BIT(7) 287 + #define DAR_IRQSTS3_TMR3MSK BIT(6) 288 + #define DAR_IRQSTS3_TMR2MSK BIT(5) 289 + #define DAR_IRQSTS3_TMR1MSK BIT(4) 290 + #define DAR_IRQSTS3_TMR4IRQ BIT(3) 291 + #define DAR_IRQSTS3_TMR3IRQ BIT(2) 292 + #define DAR_IRQSTS3_TMR2IRQ BIT(1) 293 + #define DAR_IRQSTS3_TMR1IRQ BIT(0) 294 + 295 + /* PHY_CTRL1 bits */ 296 + #define DAR_PHY_CTRL1_TMRTRIGEN BIT(7) 297 + #define DAR_PHY_CTRL1_SLOTTED BIT(6) 298 + #define DAR_PHY_CTRL1_CCABFRTX BIT(5) 299 + #define DAR_PHY_CTRL1_CCABFRTX_SHIFT 5 300 + #define DAR_PHY_CTRL1_RXACKRQD BIT(4) 301 + #define DAR_PHY_CTRL1_AUTOACK BIT(3) 302 + #define DAR_PHY_CTRL1_XCVSEQ_MASK 0x07 303 + 304 + /* PHY_CTRL2 bits */ 305 + #define DAR_PHY_CTRL2_CRC_MSK BIT(7) 306 + #define DAR_PHY_CTRL2_PLL_UNLOCK_MSK BIT(6) 307 + #define DAR_PHY_CTRL2_FILTERFAIL_MSK BIT(5) 308 + #define DAR_PHY_CTRL2_RX_WMRK_MSK BIT(4) 309 + #define DAR_PHY_CTRL2_CCAMSK BIT(3) 310 + #define DAR_PHY_CTRL2_RXMSK BIT(2) 311 + #define DAR_PHY_CTRL2_TXMSK BIT(1) 312 + #define DAR_PHY_CTRL2_SEQMSK BIT(0) 313 + 314 + /* PHY_CTRL3 bits */ 315 + #define DAR_PHY_CTRL3_TMR4CMP_EN BIT(7) 316 + #define DAR_PHY_CTRL3_TMR3CMP_EN BIT(6) 317 + #define DAR_PHY_CTRL3_TMR2CMP_EN BIT(5) 318 + #define DAR_PHY_CTRL3_TMR1CMP_EN BIT(4) 319 + #define DAR_PHY_CTRL3_ASM_MSK BIT(2) 320 + #define DAR_PHY_CTRL3_PB_ERR_MSK BIT(1) 321 + #define DAR_PHY_CTRL3_WAKE_MSK BIT(0) 322 + 323 + /* RX_FRM_LEN bits */ 324 + #define DAR_RX_FRAME_LENGTH_MASK (0x7F) 325 + 326 + /* PHY_CTRL4 bits */ 327 + #define DAR_PHY_CTRL4_TRCV_MSK BIT(7) 328 + #define DAR_PHY_CTRL4_TC3TMOUT BIT(6) 329 + #define DAR_PHY_CTRL4_PANCORDNTR0 BIT(5) 330 + #define DAR_PHY_CTRL4_CCATYPE (3) 331 + #define DAR_PHY_CTRL4_CCATYPE_SHIFT (3) 332 + #define DAR_PHY_CTRL4_CCATYPE_MASK (0x18) 333 + #define DAR_PHY_CTRL4_TMRLOAD BIT(2) 334 + #define DAR_PHY_CTRL4_PROMISCUOUS BIT(1) 335 + #define DAR_PHY_CTRL4_TC2PRIME_EN BIT(0) 336 + 337 + /* SRC_CTRL bits */ 338 + #define DAR_SRC_CTRL_INDEX (0x0F) 339 + #define DAR_SRC_CTRL_INDEX_SHIFT (4) 340 + #define DAR_SRC_CTRL_ACK_FRM_PND BIT(3) 341 + #define DAR_SRC_CTRL_SRCADDR_EN BIT(2) 342 + #define DAR_SRC_CTRL_INDEX_EN BIT(1) 343 + #define DAR_SRC_CTRL_INDEX_DISABLE BIT(0) 344 + 345 + /* DAR_ASM_CTRL1 bits */ 346 + #define DAR_ASM_CTRL1_CLEAR BIT(7) 347 + #define DAR_ASM_CTRL1_START BIT(6) 348 + #define DAR_ASM_CTRL1_SELFTST BIT(5) 349 + #define DAR_ASM_CTRL1_CTR BIT(4) 350 + #define DAR_ASM_CTRL1_CBC BIT(3) 351 + #define DAR_ASM_CTRL1_AES BIT(2) 352 + #define DAR_ASM_CTRL1_LOAD_MAC BIT(1) 353 + 354 + /* DAR_ASM_CTRL2 bits */ 355 + #define DAR_ASM_CTRL2_DATA_REG_TYPE_SEL (7) 356 + #define DAR_ASM_CTRL2_DATA_REG_TYPE_SEL_SHIFT (5) 357 + #define DAR_ASM_CTRL2_TSTPAS BIT(1) 358 + 359 + /* DAR_CLK_OUT_CTRL bits */ 360 + #define DAR_CLK_OUT_CTRL_EXTEND BIT(7) 361 + #define DAR_CLK_OUT_CTRL_HIZ BIT(6) 362 + #define DAR_CLK_OUT_CTRL_SR BIT(5) 363 + #define DAR_CLK_OUT_CTRL_DS BIT(4) 364 + #define DAR_CLK_OUT_CTRL_EN BIT(3) 365 + #define DAR_CLK_OUT_CTRL_DIV (7) 366 + 367 + /* DAR_PWR_MODES bits */ 368 + #define DAR_PWR_MODES_XTAL_READY BIT(5) 369 + #define DAR_PWR_MODES_XTALEN BIT(4) 370 + #define DAR_PWR_MODES_ASM_CLK_EN BIT(3) 371 + #define DAR_PWR_MODES_AUTODOZE BIT(1) 372 + #define DAR_PWR_MODES_PMC_MODE BIT(0) 373 + 374 + /* RX_FRAME_FILTER bits */ 375 + #define IAR_RX_FRAME_FLT_FRM_VER (0xC0) 376 + #define IAR_RX_FRAME_FLT_FRM_VER_SHIFT (6) 377 + #define IAR_RX_FRAME_FLT_ACTIVE_PROMISCUOUS BIT(5) 378 + #define IAR_RX_FRAME_FLT_NS_FT BIT(4) 379 + #define IAR_RX_FRAME_FLT_CMD_FT BIT(3) 380 + #define IAR_RX_FRAME_FLT_ACK_FT BIT(2) 381 + #define IAR_RX_FRAME_FLT_DATA_FT BIT(1) 382 + #define IAR_RX_FRAME_FLT_BEACON_FT BIT(0) 383 + 384 + /* DUAL_PAN_CTRL bits */ 385 + #define IAR_DUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_MSK (0xF0) 386 + #define IAR_DUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_SHIFT (4) 387 + #define IAR_DUAL_PAN_CTRL_CURRENT_NETWORK BIT(3) 388 + #define IAR_DUAL_PAN_CTRL_PANCORDNTR1 BIT(2) 389 + #define IAR_DUAL_PAN_CTRL_DUAL_PAN_AUTO BIT(1) 390 + #define IAR_DUAL_PAN_CTRL_ACTIVE_NETWORK BIT(0) 391 + 392 + /* DUAL_PAN_STS bits */ 393 + #define IAR_DUAL_PAN_STS_RECD_ON_PAN1 BIT(7) 394 + #define IAR_DUAL_PAN_STS_RECD_ON_PAN0 BIT(6) 395 + #define IAR_DUAL_PAN_STS_DUAL_PAN_REMAIN (0x3F) 396 + 397 + /* CCA_CTRL bits */ 398 + #define IAR_CCA_CTRL_AGC_FRZ_EN BIT(6) 399 + #define IAR_CCA_CTRL_CONT_RSSI_EN BIT(5) 400 + #define IAR_CCA_CTRL_LQI_RSSI_NOT_CORR BIT(4) 401 + #define IAR_CCA_CTRL_CCA3_AND_NOT_OR BIT(3) 402 + #define IAR_CCA_CTRL_POWER_COMP_EN_LQI BIT(2) 403 + #define IAR_CCA_CTRL_POWER_COMP_EN_ED BIT(1) 404 + #define IAR_CCA_CTRL_POWER_COMP_EN_CCA1 BIT(0) 405 + 406 + /* ANT_PAD_CTRL bits */ 407 + #define IAR_ANT_PAD_CTRL_ANTX_POL (0x0F) 408 + #define IAR_ANT_PAD_CTRL_ANTX_POL_SHIFT (4) 409 + #define IAR_ANT_PAD_CTRL_ANTX_CTRLMODE BIT(3) 410 + #define IAR_ANT_PAD_CTRL_ANTX_HZ BIT(2) 411 + #define IAR_ANT_PAD_CTRL_ANTX_EN (3) 412 + 413 + /* MISC_PAD_CTRL bits */ 414 + #define IAR_MISC_PAD_CTRL_MISO_HIZ_EN BIT(3) 415 + #define IAR_MISC_PAD_CTRL_IRQ_B_OD BIT(2) 416 + #define IAR_MISC_PAD_CTRL_NON_GPIO_DS BIT(1) 417 + #define IAR_MISC_PAD_CTRL_ANTX_CURR (1) 418 + 419 + /* ANT_AGC_CTRL bits */ 420 + #define IAR_ANT_AGC_CTRL_FAD_EN_SHIFT (0) 421 + #define IAR_ANT_AGC_CTRL_FAD_EN_MASK (1) 422 + #define IAR_ANT_AGC_CTRL_ANTX_SHIFT (1) 423 + #define IAR_ANT_AGC_CTRL_ANTX_MASK BIT(AR_ANT_AGC_CTRL_ANTX_SHIFT) 424 + 425 + /* BSM_CTRL bits */ 426 + #define BSM_CTRL_BSM_EN (1) 427 + 428 + /* SOFT_RESET bits */ 429 + #define IAR_SOFT_RESET_SOG_RST BIT(7) 430 + #define IAR_SOFT_RESET_REGS_RST BIT(4) 431 + #define IAR_SOFT_RESET_PLL_RST BIT(3) 432 + #define IAR_SOFT_RESET_TX_RST BIT(2) 433 + #define IAR_SOFT_RESET_RX_RST BIT(1) 434 + #define IAR_SOFT_RESET_SEQ_MGR_RST BIT(0) 435 + 436 + /* SEQ_MGR_CTRL bits */ 437 + #define IAR_SEQ_MGR_CTRL_SEQ_STATE_CTRL (3) 438 + #define IAR_SEQ_MGR_CTRL_SEQ_STATE_CTRL_SHIFT (6) 439 + #define IAR_SEQ_MGR_CTRL_NO_RX_RECYCLE BIT(5) 440 + #define IAR_SEQ_MGR_CTRL_LATCH_PREAMBLE BIT(4) 441 + #define IAR_SEQ_MGR_CTRL_EVENT_TMR_DO_NOT_LATCH BIT(3) 442 + #define IAR_SEQ_MGR_CTRL_CLR_NEW_SEQ_INHIBIT BIT(2) 443 + #define IAR_SEQ_MGR_CTRL_PSM_LOCK_DIS BIT(1) 444 + #define IAR_SEQ_MGR_CTRL_PLL_ABORT_OVRD BIT(0) 445 + 446 + /* SEQ_MGR_STS bits */ 447 + #define IAR_SEQ_MGR_STS_TMR2_SEQ_TRIG_ARMED BIT(7) 448 + #define IAR_SEQ_MGR_STS_RX_MODE BIT(6) 449 + #define IAR_SEQ_MGR_STS_RX_TIMEOUT_PENDING BIT(5) 450 + #define IAR_SEQ_MGR_STS_NEW_SEQ_INHIBIT BIT(4) 451 + #define IAR_SEQ_MGR_STS_SEQ_IDLE BIT(3) 452 + #define IAR_SEQ_MGR_STS_XCVSEQ_ACTUAL (7) 453 + 454 + /* ABORT_STS bits */ 455 + #define IAR_ABORT_STS_PLL_ABORTED BIT(2) 456 + #define IAR_ABORT_STS_TC3_ABORTED BIT(1) 457 + #define IAR_ABORT_STS_SW_ABORTED BIT(0) 458 + 459 + /* IAR_FILTERFAIL_CODE2 bits */ 460 + #define IAR_FILTERFAIL_CODE2_PAN_SEL BIT(7) 461 + #define IAR_FILTERFAIL_CODE2_9_8 (3) 462 + 463 + /* PHY_STS bits */ 464 + #define IAR_PHY_STS_PLL_UNLOCK BIT(7) 465 + #define IAR_PHY_STS_PLL_LOCK_ERR BIT(6) 466 + #define IAR_PHY_STS_PLL_LOCK BIT(5) 467 + #define IAR_PHY_STS_CRCVALID BIT(3) 468 + #define IAR_PHY_STS_FILTERFAIL_FLAG_SEL BIT(2) 469 + #define IAR_PHY_STS_SFD_DET BIT(1) 470 + #define IAR_PHY_STS_PREAMBLE_DET BIT(0) 471 + 472 + /* TESTMODE_CTRL bits */ 473 + #define IAR_TEST_MODE_CTRL_HOT_ANT BIT(4) 474 + #define IAR_TEST_MODE_CTRL_IDEAL_RSSI_EN BIT(3) 475 + #define IAR_TEST_MODE_CTRL_IDEAL_PFC_EN BIT(2) 476 + #define IAR_TEST_MODE_CTRL_CONTINUOUS_EN BIT(1) 477 + #define IAR_TEST_MODE_CTRL_FPGA_EN BIT(0) 478 + 479 + /* DTM_CTRL1 bits */ 480 + #define IAR_DTM_CTRL1_ATM_LOCKED BIT(7) 481 + #define IAR_DTM_CTRL1_DTM_EN BIT(6) 482 + #define IAR_DTM_CTRL1_PAGE5 BIT(5) 483 + #define IAR_DTM_CTRL1_PAGE4 BIT(4) 484 + #define IAR_DTM_CTRL1_PAGE3 BIT(3) 485 + #define IAR_DTM_CTRL1_PAGE2 BIT(2) 486 + #define IAR_DTM_CTRL1_PAGE1 BIT(1) 487 + #define IAR_DTM_CTRL1_PAGE0 BIT(0) 488 + 489 + /* TX_MODE_CTRL */ 490 + #define IAR_TX_MODE_CTRL_TX_INV BIT(4) 491 + #define IAR_TX_MODE_CTRL_BT_EN BIT(3) 492 + #define IAR_TX_MODE_CTRL_DTS2 BIT(2) 493 + #define IAR_TX_MODE_CTRL_DTS1 BIT(1) 494 + #define IAR_TX_MODE_CTRL_DTS0 BIT(0) 495 + 496 + #define TX_MODE_CTRL_DTS_MASK (7) 497 + 498 + #endif /* _MCR20A_H */