root/drivers/pcmcia/sa1111_generic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sa1111_pcmcia_socket_state
  2. sa1111_pcmcia_configure_socket
  3. sa1111_pcmcia_add
  4. pcmcia_probe
  5. pcmcia_remove
  6. sa1111_drv_pcmcia_init
  7. sa1111_drv_pcmcia_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/drivers/pcmcia/sa1111_generic.c
   4  *
   5  * We implement the generic parts of a SA1111 PCMCIA driver.  This
   6  * basically means we handle everything except controlling the
   7  * power.  Power is machine specific...
   8  */
   9 #include <linux/module.h>
  10 #include <linux/kernel.h>
  11 #include <linux/ioport.h>
  12 #include <linux/device.h>
  13 #include <linux/interrupt.h>
  14 #include <linux/init.h>
  15 #include <linux/io.h>
  16 #include <linux/slab.h>
  17 
  18 #include <pcmcia/ss.h>
  19 
  20 #include <mach/hardware.h>
  21 #include <asm/hardware/sa1111.h>
  22 #include <asm/mach-types.h>
  23 #include <asm/irq.h>
  24 
  25 #include "sa1111_generic.h"
  26 
  27 /*
  28  * These are offsets from the above base.
  29  */
  30 #define PCCR    0x0000
  31 #define PCSSR   0x0004
  32 #define PCSR    0x0008
  33 
  34 #define PCSR_S0_READY   (1<<0)
  35 #define PCSR_S1_READY   (1<<1)
  36 #define PCSR_S0_DETECT  (1<<2)
  37 #define PCSR_S1_DETECT  (1<<3)
  38 #define PCSR_S0_VS1     (1<<4)
  39 #define PCSR_S0_VS2     (1<<5)
  40 #define PCSR_S1_VS1     (1<<6)
  41 #define PCSR_S1_VS2     (1<<7)
  42 #define PCSR_S0_WP      (1<<8)
  43 #define PCSR_S1_WP      (1<<9)
  44 #define PCSR_S0_BVD1    (1<<10)
  45 #define PCSR_S0_BVD2    (1<<11)
  46 #define PCSR_S1_BVD1    (1<<12)
  47 #define PCSR_S1_BVD2    (1<<13)
  48 
  49 #define PCCR_S0_RST     (1<<0)
  50 #define PCCR_S1_RST     (1<<1)
  51 #define PCCR_S0_FLT     (1<<2)
  52 #define PCCR_S1_FLT     (1<<3)
  53 #define PCCR_S0_PWAITEN (1<<4)
  54 #define PCCR_S1_PWAITEN (1<<5)
  55 #define PCCR_S0_PSE     (1<<6)
  56 #define PCCR_S1_PSE     (1<<7)
  57 
  58 #define PCSSR_S0_SLEEP  (1<<0)
  59 #define PCSSR_S1_SLEEP  (1<<1)
  60 
  61 #define IDX_IRQ_S0_READY_NINT   (0)
  62 #define IDX_IRQ_S0_CD_VALID     (1)
  63 #define IDX_IRQ_S0_BVD1_STSCHG  (2)
  64 #define IDX_IRQ_S1_READY_NINT   (3)
  65 #define IDX_IRQ_S1_CD_VALID     (4)
  66 #define IDX_IRQ_S1_BVD1_STSCHG  (5)
  67 #define NUM_IRQS                (6)
  68 
  69 void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
  70 {
  71         struct sa1111_pcmcia_socket *s = to_skt(skt);
  72         u32 status = readl_relaxed(s->dev->mapbase + PCSR);
  73 
  74         switch (skt->nr) {
  75         case 0:
  76                 state->detect = status & PCSR_S0_DETECT ? 0 : 1;
  77                 state->ready  = status & PCSR_S0_READY  ? 1 : 0;
  78                 state->bvd1   = status & PCSR_S0_BVD1   ? 1 : 0;
  79                 state->bvd2   = status & PCSR_S0_BVD2   ? 1 : 0;
  80                 state->wrprot = status & PCSR_S0_WP     ? 1 : 0;
  81                 state->vs_3v  = status & PCSR_S0_VS1    ? 0 : 1;
  82                 state->vs_Xv  = status & PCSR_S0_VS2    ? 0 : 1;
  83                 break;
  84 
  85         case 1:
  86                 state->detect = status & PCSR_S1_DETECT ? 0 : 1;
  87                 state->ready  = status & PCSR_S1_READY  ? 1 : 0;
  88                 state->bvd1   = status & PCSR_S1_BVD1   ? 1 : 0;
  89                 state->bvd2   = status & PCSR_S1_BVD2   ? 1 : 0;
  90                 state->wrprot = status & PCSR_S1_WP     ? 1 : 0;
  91                 state->vs_3v  = status & PCSR_S1_VS1    ? 0 : 1;
  92                 state->vs_Xv  = status & PCSR_S1_VS2    ? 0 : 1;
  93                 break;
  94         }
  95 }
  96 
  97 int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
  98 {
  99         struct sa1111_pcmcia_socket *s = to_skt(skt);
 100         u32 pccr_skt_mask, pccr_set_mask, val;
 101         unsigned long flags;
 102 
 103         switch (skt->nr) {
 104         case 0:
 105                 pccr_skt_mask = PCCR_S0_RST|PCCR_S0_FLT|PCCR_S0_PWAITEN|PCCR_S0_PSE;
 106                 break;
 107 
 108         case 1:
 109                 pccr_skt_mask = PCCR_S1_RST|PCCR_S1_FLT|PCCR_S1_PWAITEN|PCCR_S1_PSE;
 110                 break;
 111 
 112         default:
 113                 return -1;
 114         }
 115 
 116         pccr_set_mask = 0;
 117 
 118         if (state->Vcc != 0)
 119                 pccr_set_mask |= PCCR_S0_PWAITEN|PCCR_S1_PWAITEN;
 120         if (state->Vcc == 50)
 121                 pccr_set_mask |= PCCR_S0_PSE|PCCR_S1_PSE;
 122         if (state->flags & SS_RESET)
 123                 pccr_set_mask |= PCCR_S0_RST|PCCR_S1_RST;
 124         if (state->flags & SS_OUTPUT_ENA)
 125                 pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
 126 
 127         local_irq_save(flags);
 128         val = readl_relaxed(s->dev->mapbase + PCCR);
 129         val &= ~pccr_skt_mask;
 130         val |= pccr_set_mask & pccr_skt_mask;
 131         writel_relaxed(val, s->dev->mapbase + PCCR);
 132         local_irq_restore(flags);
 133 
 134         return 0;
 135 }
 136 
 137 int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops,
 138         int (*add)(struct soc_pcmcia_socket *))
 139 {
 140         struct sa1111_pcmcia_socket *s;
 141         struct clk *clk;
 142         int i, ret = 0, irqs[NUM_IRQS];
 143 
 144         clk = devm_clk_get(&dev->dev, NULL);
 145         if (IS_ERR(clk))
 146                 return PTR_ERR(clk);
 147 
 148         for (i = 0; i < NUM_IRQS; i++) {
 149                 irqs[i] = sa1111_get_irq(dev, i);
 150                 if (irqs[i] <= 0)
 151                         return irqs[i] ? : -ENXIO;
 152         }
 153 
 154         ops->socket_state = sa1111_pcmcia_socket_state;
 155 
 156         for (i = 0; i < ops->nr; i++) {
 157                 s = kzalloc(sizeof(*s), GFP_KERNEL);
 158                 if (!s)
 159                         return -ENOMEM;
 160 
 161                 s->soc.nr = ops->first + i;
 162                 s->soc.clk = clk;
 163 
 164                 soc_pcmcia_init_one(&s->soc, ops, &dev->dev);
 165                 s->dev = dev;
 166                 if (s->soc.nr) {
 167                         s->soc.socket.pci_irq = irqs[IDX_IRQ_S1_READY_NINT];
 168                         s->soc.stat[SOC_STAT_CD].irq = irqs[IDX_IRQ_S1_CD_VALID];
 169                         s->soc.stat[SOC_STAT_CD].name = "SA1111 CF card detect";
 170                         s->soc.stat[SOC_STAT_BVD1].irq = irqs[IDX_IRQ_S1_BVD1_STSCHG];
 171                         s->soc.stat[SOC_STAT_BVD1].name = "SA1111 CF BVD1";
 172                 } else {
 173                         s->soc.socket.pci_irq = irqs[IDX_IRQ_S0_READY_NINT];
 174                         s->soc.stat[SOC_STAT_CD].irq = irqs[IDX_IRQ_S0_CD_VALID];
 175                         s->soc.stat[SOC_STAT_CD].name = "SA1111 PCMCIA card detect";
 176                         s->soc.stat[SOC_STAT_BVD1].irq = irqs[IDX_IRQ_S0_BVD1_STSCHG];
 177                         s->soc.stat[SOC_STAT_BVD1].name = "SA1111 PCMCIA BVD1";
 178                 }
 179 
 180                 ret = add(&s->soc);
 181                 if (ret == 0) {
 182                         s->next = dev_get_drvdata(&dev->dev);
 183                         dev_set_drvdata(&dev->dev, s);
 184                 } else
 185                         kfree(s);
 186         }
 187 
 188         return ret;
 189 }
 190 
 191 static int pcmcia_probe(struct sa1111_dev *dev)
 192 {
 193         void __iomem *base;
 194         int ret;
 195 
 196         ret = sa1111_enable_device(dev);
 197         if (ret)
 198                 return ret;
 199 
 200         dev_set_drvdata(&dev->dev, NULL);
 201 
 202         if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) {
 203                 sa1111_disable_device(dev);
 204                 return -EBUSY;
 205         }
 206 
 207         base = dev->mapbase;
 208 
 209         /*
 210          * Initialise the suspend state.
 211          */
 212         writel_relaxed(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + PCSSR);
 213         writel_relaxed(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR);
 214 
 215         ret = -ENODEV;
 216 #ifdef CONFIG_SA1100_BADGE4
 217         if (machine_is_badge4())
 218                 ret = pcmcia_badge4_init(dev);
 219 #endif
 220 #ifdef CONFIG_SA1100_JORNADA720
 221         if (machine_is_jornada720())
 222                 ret = pcmcia_jornada720_init(dev);
 223 #endif
 224 #ifdef CONFIG_ARCH_LUBBOCK
 225         if (machine_is_lubbock())
 226                 ret = pcmcia_lubbock_init(dev);
 227 #endif
 228 #ifdef CONFIG_ASSABET_NEPONSET
 229         if (machine_is_assabet())
 230                 ret = pcmcia_neponset_init(dev);
 231 #endif
 232 
 233         if (ret) {
 234                 release_mem_region(dev->res.start, 512);
 235                 sa1111_disable_device(dev);
 236         }
 237 
 238         return ret;
 239 }
 240 
 241 static int pcmcia_remove(struct sa1111_dev *dev)
 242 {
 243         struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev);
 244 
 245         dev_set_drvdata(&dev->dev, NULL);
 246 
 247         for (; s; s = next) {
 248                 next = s->next;
 249                 soc_pcmcia_remove_one(&s->soc);
 250                 kfree(s);
 251         }
 252 
 253         release_mem_region(dev->res.start, 512);
 254         sa1111_disable_device(dev);
 255         return 0;
 256 }
 257 
 258 static struct sa1111_driver pcmcia_driver = {
 259         .drv = {
 260                 .name   = "sa1111-pcmcia",
 261         },
 262         .devid          = SA1111_DEVID_PCMCIA,
 263         .probe          = pcmcia_probe,
 264         .remove         = pcmcia_remove,
 265 };
 266 
 267 static int __init sa1111_drv_pcmcia_init(void)
 268 {
 269         return sa1111_driver_register(&pcmcia_driver);
 270 }
 271 
 272 static void __exit sa1111_drv_pcmcia_exit(void)
 273 {
 274         sa1111_driver_unregister(&pcmcia_driver);
 275 }
 276 
 277 fs_initcall(sa1111_drv_pcmcia_init);
 278 module_exit(sa1111_drv_pcmcia_exit);
 279 
 280 MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
 281 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */