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