root/drivers/pcmcia/pxa2xx_base.c

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

DEFINITIONS

This source file includes following definitions.
  1. pxa2xx_mcxx_hold
  2. pxa2xx_mcxx_asst
  3. pxa2xx_mcxx_setup
  4. pxa2xx_pcmcia_cmd_time
  5. pxa2xx_pcmcia_set_mcmem
  6. pxa2xx_pcmcia_set_mcio
  7. pxa2xx_pcmcia_set_mcatt
  8. pxa2xx_pcmcia_set_mcxx
  9. pxa2xx_pcmcia_set_timing
  10. pxa2xx_pcmcia_frequency_change
  11. pxa2xx_configure_sockets
  12. pxa2xx_drv_pcmcia_ops
  13. pxa2xx_drv_pcmcia_probe
  14. pxa2xx_drv_pcmcia_remove
  15. pxa2xx_drv_pcmcia_resume
  16. pxa2xx_pcmcia_init
  17. pxa2xx_pcmcia_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*======================================================================
   3 
   4   Device driver for the PCMCIA control functionality of PXA2xx
   5   microprocessors.
   6 
   7 
   8     (c) Ian Molton (spyro@f2s.com) 2003
   9     (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
  10 
  11     derived from sa11xx_base.c
  12 
  13      Portions created by John G. Dorsey are
  14      Copyright (C) 1999 John G. Dorsey.
  15 
  16   ======================================================================*/
  17 
  18 #include <linux/module.h>
  19 #include <linux/slab.h>
  20 #include <linux/init.h>
  21 #include <linux/cpufreq.h>
  22 #include <linux/ioport.h>
  23 #include <linux/kernel.h>
  24 #include <linux/spinlock.h>
  25 #include <linux/platform_device.h>
  26 
  27 #include <mach/hardware.h>
  28 #include <mach/smemc.h>
  29 #include <asm/io.h>
  30 #include <asm/irq.h>
  31 #include <mach/pxa2xx-regs.h>
  32 #include <asm/mach-types.h>
  33 
  34 #include <pcmcia/ss.h>
  35 #include <pcmcia/cistpl.h>
  36 
  37 #include "soc_common.h"
  38 #include "pxa2xx_base.h"
  39 
  40 /*
  41  * Personal Computer Memory Card International Association (PCMCIA) sockets
  42  */
  43 
  44 #define PCMCIAPrtSp     0x04000000      /* PCMCIA Partition Space [byte]   */
  45 #define PCMCIASp        (4*PCMCIAPrtSp) /* PCMCIA Space [byte]             */
  46 #define PCMCIAIOSp      PCMCIAPrtSp     /* PCMCIA I/O Space [byte]         */
  47 #define PCMCIAAttrSp    PCMCIAPrtSp     /* PCMCIA Attribute Space [byte]   */
  48 #define PCMCIAMemSp     PCMCIAPrtSp     /* PCMCIA Memory Space [byte]      */
  49 
  50 #define PCMCIA0Sp       PCMCIASp        /* PCMCIA 0 Space [byte]           */
  51 #define PCMCIA0IOSp     PCMCIAIOSp      /* PCMCIA 0 I/O Space [byte]       */
  52 #define PCMCIA0AttrSp   PCMCIAAttrSp    /* PCMCIA 0 Attribute Space [byte] */
  53 #define PCMCIA0MemSp    PCMCIAMemSp     /* PCMCIA 0 Memory Space [byte]    */
  54 
  55 #define PCMCIA1Sp       PCMCIASp        /* PCMCIA 1 Space [byte]           */
  56 #define PCMCIA1IOSp     PCMCIAIOSp      /* PCMCIA 1 I/O Space [byte]       */
  57 #define PCMCIA1AttrSp   PCMCIAAttrSp    /* PCMCIA 1 Attribute Space [byte] */
  58 #define PCMCIA1MemSp    PCMCIAMemSp     /* PCMCIA 1 Memory Space [byte]    */
  59 
  60 #define _PCMCIA(Nb)                     /* PCMCIA [0..1]                   */ \
  61                         (0x20000000 + (Nb) * PCMCIASp)
  62 #define _PCMCIAIO(Nb)   _PCMCIA(Nb)     /* PCMCIA I/O [0..1]               */
  63 #define _PCMCIAAttr(Nb)                 /* PCMCIA Attribute [0..1]         */ \
  64                         (_PCMCIA(Nb) + 2 * PCMCIAPrtSp)
  65 #define _PCMCIAMem(Nb)                  /* PCMCIA Memory [0..1]            */ \
  66                         (_PCMCIA(Nb) + 3 * PCMCIAPrtSp)
  67 
  68 #define _PCMCIA0        _PCMCIA(0)      /* PCMCIA 0                        */
  69 #define _PCMCIA0IO      _PCMCIAIO(0)    /* PCMCIA 0 I/O                    */
  70 #define _PCMCIA0Attr    _PCMCIAAttr(0)  /* PCMCIA 0 Attribute              */
  71 #define _PCMCIA0Mem     _PCMCIAMem(0)   /* PCMCIA 0 Memory                 */
  72 
  73 #define _PCMCIA1        _PCMCIA(1)      /* PCMCIA 1                        */
  74 #define _PCMCIA1IO      _PCMCIAIO(1)    /* PCMCIA 1 I/O                    */
  75 #define _PCMCIA1Attr    _PCMCIAAttr(1)  /* PCMCIA 1 Attribute              */
  76 #define _PCMCIA1Mem     _PCMCIAMem(1)   /* PCMCIA 1 Memory                 */
  77 
  78 
  79 #define MCXX_SETUP_MASK     (0x7f)
  80 #define MCXX_ASST_MASK      (0x1f)
  81 #define MCXX_HOLD_MASK      (0x3f)
  82 #define MCXX_SETUP_SHIFT    (0)
  83 #define MCXX_ASST_SHIFT     (7)
  84 #define MCXX_HOLD_SHIFT     (14)
  85 
  86 static inline u_int pxa2xx_mcxx_hold(u_int pcmcia_cycle_ns,
  87                                      u_int mem_clk_10khz)
  88 {
  89         u_int code = pcmcia_cycle_ns * mem_clk_10khz;
  90         return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
  91 }
  92 
  93 static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns,
  94                                      u_int mem_clk_10khz)
  95 {
  96         u_int code = pcmcia_cycle_ns * mem_clk_10khz;
  97         return (code / 300000) + ((code % 300000) ? 1 : 0) + 1;
  98 }
  99 
 100 static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns,
 101                                       u_int mem_clk_10khz)
 102 {
 103         u_int code = pcmcia_cycle_ns * mem_clk_10khz;
 104         return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
 105 }
 106 
 107 /* This function returns the (approximate) command assertion period, in
 108  * nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
 109  */
 110 static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
 111                                            u_int pcmcia_mcxx_asst)
 112 {
 113         return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
 114 }
 115 
 116 static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
 117 {
 118         uint32_t val;
 119 
 120         val = ((pxa2xx_mcxx_setup(speed, clock)
 121                 & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
 122                 | ((pxa2xx_mcxx_asst(speed, clock)
 123                 & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
 124                 | ((pxa2xx_mcxx_hold(speed, clock)
 125                 & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 126 
 127         __raw_writel(val, MCMEM(sock));
 128 
 129         return 0;
 130 }
 131 
 132 static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
 133 {
 134         uint32_t val;
 135 
 136         val = ((pxa2xx_mcxx_setup(speed, clock)
 137                 & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
 138                 | ((pxa2xx_mcxx_asst(speed, clock)
 139                 & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
 140                 | ((pxa2xx_mcxx_hold(speed, clock)
 141                 & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 142 
 143         __raw_writel(val, MCIO(sock));
 144 
 145         return 0;
 146 }
 147 
 148 static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
 149 {
 150         uint32_t val;
 151 
 152         val = ((pxa2xx_mcxx_setup(speed, clock)
 153                 & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
 154                 | ((pxa2xx_mcxx_asst(speed, clock)
 155                 & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
 156                 | ((pxa2xx_mcxx_hold(speed, clock)
 157                 & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 158 
 159         __raw_writel(val, MCATT(sock));
 160 
 161         return 0;
 162 }
 163 
 164 static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int clk)
 165 {
 166         struct soc_pcmcia_timing timing;
 167         int sock = skt->nr;
 168 
 169         soc_common_pcmcia_get_timing(skt, &timing);
 170 
 171         pxa2xx_pcmcia_set_mcmem(sock, timing.mem, clk);
 172         pxa2xx_pcmcia_set_mcatt(sock, timing.attr, clk);
 173         pxa2xx_pcmcia_set_mcio(sock, timing.io, clk);
 174 
 175         return 0;
 176 }
 177 
 178 static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
 179 {
 180         unsigned long clk = clk_get_rate(skt->clk);
 181         return pxa2xx_pcmcia_set_mcxx(skt, clk / 10000);
 182 }
 183 
 184 #ifdef CONFIG_CPU_FREQ
 185 
 186 static int
 187 pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
 188                                unsigned long val,
 189                                struct cpufreq_freqs *freqs)
 190 {
 191         switch (val) {
 192         case CPUFREQ_PRECHANGE:
 193                 if (freqs->new > freqs->old) {
 194                         debug(skt, 2, "new frequency %u.%uMHz > %u.%uMHz, "
 195                                "pre-updating\n",
 196                                freqs->new / 1000, (freqs->new / 100) % 10,
 197                                freqs->old / 1000, (freqs->old / 100) % 10);
 198                         pxa2xx_pcmcia_set_timing(skt);
 199                 }
 200                 break;
 201 
 202         case CPUFREQ_POSTCHANGE:
 203                 if (freqs->new < freqs->old) {
 204                         debug(skt, 2, "new frequency %u.%uMHz < %u.%uMHz, "
 205                                "post-updating\n",
 206                                freqs->new / 1000, (freqs->new / 100) % 10,
 207                                freqs->old / 1000, (freqs->old / 100) % 10);
 208                         pxa2xx_pcmcia_set_timing(skt);
 209                 }
 210                 break;
 211         }
 212         return 0;
 213 }
 214 #endif
 215 
 216 void pxa2xx_configure_sockets(struct device *dev, struct pcmcia_low_level *ops)
 217 {
 218         /*
 219          * We have at least one socket, so set MECR:CIT
 220          * (Card Is There)
 221          */
 222         uint32_t mecr = MECR_CIT;
 223 
 224         /* Set MECR:NOS (Number Of Sockets) */
 225         if ((ops->first + ops->nr) > 1 ||
 226             machine_is_viper() || machine_is_arcom_zeus())
 227                 mecr |= MECR_NOS;
 228 
 229         __raw_writel(mecr, MECR);
 230 }
 231 EXPORT_SYMBOL(pxa2xx_configure_sockets);
 232 
 233 static const char *skt_names[] = {
 234         "PCMCIA socket 0",
 235         "PCMCIA socket 1",
 236 };
 237 
 238 #define SKT_DEV_INFO_SIZE(n) \
 239         (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
 240 
 241 int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)
 242 {
 243         skt->res_skt.start = _PCMCIA(skt->nr);
 244         skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1;
 245         skt->res_skt.name = skt_names[skt->nr];
 246         skt->res_skt.flags = IORESOURCE_MEM;
 247 
 248         skt->res_io.start = _PCMCIAIO(skt->nr);
 249         skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
 250         skt->res_io.name = "io";
 251         skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 252 
 253         skt->res_mem.start = _PCMCIAMem(skt->nr);
 254         skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
 255         skt->res_mem.name = "memory";
 256         skt->res_mem.flags = IORESOURCE_MEM;
 257 
 258         skt->res_attr.start = _PCMCIAAttr(skt->nr);
 259         skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
 260         skt->res_attr.name = "attribute";
 261         skt->res_attr.flags = IORESOURCE_MEM;
 262 
 263         return soc_pcmcia_add_one(skt);
 264 }
 265 EXPORT_SYMBOL(pxa2xx_drv_pcmcia_add_one);
 266 
 267 void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
 268 {
 269         /* Provide our PXA2xx specific timing routines. */
 270         ops->set_timing  = pxa2xx_pcmcia_set_timing;
 271 #ifdef CONFIG_CPU_FREQ
 272         ops->frequency_change = pxa2xx_pcmcia_frequency_change;
 273 #endif
 274 }
 275 EXPORT_SYMBOL(pxa2xx_drv_pcmcia_ops);
 276 
 277 static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
 278 {
 279         int i, ret = 0;
 280         struct pcmcia_low_level *ops;
 281         struct skt_dev_info *sinfo;
 282         struct soc_pcmcia_socket *skt;
 283         struct clk *clk;
 284 
 285         ops = (struct pcmcia_low_level *)dev->dev.platform_data;
 286         if (!ops) {
 287                 ret = -ENODEV;
 288                 goto err0;
 289         }
 290 
 291         if (cpu_is_pxa320() && ops->nr > 1) {
 292                 dev_err(&dev->dev, "pxa320 supports only one pcmcia slot");
 293                 ret = -EINVAL;
 294                 goto err0;
 295         }
 296 
 297         clk = devm_clk_get(&dev->dev, NULL);
 298         if (IS_ERR(clk))
 299                 return -ENODEV;
 300 
 301         pxa2xx_drv_pcmcia_ops(ops);
 302 
 303         sinfo = devm_kzalloc(&dev->dev, SKT_DEV_INFO_SIZE(ops->nr),
 304                              GFP_KERNEL);
 305         if (!sinfo)
 306                 return -ENOMEM;
 307 
 308         sinfo->nskt = ops->nr;
 309 
 310         /* Initialize processor specific parameters */
 311         for (i = 0; i < ops->nr; i++) {
 312                 skt = &sinfo->skt[i];
 313 
 314                 skt->nr = ops->first + i;
 315                 skt->clk = clk;
 316                 soc_pcmcia_init_one(skt, ops, &dev->dev);
 317 
 318                 ret = pxa2xx_drv_pcmcia_add_one(skt);
 319                 if (ret)
 320                         goto err1;
 321         }
 322 
 323         pxa2xx_configure_sockets(&dev->dev, ops);
 324         dev_set_drvdata(&dev->dev, sinfo);
 325 
 326         return 0;
 327 
 328 err1:
 329         while (--i >= 0)
 330                 soc_pcmcia_remove_one(&sinfo->skt[i]);
 331 
 332 err0:
 333         return ret;
 334 }
 335 
 336 static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
 337 {
 338         struct skt_dev_info *sinfo = platform_get_drvdata(dev);
 339         int i;
 340 
 341         for (i = 0; i < sinfo->nskt; i++)
 342                 soc_pcmcia_remove_one(&sinfo->skt[i]);
 343 
 344         return 0;
 345 }
 346 
 347 static int pxa2xx_drv_pcmcia_resume(struct device *dev)
 348 {
 349         struct pcmcia_low_level *ops = (struct pcmcia_low_level *)dev->platform_data;
 350 
 351         pxa2xx_configure_sockets(dev, ops);
 352         return 0;
 353 }
 354 
 355 static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = {
 356         .resume         = pxa2xx_drv_pcmcia_resume,
 357 };
 358 
 359 static struct platform_driver pxa2xx_pcmcia_driver = {
 360         .probe          = pxa2xx_drv_pcmcia_probe,
 361         .remove         = pxa2xx_drv_pcmcia_remove,
 362         .driver         = {
 363                 .name   = "pxa2xx-pcmcia",
 364                 .pm     = &pxa2xx_drv_pcmcia_pm_ops,
 365         },
 366 };
 367 
 368 static int __init pxa2xx_pcmcia_init(void)
 369 {
 370         return platform_driver_register(&pxa2xx_pcmcia_driver);
 371 }
 372 
 373 static void __exit pxa2xx_pcmcia_exit(void)
 374 {
 375         platform_driver_unregister(&pxa2xx_pcmcia_driver);
 376 }
 377 
 378 fs_initcall(pxa2xx_pcmcia_init);
 379 module_exit(pxa2xx_pcmcia_exit);
 380 
 381 MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>");
 382 MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA2xx core socket driver");
 383 MODULE_LICENSE("GPL");
 384 MODULE_ALIAS("platform:pxa2xx-pcmcia");

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