linux/arch/mips/bcm63xx/dev-pcmcia.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   7 */
   8
   9#include <linux/init.h>
  10#include <linux/kernel.h>
  11#include <asm/bootinfo.h>
  12#include <linux/platform_device.h>
  13#include <bcm63xx_cs.h>
  14#include <bcm63xx_cpu.h>
  15#include <bcm63xx_dev_pcmcia.h>
  16#include <bcm63xx_io.h>
  17#include <bcm63xx_regs.h>
  18
  19static struct resource pcmcia_resources[] = {
  20        /* pcmcia registers */
  21        {
  22                /* start & end filled at runtime */
  23                .flags          = IORESOURCE_MEM,
  24        },
  25
  26        /* pcmcia memory zone resources */
  27        {
  28                .start          = BCM_PCMCIA_COMMON_BASE_PA,
  29                .end            = BCM_PCMCIA_COMMON_END_PA,
  30                .flags          = IORESOURCE_MEM,
  31        },
  32        {
  33                .start          = BCM_PCMCIA_ATTR_BASE_PA,
  34                .end            = BCM_PCMCIA_ATTR_END_PA,
  35                .flags          = IORESOURCE_MEM,
  36        },
  37        {
  38                .start          = BCM_PCMCIA_IO_BASE_PA,
  39                .end            = BCM_PCMCIA_IO_END_PA,
  40                .flags          = IORESOURCE_MEM,
  41        },
  42
  43        /* PCMCIA irq */
  44        {
  45                /* start filled at runtime */
  46                .flags          = IORESOURCE_IRQ,
  47        },
  48
  49        /* declare PCMCIA IO resource also */
  50        {
  51                .start          = BCM_PCMCIA_IO_BASE_PA,
  52                .end            = BCM_PCMCIA_IO_END_PA,
  53                .flags          = IORESOURCE_IO,
  54        },
  55};
  56
  57static struct bcm63xx_pcmcia_platform_data pd;
  58
  59static struct platform_device bcm63xx_pcmcia_device = {
  60        .name           = "bcm63xx_pcmcia",
  61        .id             = 0,
  62        .num_resources  = ARRAY_SIZE(pcmcia_resources),
  63        .resource       = pcmcia_resources,
  64        .dev            = {
  65                .platform_data = &pd,
  66        },
  67};
  68
  69static int __init config_pcmcia_cs(unsigned int cs,
  70                                   u32 base, unsigned int size)
  71{
  72        int ret;
  73
  74        ret = bcm63xx_set_cs_status(cs, 0);
  75        if (!ret)
  76                ret = bcm63xx_set_cs_base(cs, base, size);
  77        if (!ret)
  78                ret = bcm63xx_set_cs_status(cs, 1);
  79        return ret;
  80}
  81
  82static const struct {
  83        unsigned int    cs;
  84        unsigned int    base;
  85        unsigned int    size;
  86} pcmcia_cs[3] __initconst = {
  87        {
  88                .cs     = MPI_CS_PCMCIA_COMMON,
  89                .base   = BCM_PCMCIA_COMMON_BASE_PA,
  90                .size   = BCM_PCMCIA_COMMON_SIZE
  91        },
  92        {
  93                .cs     = MPI_CS_PCMCIA_ATTR,
  94                .base   = BCM_PCMCIA_ATTR_BASE_PA,
  95                .size   = BCM_PCMCIA_ATTR_SIZE
  96        },
  97        {
  98                .cs     = MPI_CS_PCMCIA_IO,
  99                .base   = BCM_PCMCIA_IO_BASE_PA,
 100                .size   = BCM_PCMCIA_IO_SIZE
 101        },
 102};
 103
 104int __init bcm63xx_pcmcia_register(void)
 105{
 106        int ret, i;
 107
 108        if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
 109                return 0;
 110
 111        /* use correct pcmcia ready gpio depending on processor */
 112        switch (bcm63xx_get_cpu_id()) {
 113        case BCM6348_CPU_ID:
 114                pd.ready_gpio = 22;
 115                break;
 116
 117        case BCM6358_CPU_ID:
 118                pd.ready_gpio = 18;
 119                break;
 120
 121        default:
 122                return -ENODEV;
 123        }
 124
 125        pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA);
 126        pcmcia_resources[0].end = pcmcia_resources[0].start +
 127                RSET_PCMCIA_SIZE - 1;
 128        pcmcia_resources[4].start = bcm63xx_get_irq_number(IRQ_PCMCIA);
 129
 130        /* configure pcmcia chip selects */
 131        for (i = 0; i < 3; i++) {
 132                ret = config_pcmcia_cs(pcmcia_cs[i].cs,
 133                                       pcmcia_cs[i].base,
 134                                       pcmcia_cs[i].size);
 135                if (ret)
 136                        goto out_err;
 137        }
 138
 139        return platform_device_register(&bcm63xx_pcmcia_device);
 140
 141out_err:
 142        pr_err("unable to set pcmcia chip select\n");
 143        return ret;
 144}
 145