at master 17 kB view raw
1// SPDX-License-Identifier: (GPL-2.0) 2/* 3 * Microchip CoreSPI SPI controller driver 4 * 5 * Copyright (c) 2018-2022 Microchip Technology Inc. and its subsidiaries 6 * 7 * Author: Daire McNamara <daire.mcnamara@microchip.com> 8 * Author: Conor Dooley <conor.dooley@microchip.com> 9 * 10 */ 11 12#include <linux/clk.h> 13#include <linux/delay.h> 14#include <linux/err.h> 15#include <linux/init.h> 16#include <linux/interrupt.h> 17#include <linux/io.h> 18#include <linux/module.h> 19#include <linux/of.h> 20#include <linux/platform_device.h> 21#include <linux/spi/spi.h> 22 23#define MAX_LEN (0xffff) 24#define MAX_CS (1) 25#define DEFAULT_FRAMESIZE (8) 26#define FIFO_DEPTH (32) 27#define CLK_GEN_MODE1_MAX (255) 28#define CLK_GEN_MODE0_MAX (15) 29#define CLK_GEN_MIN (0) 30#define MODE_X_MASK_SHIFT (24) 31 32#define CONTROL_ENABLE BIT(0) 33#define CONTROL_MASTER BIT(1) 34#define CONTROL_RX_DATA_INT BIT(4) 35#define CONTROL_TX_DATA_INT BIT(5) 36#define CONTROL_RX_OVER_INT BIT(6) 37#define CONTROL_TX_UNDER_INT BIT(7) 38#define CONTROL_SPO BIT(24) 39#define CONTROL_SPH BIT(25) 40#define CONTROL_SPS BIT(26) 41#define CONTROL_FRAMEURUN BIT(27) 42#define CONTROL_CLKMODE BIT(28) 43#define CONTROL_BIGFIFO BIT(29) 44#define CONTROL_OENOFF BIT(30) 45#define CONTROL_RESET BIT(31) 46 47#define CONTROL_MODE_MASK GENMASK(3, 2) 48#define MOTOROLA_MODE (0) 49#define CONTROL_FRAMECNT_MASK GENMASK(23, 8) 50#define CONTROL_FRAMECNT_SHIFT (8) 51 52#define STATUS_ACTIVE BIT(14) 53#define STATUS_SSEL BIT(13) 54#define STATUS_FRAMESTART BIT(12) 55#define STATUS_TXFIFO_EMPTY_NEXT_READ BIT(11) 56#define STATUS_TXFIFO_EMPTY BIT(10) 57#define STATUS_TXFIFO_FULL_NEXT_WRITE BIT(9) 58#define STATUS_TXFIFO_FULL BIT(8) 59#define STATUS_RXFIFO_EMPTY_NEXT_READ BIT(7) 60#define STATUS_RXFIFO_EMPTY BIT(6) 61#define STATUS_RXFIFO_FULL_NEXT_WRITE BIT(5) 62#define STATUS_RXFIFO_FULL BIT(4) 63#define STATUS_TX_UNDERRUN BIT(3) 64#define STATUS_RX_OVERFLOW BIT(2) 65#define STATUS_RXDAT_RXED BIT(1) 66#define STATUS_TXDAT_SENT BIT(0) 67 68#define INT_TXDONE BIT(0) 69#define INT_RXRDY BIT(1) 70#define INT_RX_CHANNEL_OVERFLOW BIT(2) 71#define INT_TX_CHANNEL_UNDERRUN BIT(3) 72 73#define INT_ENABLE_MASK (CONTROL_RX_OVER_INT | CONTROL_TX_UNDER_INT) 74 75#define REG_CONTROL (0x00) 76#define REG_FRAME_SIZE (0x04) 77#define FRAME_SIZE_MASK GENMASK(5, 0) 78#define REG_STATUS (0x08) 79#define REG_INT_CLEAR (0x0c) 80#define REG_RX_DATA (0x10) 81#define REG_TX_DATA (0x14) 82#define REG_CLK_GEN (0x18) 83#define REG_SLAVE_SELECT (0x1c) 84#define SSEL_MASK GENMASK(7, 0) 85#define SSEL_DIRECT BIT(8) 86#define SSELOUT_SHIFT 9 87#define SSELOUT BIT(SSELOUT_SHIFT) 88#define REG_MIS (0x20) 89#define REG_RIS (0x24) 90#define REG_CONTROL2 (0x28) 91#define REG_COMMAND (0x2c) 92#define COMMAND_CLRFRAMECNT BIT(4) 93#define COMMAND_TXFIFORST BIT(3) 94#define COMMAND_RXFIFORST BIT(2) 95#define REG_PKTSIZE (0x30) 96#define REG_CMD_SIZE (0x34) 97#define REG_HWSTATUS (0x38) 98#define REG_STAT8 (0x3c) 99#define REG_CTRL2 (0x48) 100#define REG_FRAMESUP (0x50) 101 102struct mpfs_spi { 103 void __iomem *regs; 104 struct clk *clk; 105 const u8 *tx_buf; 106 u8 *rx_buf; 107 u32 clk_gen; /* divider for spi output clock generated by the controller */ 108 u32 clk_mode; 109 u32 pending_slave_select; 110 int irq; 111 int tx_len; 112 int rx_len; 113 int n_bytes; 114}; 115 116static inline u32 mpfs_spi_read(struct mpfs_spi *spi, unsigned int reg) 117{ 118 return readl(spi->regs + reg); 119} 120 121static inline void mpfs_spi_write(struct mpfs_spi *spi, unsigned int reg, u32 val) 122{ 123 writel(val, spi->regs + reg); 124} 125 126static inline void mpfs_spi_disable(struct mpfs_spi *spi) 127{ 128 u32 control = mpfs_spi_read(spi, REG_CONTROL); 129 130 control &= ~CONTROL_ENABLE; 131 132 mpfs_spi_write(spi, REG_CONTROL, control); 133} 134 135static inline void mpfs_spi_read_fifo(struct mpfs_spi *spi, int fifo_max) 136{ 137 for (int i = 0; i < fifo_max; i++) { 138 u32 data; 139 140 while (mpfs_spi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY) 141 ; 142 143 data = mpfs_spi_read(spi, REG_RX_DATA); 144 145 spi->rx_len -= spi->n_bytes; 146 147 if (!spi->rx_buf) 148 continue; 149 150 if (spi->n_bytes == 4) 151 *((u32 *)spi->rx_buf) = data; 152 else if (spi->n_bytes == 2) 153 *((u16 *)spi->rx_buf) = data; 154 else 155 *spi->rx_buf = data; 156 157 spi->rx_buf += spi->n_bytes; 158 } 159} 160 161static void mpfs_spi_enable_ints(struct mpfs_spi *spi) 162{ 163 u32 control = mpfs_spi_read(spi, REG_CONTROL); 164 165 control |= INT_ENABLE_MASK; 166 mpfs_spi_write(spi, REG_CONTROL, control); 167} 168 169static void mpfs_spi_disable_ints(struct mpfs_spi *spi) 170{ 171 u32 control = mpfs_spi_read(spi, REG_CONTROL); 172 173 control &= ~INT_ENABLE_MASK; 174 mpfs_spi_write(spi, REG_CONTROL, control); 175} 176 177static inline void mpfs_spi_set_xfer_size(struct mpfs_spi *spi, int len) 178{ 179 u32 control; 180 u32 lenpart; 181 u32 frames = mpfs_spi_read(spi, REG_FRAMESUP); 182 183 /* 184 * Writing to FRAMECNT in REG_CONTROL will reset the frame count, taking 185 * a shortcut requires an explicit clear. 186 */ 187 if (frames == len) { 188 mpfs_spi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT); 189 return; 190 } 191 192 /* 193 * The lower 16 bits of the frame count are stored in the control reg 194 * for legacy reasons, but the upper 16 written to a different register: 195 * FRAMESUP. While both the upper and lower bits can be *READ* from the 196 * FRAMESUP register, writing to the lower 16 bits is (supposedly) a NOP. 197 * 198 * The driver used to disable the controller while modifying the frame 199 * count, and mask off the lower 16 bits of len while writing to 200 * FRAMES_UP. When the driver was changed to disable the controller as 201 * infrequently as possible, it was discovered that the logic of 202 * lenpart = len & 0xffff_0000 203 * write(REG_FRAMESUP, lenpart) 204 * would actually write zeros into the lower 16 bits on an mpfs250t-es, 205 * despite documentation stating these bits were read-only. 206 * Writing len unmasked into FRAMES_UP ensures those bits aren't zeroed 207 * on an mpfs250t-es and will be a NOP for the lower 16 bits on hardware 208 * that matches the documentation. 209 */ 210 lenpart = len & 0xffff; 211 control = mpfs_spi_read(spi, REG_CONTROL); 212 control &= ~CONTROL_FRAMECNT_MASK; 213 control |= lenpart << CONTROL_FRAMECNT_SHIFT; 214 mpfs_spi_write(spi, REG_CONTROL, control); 215 mpfs_spi_write(spi, REG_FRAMESUP, len); 216} 217 218static inline void mpfs_spi_write_fifo(struct mpfs_spi *spi, int fifo_max) 219{ 220 int i = 0; 221 222 mpfs_spi_set_xfer_size(spi, fifo_max); 223 224 while ((i < fifo_max) && !(mpfs_spi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) { 225 u32 word; 226 227 if (spi->n_bytes == 4) 228 word = spi->tx_buf ? *((u32 *)spi->tx_buf) : 0xaa; 229 else if (spi->n_bytes == 2) 230 word = spi->tx_buf ? *((u16 *)spi->tx_buf) : 0xaa; 231 else 232 word = spi->tx_buf ? *spi->tx_buf : 0xaa; 233 234 mpfs_spi_write(spi, REG_TX_DATA, word); 235 if (spi->tx_buf) 236 spi->tx_buf += spi->n_bytes; 237 i++; 238 } 239 240 spi->tx_len -= i * spi->n_bytes; 241} 242 243static inline void mpfs_spi_set_framesize(struct mpfs_spi *spi, int bt) 244{ 245 u32 frame_size = mpfs_spi_read(spi, REG_FRAME_SIZE); 246 u32 control; 247 248 if ((frame_size & FRAME_SIZE_MASK) == bt) 249 return; 250 251 /* 252 * Disable the SPI controller. Writes to the frame size have 253 * no effect when the controller is enabled. 254 */ 255 control = mpfs_spi_read(spi, REG_CONTROL); 256 control &= ~CONTROL_ENABLE; 257 mpfs_spi_write(spi, REG_CONTROL, control); 258 259 mpfs_spi_write(spi, REG_FRAME_SIZE, bt); 260 261 control |= CONTROL_ENABLE; 262 mpfs_spi_write(spi, REG_CONTROL, control); 263} 264 265static void mpfs_spi_set_cs(struct spi_device *spi, bool disable) 266{ 267 u32 reg; 268 struct mpfs_spi *mspi = spi_controller_get_devdata(spi->controller); 269 270 reg = mpfs_spi_read(mspi, REG_SLAVE_SELECT); 271 reg &= ~BIT(spi_get_chipselect(spi, 0)); 272 reg |= !disable << spi_get_chipselect(spi, 0); 273 mspi->pending_slave_select = reg; 274 275 /* 276 * Only deassert chip select immediately. Writing to some registers 277 * requires the controller to be disabled, which results in the 278 * output pins being tristated and can cause the SCLK and MOSI lines 279 * to transition. Therefore asserting the chip select is deferred 280 * until just before writing to the TX FIFO, to ensure the device 281 * doesn't see any spurious clock transitions whilst CS is enabled. 282 */ 283 if (((spi->mode & SPI_CS_HIGH) == 0) == disable) 284 mpfs_spi_write(mspi, REG_SLAVE_SELECT, reg); 285} 286 287static int mpfs_spi_setup(struct spi_device *spi) 288{ 289 struct mpfs_spi *mspi = spi_controller_get_devdata(spi->controller); 290 u32 reg; 291 292 if (spi_is_csgpiod(spi)) 293 return 0; 294 295 /* 296 * Active high targets need to be specifically set to their inactive 297 * states during probe by adding them to the "control group" & thus 298 * driving their select line low. 299 */ 300 if (spi->mode & SPI_CS_HIGH) { 301 reg = mpfs_spi_read(mspi, REG_SLAVE_SELECT); 302 reg |= BIT(spi_get_chipselect(spi, 0)); 303 mspi->pending_slave_select = reg; 304 mpfs_spi_write(mspi, REG_SLAVE_SELECT, reg); 305 } 306 return 0; 307} 308 309static void mpfs_spi_init(struct spi_controller *host, struct mpfs_spi *spi) 310{ 311 unsigned long clk_hz; 312 u32 control = mpfs_spi_read(spi, REG_CONTROL); 313 314 control &= ~CONTROL_ENABLE; 315 mpfs_spi_write(spi, REG_CONTROL, control); 316 317 control |= CONTROL_MASTER; 318 control &= ~CONTROL_MODE_MASK; 319 control |= MOTOROLA_MODE; 320 321 /* 322 * The controller must be configured so that it doesn't remove Chip 323 * Select until the entire message has been transferred, even if at 324 * some points TX FIFO becomes empty. 325 * 326 * BIGFIFO mode is also enabled, which sets the fifo depth to 32 frames 327 * for the 8 bit transfers that this driver uses. 328 */ 329 control |= CONTROL_SPS | CONTROL_BIGFIFO; 330 331 mpfs_spi_write(spi, REG_CONTROL, control); 332 333 mpfs_spi_set_framesize(spi, DEFAULT_FRAMESIZE); 334 335 /* max. possible spi clock rate is the apb clock rate */ 336 clk_hz = clk_get_rate(spi->clk); 337 host->max_speed_hz = clk_hz; 338 339 mpfs_spi_enable_ints(spi); 340 341 /* 342 * It is required to enable direct mode, otherwise control over the chip 343 * select is relinquished to the hardware. SSELOUT is enabled too so we 344 * can deal with active high targets. 345 */ 346 spi->pending_slave_select = SSELOUT | SSEL_DIRECT; 347 mpfs_spi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); 348 349 control = mpfs_spi_read(spi, REG_CONTROL); 350 351 control &= ~CONTROL_RESET; 352 control |= CONTROL_ENABLE; 353 354 mpfs_spi_write(spi, REG_CONTROL, control); 355} 356 357static inline void mpfs_spi_set_clk_gen(struct mpfs_spi *spi) 358{ 359 u32 control; 360 361 control = mpfs_spi_read(spi, REG_CONTROL); 362 if (spi->clk_mode) 363 control |= CONTROL_CLKMODE; 364 else 365 control &= ~CONTROL_CLKMODE; 366 367 mpfs_spi_write(spi, REG_CLK_GEN, spi->clk_gen); 368 mpfs_spi_write(spi, REG_CONTROL, control); 369} 370 371static inline void mpfs_spi_set_mode(struct mpfs_spi *spi, unsigned int mode) 372{ 373 u32 mode_val; 374 u32 control = mpfs_spi_read(spi, REG_CONTROL); 375 376 switch (mode & SPI_MODE_X_MASK) { 377 case SPI_MODE_0: 378 mode_val = 0; 379 break; 380 case SPI_MODE_1: 381 mode_val = CONTROL_SPH; 382 break; 383 case SPI_MODE_2: 384 mode_val = CONTROL_SPO; 385 break; 386 case SPI_MODE_3: 387 mode_val = CONTROL_SPH | CONTROL_SPO; 388 break; 389 } 390 391 /* 392 * Disable the SPI controller. Writes to the frame protocol have 393 * no effect when the controller is enabled. 394 */ 395 396 control &= ~CONTROL_ENABLE; 397 mpfs_spi_write(spi, REG_CONTROL, control); 398 399 control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT); 400 control |= mode_val; 401 402 mpfs_spi_write(spi, REG_CONTROL, control); 403 404 control |= CONTROL_ENABLE; 405 mpfs_spi_write(spi, REG_CONTROL, control); 406} 407 408static irqreturn_t mpfs_spi_interrupt(int irq, void *dev_id) 409{ 410 struct spi_controller *host = dev_id; 411 struct mpfs_spi *spi = spi_controller_get_devdata(host); 412 u32 intfield = mpfs_spi_read(spi, REG_MIS) & 0xf; 413 bool finalise = false; 414 415 /* Interrupt line may be shared and not for us at all */ 416 if (intfield == 0) 417 return IRQ_NONE; 418 419 if (intfield & INT_RX_CHANNEL_OVERFLOW) { 420 mpfs_spi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); 421 finalise = true; 422 dev_err(&host->dev, 423 "%s: RX OVERFLOW: rxlen: %d, txlen: %d\n", __func__, 424 spi->rx_len, spi->tx_len); 425 } 426 427 if (intfield & INT_TX_CHANNEL_UNDERRUN) { 428 mpfs_spi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN); 429 finalise = true; 430 dev_err(&host->dev, 431 "%s: TX UNDERFLOW: rxlen: %d, txlen: %d\n", __func__, 432 spi->rx_len, spi->tx_len); 433 } 434 435 if (finalise) 436 spi_finalize_current_transfer(host); 437 438 return IRQ_HANDLED; 439} 440 441static int mpfs_spi_calculate_clkgen(struct mpfs_spi *spi, 442 unsigned long target_hz) 443{ 444 unsigned long clk_hz, spi_hz, clk_gen; 445 446 clk_hz = clk_get_rate(spi->clk); 447 if (!clk_hz) 448 return -EINVAL; 449 spi_hz = min(target_hz, clk_hz); 450 451 /* 452 * There are two possible clock modes for the controller generated 453 * clock's division ratio: 454 * CLK_MODE = 0: 1 / (2^(CLK_GEN + 1)) where CLK_GEN = 0 to 15. 455 * CLK_MODE = 1: 1 / (2 * CLK_GEN + 1) where CLK_GEN = 0 to 255. 456 * First try mode 1, fall back to 0 and if we have tried both modes and 457 * we /still/ can't get a good setting, we then throw the toys out of 458 * the pram and give up 459 * clk_gen is the register name for the clock divider on MPFS. 460 */ 461 clk_gen = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1; 462 if (clk_gen > CLK_GEN_MODE1_MAX || clk_gen <= CLK_GEN_MIN) { 463 clk_gen = DIV_ROUND_UP(clk_hz, spi_hz); 464 clk_gen = fls(clk_gen) - 1; 465 466 if (clk_gen > CLK_GEN_MODE0_MAX) 467 return -EINVAL; 468 469 spi->clk_mode = 0; 470 } else { 471 spi->clk_mode = 1; 472 } 473 474 spi->clk_gen = clk_gen; 475 return 0; 476} 477 478static int mpfs_spi_transfer_one(struct spi_controller *host, 479 struct spi_device *spi_dev, 480 struct spi_transfer *xfer) 481{ 482 struct mpfs_spi *spi = spi_controller_get_devdata(host); 483 int ret; 484 485 ret = mpfs_spi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz); 486 if (ret) { 487 dev_err(&host->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz); 488 return ret; 489 } 490 491 mpfs_spi_set_clk_gen(spi); 492 493 spi->tx_buf = xfer->tx_buf; 494 spi->rx_buf = xfer->rx_buf; 495 spi->tx_len = xfer->len; 496 spi->rx_len = xfer->len; 497 spi->n_bytes = roundup_pow_of_two(DIV_ROUND_UP(xfer->bits_per_word, BITS_PER_BYTE)); 498 499 mpfs_spi_set_framesize(spi, xfer->bits_per_word); 500 501 mpfs_spi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST); 502 503 mpfs_spi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); 504 505 while (spi->tx_len) { 506 int fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes); 507 508 mpfs_spi_write_fifo(spi, fifo_max); 509 mpfs_spi_read_fifo(spi, fifo_max); 510 } 511 512 spi_finalize_current_transfer(host); 513 return 1; 514} 515 516static int mpfs_spi_prepare_message(struct spi_controller *host, 517 struct spi_message *msg) 518{ 519 struct spi_device *spi_dev = msg->spi; 520 struct mpfs_spi *spi = spi_controller_get_devdata(host); 521 522 mpfs_spi_set_mode(spi, spi_dev->mode); 523 524 return 0; 525} 526 527static int mpfs_spi_probe(struct platform_device *pdev) 528{ 529 struct spi_controller *host; 530 struct mpfs_spi *spi; 531 struct resource *res; 532 u32 num_cs; 533 int ret = 0; 534 535 host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi)); 536 if (!host) 537 return dev_err_probe(&pdev->dev, -ENOMEM, 538 "unable to allocate host for SPI controller\n"); 539 540 platform_set_drvdata(pdev, host); 541 542 if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs)) 543 num_cs = MAX_CS; 544 545 host->num_chipselect = num_cs; 546 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 547 host->use_gpio_descriptors = true; 548 host->setup = mpfs_spi_setup; 549 host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); 550 host->transfer_one = mpfs_spi_transfer_one; 551 host->prepare_message = mpfs_spi_prepare_message; 552 host->set_cs = mpfs_spi_set_cs; 553 host->dev.of_node = pdev->dev.of_node; 554 555 spi = spi_controller_get_devdata(host); 556 557 spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 558 if (IS_ERR(spi->regs)) 559 return PTR_ERR(spi->regs); 560 561 spi->irq = platform_get_irq(pdev, 0); 562 if (spi->irq < 0) 563 return spi->irq; 564 565 ret = devm_request_irq(&pdev->dev, spi->irq, mpfs_spi_interrupt, 566 IRQF_SHARED, dev_name(&pdev->dev), host); 567 if (ret) 568 return dev_err_probe(&pdev->dev, ret, 569 "could not request irq\n"); 570 571 spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); 572 if (IS_ERR(spi->clk)) 573 return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), 574 "could not get clk\n"); 575 576 mpfs_spi_init(host, spi); 577 578 ret = devm_spi_register_controller(&pdev->dev, host); 579 if (ret) { 580 mpfs_spi_disable_ints(spi); 581 mpfs_spi_disable(spi); 582 return dev_err_probe(&pdev->dev, ret, 583 "unable to register host for SPI controller\n"); 584 } 585 586 dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num); 587 588 return 0; 589} 590 591static void mpfs_spi_remove(struct platform_device *pdev) 592{ 593 struct spi_controller *host = platform_get_drvdata(pdev); 594 struct mpfs_spi *spi = spi_controller_get_devdata(host); 595 596 mpfs_spi_disable_ints(spi); 597 mpfs_spi_disable(spi); 598} 599 600#define MICROCHIP_SPI_PM_OPS (NULL) 601 602/* 603 * Platform driver data structure 604 */ 605 606#if defined(CONFIG_OF) 607static const struct of_device_id mpfs_spi_dt_ids[] = { 608 { .compatible = "microchip,mpfs-spi" }, 609 { /* sentinel */ } 610}; 611MODULE_DEVICE_TABLE(of, mpfs_spi_dt_ids); 612#endif 613 614static struct platform_driver mpfs_spi_driver = { 615 .probe = mpfs_spi_probe, 616 .driver = { 617 .name = "microchip-spi", 618 .pm = MICROCHIP_SPI_PM_OPS, 619 .of_match_table = of_match_ptr(mpfs_spi_dt_ids), 620 }, 621 .remove = mpfs_spi_remove, 622}; 623module_platform_driver(mpfs_spi_driver); 624MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver"); 625MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>"); 626MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>"); 627MODULE_LICENSE("GPL");