device.c (15295B)
1/* 2 * device.c -- common ColdFire SoC device support 3 * 4 * (C) Copyright 2011, Greg Ungerer <gerg@uclinux.org> 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/init.h> 13#include <linux/io.h> 14#include <linux/spi/spi.h> 15#include <linux/gpio.h> 16#include <linux/fec.h> 17#include <linux/dmaengine.h> 18#include <asm/traps.h> 19#include <asm/coldfire.h> 20#include <asm/mcfsim.h> 21#include <asm/mcfuart.h> 22#include <asm/mcfqspi.h> 23#include <linux/platform_data/edma.h> 24#include <linux/platform_data/dma-mcf-edma.h> 25#include <linux/platform_data/mmc-esdhc-mcf.h> 26 27/* 28 * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. 29 */ 30static struct mcf_platform_uart mcf_uart_platform_data[] = { 31 { 32 .mapbase = MCFUART_BASE0, 33 .irq = MCF_IRQ_UART0, 34 }, 35 { 36 .mapbase = MCFUART_BASE1, 37 .irq = MCF_IRQ_UART1, 38 }, 39#ifdef MCFUART_BASE2 40 { 41 .mapbase = MCFUART_BASE2, 42 .irq = MCF_IRQ_UART2, 43 }, 44#endif 45#ifdef MCFUART_BASE3 46 { 47 .mapbase = MCFUART_BASE3, 48 .irq = MCF_IRQ_UART3, 49 }, 50#endif 51#ifdef MCFUART_BASE4 52 { 53 .mapbase = MCFUART_BASE4, 54 .irq = MCF_IRQ_UART4, 55 }, 56#endif 57#ifdef MCFUART_BASE5 58 { 59 .mapbase = MCFUART_BASE5, 60 .irq = MCF_IRQ_UART5, 61 }, 62#endif 63#ifdef MCFUART_BASE6 64 { 65 .mapbase = MCFUART_BASE6, 66 .irq = MCF_IRQ_UART6, 67 }, 68#endif 69#ifdef MCFUART_BASE7 70 { 71 .mapbase = MCFUART_BASE7, 72 .irq = MCF_IRQ_UART7, 73 }, 74#endif 75#ifdef MCFUART_BASE8 76 { 77 .mapbase = MCFUART_BASE8, 78 .irq = MCF_IRQ_UART8, 79 }, 80#endif 81#ifdef MCFUART_BASE9 82 { 83 .mapbase = MCFUART_BASE9, 84 .irq = MCF_IRQ_UART9, 85 }, 86#endif 87 { }, 88}; 89 90static struct platform_device mcf_uart = { 91 .name = "mcfuart", 92 .id = 0, 93 .dev.platform_data = mcf_uart_platform_data, 94}; 95 96#if IS_ENABLED(CONFIG_FEC) 97 98#ifdef CONFIG_M5441x 99#define FEC_NAME "enet-fec" 100static struct fec_platform_data fec_pdata = { 101 .phy = PHY_INTERFACE_MODE_RMII, 102}; 103#define FEC_PDATA (&fec_pdata) 104#else 105#define FEC_NAME "fec" 106#define FEC_PDATA NULL 107#endif 108 109/* 110 * Some ColdFire cores contain the Fast Ethernet Controller (FEC) 111 * block. It is Freescale's own hardware block. Some ColdFires 112 * have 2 of these. 113 */ 114static struct resource mcf_fec0_resources[] = { 115 { 116 .start = MCFFEC_BASE0, 117 .end = MCFFEC_BASE0 + MCFFEC_SIZE0 - 1, 118 .flags = IORESOURCE_MEM, 119 }, 120 { 121 .start = MCF_IRQ_FECRX0, 122 .end = MCF_IRQ_FECRX0, 123 .flags = IORESOURCE_IRQ, 124 }, 125 { 126 .start = MCF_IRQ_FECTX0, 127 .end = MCF_IRQ_FECTX0, 128 .flags = IORESOURCE_IRQ, 129 }, 130 { 131 .start = MCF_IRQ_FECENTC0, 132 .end = MCF_IRQ_FECENTC0, 133 .flags = IORESOURCE_IRQ, 134 }, 135}; 136 137static struct platform_device mcf_fec0 = { 138 .name = FEC_NAME, 139 .id = 0, 140 .num_resources = ARRAY_SIZE(mcf_fec0_resources), 141 .resource = mcf_fec0_resources, 142 .dev = { 143 .dma_mask = &mcf_fec0.dev.coherent_dma_mask, 144 .coherent_dma_mask = DMA_BIT_MASK(32), 145 .platform_data = FEC_PDATA, 146 } 147}; 148 149#ifdef MCFFEC_BASE1 150static struct resource mcf_fec1_resources[] = { 151 { 152 .start = MCFFEC_BASE1, 153 .end = MCFFEC_BASE1 + MCFFEC_SIZE1 - 1, 154 .flags = IORESOURCE_MEM, 155 }, 156 { 157 .start = MCF_IRQ_FECRX1, 158 .end = MCF_IRQ_FECRX1, 159 .flags = IORESOURCE_IRQ, 160 }, 161 { 162 .start = MCF_IRQ_FECTX1, 163 .end = MCF_IRQ_FECTX1, 164 .flags = IORESOURCE_IRQ, 165 }, 166 { 167 .start = MCF_IRQ_FECENTC1, 168 .end = MCF_IRQ_FECENTC1, 169 .flags = IORESOURCE_IRQ, 170 }, 171}; 172 173static struct platform_device mcf_fec1 = { 174 .name = FEC_NAME, 175 .id = 1, 176 .num_resources = ARRAY_SIZE(mcf_fec1_resources), 177 .resource = mcf_fec1_resources, 178 .dev = { 179 .dma_mask = &mcf_fec1.dev.coherent_dma_mask, 180 .coherent_dma_mask = DMA_BIT_MASK(32), 181 .platform_data = FEC_PDATA, 182 } 183}; 184#endif /* MCFFEC_BASE1 */ 185#endif /* CONFIG_FEC */ 186 187#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) 188/* 189 * The ColdFire QSPI module is an SPI protocol hardware block used 190 * on a number of different ColdFire CPUs. 191 */ 192static struct resource mcf_qspi_resources[] = { 193 { 194 .start = MCFQSPI_BASE, 195 .end = MCFQSPI_BASE + MCFQSPI_SIZE - 1, 196 .flags = IORESOURCE_MEM, 197 }, 198 { 199 .start = MCF_IRQ_QSPI, 200 .end = MCF_IRQ_QSPI, 201 .flags = IORESOURCE_IRQ, 202 }, 203}; 204 205static int mcf_cs_setup(struct mcfqspi_cs_control *cs_control) 206{ 207 int status; 208 209 status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0"); 210 if (status) { 211 pr_debug("gpio_request for MCFQSPI_CS0 failed\n"); 212 goto fail0; 213 } 214 status = gpio_direction_output(MCFQSPI_CS0, 1); 215 if (status) { 216 pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n"); 217 goto fail1; 218 } 219 220 status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1"); 221 if (status) { 222 pr_debug("gpio_request for MCFQSPI_CS1 failed\n"); 223 goto fail1; 224 } 225 status = gpio_direction_output(MCFQSPI_CS1, 1); 226 if (status) { 227 pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n"); 228 goto fail2; 229 } 230 231 status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2"); 232 if (status) { 233 pr_debug("gpio_request for MCFQSPI_CS2 failed\n"); 234 goto fail2; 235 } 236 status = gpio_direction_output(MCFQSPI_CS2, 1); 237 if (status) { 238 pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n"); 239 goto fail3; 240 } 241 242#ifdef MCFQSPI_CS3 243 status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3"); 244 if (status) { 245 pr_debug("gpio_request for MCFQSPI_CS3 failed\n"); 246 goto fail3; 247 } 248 status = gpio_direction_output(MCFQSPI_CS3, 1); 249 if (status) { 250 pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n"); 251 gpio_free(MCFQSPI_CS3); 252 goto fail3; 253 } 254#endif 255 256 return 0; 257 258fail3: 259 gpio_free(MCFQSPI_CS2); 260fail2: 261 gpio_free(MCFQSPI_CS1); 262fail1: 263 gpio_free(MCFQSPI_CS0); 264fail0: 265 return status; 266} 267 268static void mcf_cs_teardown(struct mcfqspi_cs_control *cs_control) 269{ 270#ifdef MCFQSPI_CS3 271 gpio_free(MCFQSPI_CS3); 272#endif 273 gpio_free(MCFQSPI_CS2); 274 gpio_free(MCFQSPI_CS1); 275 gpio_free(MCFQSPI_CS0); 276} 277 278static void mcf_cs_select(struct mcfqspi_cs_control *cs_control, 279 u8 chip_select, bool cs_high) 280{ 281 switch (chip_select) { 282 case 0: 283 gpio_set_value(MCFQSPI_CS0, cs_high); 284 break; 285 case 1: 286 gpio_set_value(MCFQSPI_CS1, cs_high); 287 break; 288 case 2: 289 gpio_set_value(MCFQSPI_CS2, cs_high); 290 break; 291#ifdef MCFQSPI_CS3 292 case 3: 293 gpio_set_value(MCFQSPI_CS3, cs_high); 294 break; 295#endif 296 } 297} 298 299static void mcf_cs_deselect(struct mcfqspi_cs_control *cs_control, 300 u8 chip_select, bool cs_high) 301{ 302 switch (chip_select) { 303 case 0: 304 gpio_set_value(MCFQSPI_CS0, !cs_high); 305 break; 306 case 1: 307 gpio_set_value(MCFQSPI_CS1, !cs_high); 308 break; 309 case 2: 310 gpio_set_value(MCFQSPI_CS2, !cs_high); 311 break; 312#ifdef MCFQSPI_CS3 313 case 3: 314 gpio_set_value(MCFQSPI_CS3, !cs_high); 315 break; 316#endif 317 } 318} 319 320static struct mcfqspi_cs_control mcf_cs_control = { 321 .setup = mcf_cs_setup, 322 .teardown = mcf_cs_teardown, 323 .select = mcf_cs_select, 324 .deselect = mcf_cs_deselect, 325}; 326 327static struct mcfqspi_platform_data mcf_qspi_data = { 328 .bus_num = 0, 329 .num_chipselect = 4, 330 .cs_control = &mcf_cs_control, 331}; 332 333static struct platform_device mcf_qspi = { 334 .name = "mcfqspi", 335 .id = 0, 336 .num_resources = ARRAY_SIZE(mcf_qspi_resources), 337 .resource = mcf_qspi_resources, 338 .dev.platform_data = &mcf_qspi_data, 339}; 340#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */ 341 342#if IS_ENABLED(CONFIG_I2C_IMX) 343static struct resource mcf_i2c0_resources[] = { 344 { 345 .start = MCFI2C_BASE0, 346 .end = MCFI2C_BASE0 + MCFI2C_SIZE0 - 1, 347 .flags = IORESOURCE_MEM, 348 }, 349 { 350 .start = MCF_IRQ_I2C0, 351 .end = MCF_IRQ_I2C0, 352 .flags = IORESOURCE_IRQ, 353 }, 354}; 355 356static struct platform_device mcf_i2c0 = { 357 .name = "imx1-i2c", 358 .id = 0, 359 .num_resources = ARRAY_SIZE(mcf_i2c0_resources), 360 .resource = mcf_i2c0_resources, 361}; 362#ifdef MCFI2C_BASE1 363 364static struct resource mcf_i2c1_resources[] = { 365 { 366 .start = MCFI2C_BASE1, 367 .end = MCFI2C_BASE1 + MCFI2C_SIZE1 - 1, 368 .flags = IORESOURCE_MEM, 369 }, 370 { 371 .start = MCF_IRQ_I2C1, 372 .end = MCF_IRQ_I2C1, 373 .flags = IORESOURCE_IRQ, 374 }, 375}; 376 377static struct platform_device mcf_i2c1 = { 378 .name = "imx1-i2c", 379 .id = 1, 380 .num_resources = ARRAY_SIZE(mcf_i2c1_resources), 381 .resource = mcf_i2c1_resources, 382}; 383 384#endif /* MCFI2C_BASE1 */ 385 386#ifdef MCFI2C_BASE2 387 388static struct resource mcf_i2c2_resources[] = { 389 { 390 .start = MCFI2C_BASE2, 391 .end = MCFI2C_BASE2 + MCFI2C_SIZE2 - 1, 392 .flags = IORESOURCE_MEM, 393 }, 394 { 395 .start = MCF_IRQ_I2C2, 396 .end = MCF_IRQ_I2C2, 397 .flags = IORESOURCE_IRQ, 398 }, 399}; 400 401static struct platform_device mcf_i2c2 = { 402 .name = "imx1-i2c", 403 .id = 2, 404 .num_resources = ARRAY_SIZE(mcf_i2c2_resources), 405 .resource = mcf_i2c2_resources, 406}; 407 408#endif /* MCFI2C_BASE2 */ 409 410#ifdef MCFI2C_BASE3 411 412static struct resource mcf_i2c3_resources[] = { 413 { 414 .start = MCFI2C_BASE3, 415 .end = MCFI2C_BASE3 + MCFI2C_SIZE3 - 1, 416 .flags = IORESOURCE_MEM, 417 }, 418 { 419 .start = MCF_IRQ_I2C3, 420 .end = MCF_IRQ_I2C3, 421 .flags = IORESOURCE_IRQ, 422 }, 423}; 424 425static struct platform_device mcf_i2c3 = { 426 .name = "imx1-i2c", 427 .id = 3, 428 .num_resources = ARRAY_SIZE(mcf_i2c3_resources), 429 .resource = mcf_i2c3_resources, 430}; 431 432#endif /* MCFI2C_BASE3 */ 433 434#ifdef MCFI2C_BASE4 435 436static struct resource mcf_i2c4_resources[] = { 437 { 438 .start = MCFI2C_BASE4, 439 .end = MCFI2C_BASE4 + MCFI2C_SIZE4 - 1, 440 .flags = IORESOURCE_MEM, 441 }, 442 { 443 .start = MCF_IRQ_I2C4, 444 .end = MCF_IRQ_I2C4, 445 .flags = IORESOURCE_IRQ, 446 }, 447}; 448 449static struct platform_device mcf_i2c4 = { 450 .name = "imx1-i2c", 451 .id = 4, 452 .num_resources = ARRAY_SIZE(mcf_i2c4_resources), 453 .resource = mcf_i2c4_resources, 454}; 455 456#endif /* MCFI2C_BASE4 */ 457 458#ifdef MCFI2C_BASE5 459 460static struct resource mcf_i2c5_resources[] = { 461 { 462 .start = MCFI2C_BASE5, 463 .end = MCFI2C_BASE5 + MCFI2C_SIZE5 - 1, 464 .flags = IORESOURCE_MEM, 465 }, 466 { 467 .start = MCF_IRQ_I2C5, 468 .end = MCF_IRQ_I2C5, 469 .flags = IORESOURCE_IRQ, 470 }, 471}; 472 473static struct platform_device mcf_i2c5 = { 474 .name = "imx1-i2c", 475 .id = 5, 476 .num_resources = ARRAY_SIZE(mcf_i2c5_resources), 477 .resource = mcf_i2c5_resources, 478}; 479 480#endif /* MCFI2C_BASE5 */ 481#endif /* IS_ENABLED(CONFIG_I2C_IMX) */ 482 483#ifdef MCFEDMA_BASE 484 485static const struct dma_slave_map mcf_edma_map[] = { 486 { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, 487 { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, 488 { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, 489 { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, 490 { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, 491 { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, 492 { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, 493 { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, 494 { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, 495 { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, 496 { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, 497 { "timer3", "rx-tx", MCF_EDMA_FILTER_PARAM(11) }, 498 { "fsl-dspi.0", "rx", MCF_EDMA_FILTER_PARAM(12) }, 499 { "fsl-dspi.0", "tx", MCF_EDMA_FILTER_PARAM(13) }, 500 { "fsl-dspi.1", "rx", MCF_EDMA_FILTER_PARAM(14) }, 501 { "fsl-dspi.1", "tx", MCF_EDMA_FILTER_PARAM(15) }, 502}; 503 504static struct mcf_edma_platform_data mcf_edma_data = { 505 .dma_channels = 64, 506 .slave_map = mcf_edma_map, 507 .slavecnt = ARRAY_SIZE(mcf_edma_map), 508}; 509 510static struct resource mcf_edma_resources[] = { 511 { 512 .start = MCFEDMA_BASE, 513 .end = MCFEDMA_BASE + MCFEDMA_SIZE - 1, 514 .flags = IORESOURCE_MEM, 515 }, 516 { 517 .start = MCFEDMA_IRQ_INTR0, 518 .end = MCFEDMA_IRQ_INTR0 + 15, 519 .flags = IORESOURCE_IRQ, 520 .name = "edma-tx-00-15", 521 }, 522 { 523 .start = MCFEDMA_IRQ_INTR16, 524 .end = MCFEDMA_IRQ_INTR16 + 39, 525 .flags = IORESOURCE_IRQ, 526 .name = "edma-tx-16-55", 527 }, 528 { 529 .start = MCFEDMA_IRQ_INTR56, 530 .end = MCFEDMA_IRQ_INTR56, 531 .flags = IORESOURCE_IRQ, 532 .name = "edma-tx-56-63", 533 }, 534 { 535 .start = MCFEDMA_IRQ_ERR, 536 .end = MCFEDMA_IRQ_ERR, 537 .flags = IORESOURCE_IRQ, 538 .name = "edma-err", 539 }, 540}; 541 542static u64 mcf_edma_dmamask = DMA_BIT_MASK(32); 543 544static struct platform_device mcf_edma = { 545 .name = "mcf-edma", 546 .id = 0, 547 .num_resources = ARRAY_SIZE(mcf_edma_resources), 548 .resource = mcf_edma_resources, 549 .dev = { 550 .dma_mask = &mcf_edma_dmamask, 551 .coherent_dma_mask = DMA_BIT_MASK(32), 552 .platform_data = &mcf_edma_data, 553 } 554}; 555#endif /* MCFEDMA_BASE */ 556 557#ifdef MCFSDHC_BASE 558static struct mcf_esdhc_platform_data mcf_esdhc_data = { 559 .max_bus_width = 4, 560 .cd_type = ESDHC_CD_NONE, 561}; 562 563static struct resource mcf_esdhc_resources[] = { 564 { 565 .start = MCFSDHC_BASE, 566 .end = MCFSDHC_BASE + MCFSDHC_SIZE - 1, 567 .flags = IORESOURCE_MEM, 568 }, { 569 .start = MCF_IRQ_SDHC, 570 .end = MCF_IRQ_SDHC, 571 .flags = IORESOURCE_IRQ, 572 }, 573}; 574 575static struct platform_device mcf_esdhc = { 576 .name = "sdhci-esdhc-mcf", 577 .id = 0, 578 .num_resources = ARRAY_SIZE(mcf_esdhc_resources), 579 .resource = mcf_esdhc_resources, 580 .dev.platform_data = &mcf_esdhc_data, 581}; 582#endif /* MCFSDHC_BASE */ 583 584#if IS_ENABLED(CONFIG_CAN_FLEXCAN) 585 586#include <linux/can/platform/flexcan.h> 587 588static struct flexcan_platform_data mcf5441x_flexcan_info = { 589 .clk_src = 1, 590 .clock_frequency = 120000000, 591}; 592 593static struct resource mcf5441x_flexcan0_resource[] = { 594 { 595 .start = MCFFLEXCAN_BASE0, 596 .end = MCFFLEXCAN_BASE0 + MCFFLEXCAN_SIZE, 597 .flags = IORESOURCE_MEM, 598 }, 599 { 600 .start = MCF_IRQ_IFL0, 601 .end = MCF_IRQ_IFL0, 602 .flags = IORESOURCE_IRQ, 603 }, 604 { 605 .start = MCF_IRQ_BOFF0, 606 .end = MCF_IRQ_BOFF0, 607 .flags = IORESOURCE_IRQ, 608 }, 609 { 610 .start = MCF_IRQ_ERR0, 611 .end = MCF_IRQ_ERR0, 612 .flags = IORESOURCE_IRQ, 613 }, 614}; 615 616static struct platform_device mcf_flexcan0 = { 617 .name = "flexcan-mcf5441x", 618 .id = 0, 619 .num_resources = ARRAY_SIZE(mcf5441x_flexcan0_resource), 620 .resource = mcf5441x_flexcan0_resource, 621 .dev.platform_data = &mcf5441x_flexcan_info, 622}; 623#endif /* IS_ENABLED(CONFIG_CAN_FLEXCAN) */ 624 625static struct platform_device *mcf_devices[] __initdata = { 626 &mcf_uart, 627#if IS_ENABLED(CONFIG_FEC) 628 &mcf_fec0, 629#ifdef MCFFEC_BASE1 630 &mcf_fec1, 631#endif 632#endif 633#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) 634 &mcf_qspi, 635#endif 636#if IS_ENABLED(CONFIG_I2C_IMX) 637 &mcf_i2c0, 638#ifdef MCFI2C_BASE1 639 &mcf_i2c1, 640#endif 641#ifdef MCFI2C_BASE2 642 &mcf_i2c2, 643#endif 644#ifdef MCFI2C_BASE3 645 &mcf_i2c3, 646#endif 647#ifdef MCFI2C_BASE4 648 &mcf_i2c4, 649#endif 650#ifdef MCFI2C_BASE5 651 &mcf_i2c5, 652#endif 653#endif 654#ifdef MCFEDMA_BASE 655 &mcf_edma, 656#endif 657#ifdef MCFSDHC_BASE 658 &mcf_esdhc, 659#endif 660#if IS_ENABLED(CONFIG_CAN_FLEXCAN) 661 &mcf_flexcan0, 662#endif 663}; 664 665/* 666 * Some ColdFire UARTs let you set the IRQ line to use. 667 */ 668static void __init mcf_uart_set_irq(void) 669{ 670#ifdef MCFUART_UIVR 671 /* UART0 interrupt setup */ 672 writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCFSIM_UART1ICR); 673 writeb(MCF_IRQ_UART0, MCFUART_BASE0 + MCFUART_UIVR); 674 mcf_mapirq2imr(MCF_IRQ_UART0, MCFINTC_UART0); 675 676 /* UART1 interrupt setup */ 677 writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCFSIM_UART2ICR); 678 writeb(MCF_IRQ_UART1, MCFUART_BASE1 + MCFUART_UIVR); 679 mcf_mapirq2imr(MCF_IRQ_UART1, MCFINTC_UART1); 680#endif 681} 682 683static int __init mcf_init_devices(void) 684{ 685 mcf_uart_set_irq(); 686 platform_add_devices(mcf_devices, ARRAY_SIZE(mcf_devices)); 687 return 0; 688} 689 690arch_initcall(mcf_init_devices);