linux/arch/m68k/coldfire/device.c
<<
>>
Prefs
   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
 537