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