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 102 struct mchp_corespi { 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 116 static inline u32 mchp_corespi_read(struct mchp_corespi *spi, unsigned int reg) 117 { 118 return readl(spi->regs + reg); 119 } 120 121 static inline void mchp_corespi_write(struct mchp_corespi *spi, unsigned int reg, u32 val) 122 { 123 writel(val, spi->regs + reg); 124 } 125 126 static inline void mchp_corespi_disable(struct mchp_corespi *spi) 127 { 128 u32 control = mchp_corespi_read(spi, REG_CONTROL); 129 130 control &= ~CONTROL_ENABLE; 131 132 mchp_corespi_write(spi, REG_CONTROL, control); 133 } 134 135 static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi, int fifo_max) 136 { 137 for (int i = 0; i < fifo_max; i++) { 138 u32 data; 139 140 while (mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY) 141 ; 142 143 data = mchp_corespi_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 161 static void mchp_corespi_enable_ints(struct mchp_corespi *spi) 162 { 163 u32 control = mchp_corespi_read(spi, REG_CONTROL); 164 165 control |= INT_ENABLE_MASK; 166 mchp_corespi_write(spi, REG_CONTROL, control); 167 } 168 169 static void mchp_corespi_disable_ints(struct mchp_corespi *spi) 170 { 171 u32 control = mchp_corespi_read(spi, REG_CONTROL); 172 173 control &= ~INT_ENABLE_MASK; 174 mchp_corespi_write(spi, REG_CONTROL, control); 175 } 176 177 static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len) 178 { 179 u32 control; 180 u32 lenpart; 181 u32 frames = mchp_corespi_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 mchp_corespi_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 = mchp_corespi_read(spi, REG_CONTROL); 212 control &= ~CONTROL_FRAMECNT_MASK; 213 control |= lenpart << CONTROL_FRAMECNT_SHIFT; 214 mchp_corespi_write(spi, REG_CONTROL, control); 215 mchp_corespi_write(spi, REG_FRAMESUP, len); 216 } 217 218 static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi, int fifo_max) 219 { 220 int i = 0; 221 222 mchp_corespi_set_xfer_size(spi, fifo_max); 223 224 while ((i < fifo_max) && !(mchp_corespi_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 mchp_corespi_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 243 static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt) 244 { 245 u32 frame_size = mchp_corespi_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 = mchp_corespi_read(spi, REG_CONTROL); 256 control &= ~CONTROL_ENABLE; 257 mchp_corespi_write(spi, REG_CONTROL, control); 258 259 mchp_corespi_write(spi, REG_FRAME_SIZE, bt); 260 261 control |= CONTROL_ENABLE; 262 mchp_corespi_write(spi, REG_CONTROL, control); 263 } 264 265 static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) 266 { 267 u32 reg; 268 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); 269 270 reg = mchp_corespi_read(corespi, REG_SLAVE_SELECT); 271 reg &= ~BIT(spi_get_chipselect(spi, 0)); 272 reg |= !disable << spi_get_chipselect(spi, 0); 273 corespi->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 mchp_corespi_write(corespi, REG_SLAVE_SELECT, reg); 285 } 286 287 static int mchp_corespi_setup(struct spi_device *spi) 288 { 289 struct mchp_corespi *corespi = 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 = mchp_corespi_read(corespi, REG_SLAVE_SELECT); 302 reg |= BIT(spi_get_chipselect(spi, 0)); 303 corespi->pending_slave_select = reg; 304 mchp_corespi_write(corespi, REG_SLAVE_SELECT, reg); 305 } 306 return 0; 307 } 308 309 static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *spi) 310 { 311 unsigned long clk_hz; 312 u32 control = mchp_corespi_read(spi, REG_CONTROL); 313 314 control &= ~CONTROL_ENABLE; 315 mchp_corespi_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 mchp_corespi_write(spi, REG_CONTROL, control); 332 333 mchp_corespi_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 mchp_corespi_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 mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); 348 349 control = mchp_corespi_read(spi, REG_CONTROL); 350 351 control &= ~CONTROL_RESET; 352 control |= CONTROL_ENABLE; 353 354 mchp_corespi_write(spi, REG_CONTROL, control); 355 } 356 357 static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi) 358 { 359 u32 control; 360 361 control = mchp_corespi_read(spi, REG_CONTROL); 362 if (spi->clk_mode) 363 control |= CONTROL_CLKMODE; 364 else 365 control &= ~CONTROL_CLKMODE; 366 367 mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen); 368 mchp_corespi_write(spi, REG_CONTROL, control); 369 } 370 371 static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode) 372 { 373 u32 mode_val; 374 u32 control = mchp_corespi_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 mchp_corespi_write(spi, REG_CONTROL, control); 398 399 control &= ~(SPI_MODE_X_MASK << MODE_X_MASK_SHIFT); 400 control |= mode_val; 401 402 mchp_corespi_write(spi, REG_CONTROL, control); 403 404 control |= CONTROL_ENABLE; 405 mchp_corespi_write(spi, REG_CONTROL, control); 406 } 407 408 static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id) 409 { 410 struct spi_controller *host = dev_id; 411 struct mchp_corespi *spi = spi_controller_get_devdata(host); 412 u32 intfield = mchp_corespi_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 mchp_corespi_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 mchp_corespi_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 441 static int mchp_corespi_calculate_clkgen(struct mchp_corespi *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 478 static int mchp_corespi_transfer_one(struct spi_controller *host, 479 struct spi_device *spi_dev, 480 struct spi_transfer *xfer) 481 { 482 struct mchp_corespi *spi = spi_controller_get_devdata(host); 483 int ret; 484 485 ret = mchp_corespi_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 mchp_corespi_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 mchp_corespi_set_framesize(spi, xfer->bits_per_word); 500 501 mchp_corespi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST); 502 503 mchp_corespi_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 mchp_corespi_write_fifo(spi, fifo_max); 509 mchp_corespi_read_fifo(spi, fifo_max); 510 } 511 512 spi_finalize_current_transfer(host); 513 return 1; 514 } 515 516 static int mchp_corespi_prepare_message(struct spi_controller *host, 517 struct spi_message *msg) 518 { 519 struct spi_device *spi_dev = msg->spi; 520 struct mchp_corespi *spi = spi_controller_get_devdata(host); 521 522 mchp_corespi_set_mode(spi, spi_dev->mode); 523 524 return 0; 525 } 526 527 static int mchp_corespi_probe(struct platform_device *pdev) 528 { 529 struct spi_controller *host; 530 struct mchp_corespi *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 = mchp_corespi_setup; 549 host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); 550 host->transfer_one = mchp_corespi_transfer_one; 551 host->prepare_message = mchp_corespi_prepare_message; 552 host->set_cs = mchp_corespi_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, mchp_corespi_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 mchp_corespi_init(host, spi); 577 578 ret = devm_spi_register_controller(&pdev->dev, host); 579 if (ret) { 580 mchp_corespi_disable(spi); 581 return dev_err_probe(&pdev->dev, ret, 582 "unable to register host for SPI controller\n"); 583 } 584 585 dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num); 586 587 return 0; 588 } 589 590 static void mchp_corespi_remove(struct platform_device *pdev) 591 { 592 struct spi_controller *host = platform_get_drvdata(pdev); 593 struct mchp_corespi *spi = spi_controller_get_devdata(host); 594 595 mchp_corespi_disable_ints(spi); 596 mchp_corespi_disable(spi); 597 } 598 599 #define MICROCHIP_SPI_PM_OPS (NULL) 600 601 /* 602 * Platform driver data structure 603 */ 604 605 #if defined(CONFIG_OF) 606 static const struct of_device_id mchp_corespi_dt_ids[] = { 607 { .compatible = "microchip,mpfs-spi" }, 608 { /* sentinel */ } 609 }; 610 MODULE_DEVICE_TABLE(of, mchp_corespi_dt_ids); 611 #endif 612 613 static struct platform_driver mchp_corespi_driver = { 614 .probe = mchp_corespi_probe, 615 .driver = { 616 .name = "microchip-corespi", 617 .pm = MICROCHIP_SPI_PM_OPS, 618 .of_match_table = of_match_ptr(mchp_corespi_dt_ids), 619 }, 620 .remove = mchp_corespi_remove, 621 }; 622 module_platform_driver(mchp_corespi_driver); 623 MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver"); 624 MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>"); 625 MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>"); 626 MODULE_LICENSE("GPL"); 627