linux/drivers/pcmcia/au1000_pb1x00.c
<<
>>
Prefs
   1/*
   2 *
   3 * Alchemy Semi Pb1000 boards specific pcmcia routines.
   4 *
   5 * Copyright 2002 MontaVista Software Inc.
   6 * Author: MontaVista Software, Inc.
   7 *              ppopov@mvista.com or source@mvista.com
   8 *
   9 * ########################################################################
  10 *
  11 *  This program is free software; you can distribute it and/or modify it
  12 *  under the terms of the GNU General Public License (Version 2) as
  13 *  published by the Free Software Foundation.
  14 *
  15 *  This program is distributed in the hope it will be useful, but WITHOUT
  16 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  18 *  for more details.
  19 *
  20 *  You should have received a copy of the GNU General Public License along
  21 *  with this program; if not, write to the Free Software Foundation, Inc.,
  22 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  23 */
  24#include <linux/module.h>
  25#include <linux/init.h>
  26#include <linux/delay.h>
  27#include <linux/ioport.h>
  28#include <linux/kernel.h>
  29#include <linux/timer.h>
  30#include <linux/mm.h>
  31#include <linux/proc_fs.h>
  32#include <linux/types.h>
  33
  34#include <pcmcia/ss.h>
  35#include <pcmcia/cistpl.h>
  36
  37#include <asm/io.h>
  38#include <asm/irq.h>
  39#include <asm/system.h>
  40
  41#include <asm/au1000.h>
  42#include <asm/au1000_pcmcia.h>
  43
  44#define debug(fmt, arg...) do { } while (0)
  45
  46#include <asm/pb1000.h>
  47#define PCMCIA_IRQ AU1000_GPIO_15
  48
  49static int pb1x00_pcmcia_init(struct pcmcia_init *init)
  50{
  51        u16 pcr;
  52        pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
  53
  54        au_writel(0x8000, PB1000_MDR); /* clear pcmcia interrupt */
  55        au_sync_delay(100);
  56        au_writel(0x4000, PB1000_MDR); /* enable pcmcia interrupt */
  57        au_sync();
  58
  59        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
  60        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
  61        au_writel(pcr, PB1000_PCR);
  62        au_sync_delay(20);
  63          
  64        return PCMCIA_NUM_SOCKS;
  65}
  66
  67static int pb1x00_pcmcia_shutdown(void)
  68{
  69        u16 pcr;
  70        pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
  71        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
  72        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
  73        au_writel(pcr, PB1000_PCR);
  74        au_sync_delay(20);
  75        return 0;
  76}
  77
  78static int 
  79pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
  80{
  81        u32 inserted0, inserted1;
  82        u16 vs0, vs1;
  83
  84        vs0 = vs1 = (u16)au_readl(PB1000_ACR1);
  85        inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2));
  86        inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2));
  87        vs0 = (vs0 >> 4) & 0x3;
  88        vs1 = (vs1 >> 12) & 0x3;
  89
  90        state->ready = 0;
  91        state->vs_Xv = 0;
  92        state->vs_3v = 0;
  93        state->detect = 0;
  94
  95        if (sock == 0) {
  96                if (inserted0) {
  97                        switch (vs0) {
  98                                case 0:
  99                                case 2:
 100                                        state->vs_3v=1;
 101                                        break;
 102                                case 3: /* 5V */
 103                                        break;
 104                                default:
 105                                        /* return without setting 'detect' */
 106                                        printk(KERN_ERR "pb1x00 bad VS (%d)\n",
 107                                                        vs0);
 108                                        return 0;
 109                        }
 110                        state->detect = 1;
 111                }
 112        }
 113        else  {
 114                if (inserted1) {
 115                        switch (vs1) {
 116                                case 0:
 117                                case 2:
 118                                        state->vs_3v=1;
 119                                        break;
 120                                case 3: /* 5V */
 121                                        break;
 122                                default:
 123                                        /* return without setting 'detect' */
 124                                        printk(KERN_ERR "pb1x00 bad VS (%d)\n",
 125                                                        vs1);
 126                                        return 0;
 127                        }
 128                        state->detect = 1;
 129                }
 130        }
 131
 132        if (state->detect) {
 133                state->ready = 1;
 134        }
 135
 136        state->bvd1=1;
 137        state->bvd2=1;
 138        state->wrprot=0; 
 139        return 1;
 140}
 141
 142
 143static int pb1x00_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
 144{
 145
 146        if(info->sock > PCMCIA_MAX_SOCK) return -1;
 147
 148        /*
 149         * Even in the case of the Pb1000, both sockets are connected
 150         * to the same irq line.
 151         */
 152        info->irq = PCMCIA_IRQ;
 153
 154        return 0;
 155}
 156
 157
 158static int 
 159pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
 160{
 161        u16 pcr;
 162
 163        if(configure->sock > PCMCIA_MAX_SOCK) return -1;
 164
 165        pcr = au_readl(PB1000_PCR);
 166
 167        if (configure->sock == 0) {
 168                pcr &= ~(PCR_SLOT_0_VCC0 | PCR_SLOT_0_VCC1 | 
 169                                PCR_SLOT_0_VPP0 | PCR_SLOT_0_VPP1);
 170        }
 171        else  {
 172                pcr &= ~(PCR_SLOT_1_VCC0 | PCR_SLOT_1_VCC1 | 
 173                                PCR_SLOT_1_VPP0 | PCR_SLOT_1_VPP1);
 174        }
 175
 176        pcr &= ~PCR_SLOT_0_RST;
 177        debug("Vcc %dV Vpp %dV, pcr %x\n", 
 178                        configure->vcc, configure->vpp, pcr);
 179        switch(configure->vcc){
 180                case 0:  /* Vcc 0 */
 181                        switch(configure->vpp) {
 182                                case 0:
 183                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_GND,
 184                                                        configure->sock);
 185                                        break;
 186                                case 12:
 187                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_12V,
 188                                                        configure->sock);
 189                                        break;
 190                                case 50:
 191                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_5V,
 192                                                        configure->sock);
 193                                        break;
 194                                case 33:
 195                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_3V,
 196                                                        configure->sock);
 197                                        break;
 198                                default:
 199                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
 200                                                        configure->sock);
 201                                        printk("%s: bad Vcc/Vpp (%d:%d)\n", 
 202                                                        __func__,
 203                                                        configure->vcc, 
 204                                                        configure->vpp);
 205                                        break;
 206                        }
 207                        break;
 208                case 50: /* Vcc 5V */
 209                        switch(configure->vpp) {
 210                                case 0:
 211                                        pcr |= SET_VCC_VPP(VCC_5V,VPP_GND,
 212                                                        configure->sock);
 213                                        break;
 214                                case 50:
 215                                        pcr |= SET_VCC_VPP(VCC_5V,VPP_5V,
 216                                                        configure->sock);
 217                                        break;
 218                                case 12:
 219                                        pcr |= SET_VCC_VPP(VCC_5V,VPP_12V,
 220                                                        configure->sock);
 221                                        break;
 222                                case 33:
 223                                        pcr |= SET_VCC_VPP(VCC_5V,VPP_3V,
 224                                                        configure->sock);
 225                                        break;
 226                                default:
 227                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
 228                                                        configure->sock);
 229                                        printk("%s: bad Vcc/Vpp (%d:%d)\n", 
 230                                                        __func__,
 231                                                        configure->vcc, 
 232                                                        configure->vpp);
 233                                        break;
 234                        }
 235                        break;
 236                case 33: /* Vcc 3.3V */
 237                        switch(configure->vpp) {
 238                                case 0:
 239                                        pcr |= SET_VCC_VPP(VCC_3V,VPP_GND,
 240                                                        configure->sock);
 241                                        break;
 242                                case 50:
 243                                        pcr |= SET_VCC_VPP(VCC_3V,VPP_5V,
 244                                                        configure->sock);
 245                                        break;
 246                                case 12:
 247                                        pcr |= SET_VCC_VPP(VCC_3V,VPP_12V,
 248                                                        configure->sock);
 249                                        break;
 250                                case 33:
 251                                        pcr |= SET_VCC_VPP(VCC_3V,VPP_3V,
 252                                                        configure->sock);
 253                                        break;
 254                                default:
 255                                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
 256                                                        configure->sock);
 257                                        printk("%s: bad Vcc/Vpp (%d:%d)\n", 
 258                                                        __func__,
 259                                                        configure->vcc, 
 260                                                        configure->vpp);
 261                                        break;
 262                        }
 263                        break;
 264                default: /* what's this ? */
 265                        pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock);
 266                        printk(KERN_ERR "%s: bad Vcc %d\n", 
 267                                        __func__, configure->vcc);
 268                        break;
 269        }
 270
 271        if (configure->sock == 0) {
 272        pcr &= ~(PCR_SLOT_0_RST);
 273                if (configure->reset)
 274                pcr |= PCR_SLOT_0_RST;
 275        }
 276        else {
 277                pcr &= ~(PCR_SLOT_1_RST);
 278                if (configure->reset)
 279                        pcr |= PCR_SLOT_1_RST;
 280        }
 281        au_writel(pcr, PB1000_PCR);
 282        au_sync_delay(300);
 283
 284        return 0;
 285}
 286
 287
 288struct pcmcia_low_level pb1x00_pcmcia_ops = { 
 289        pb1x00_pcmcia_init,
 290        pb1x00_pcmcia_shutdown,
 291        pb1x00_pcmcia_socket_state,
 292        pb1x00_pcmcia_get_irq_info,
 293        pb1x00_pcmcia_configure_socket
 294};
 295