Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PCMCIA socket code for the MyCable XXS1500 system.
0004  *
0005  * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>
0006  *
0007  */
0008 
0009 #include <linux/delay.h>
0010 #include <linux/gpio.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/io.h>
0013 #include <linux/ioport.h>
0014 #include <linux/mm.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/pm.h>
0018 #include <linux/resource.h>
0019 #include <linux/slab.h>
0020 #include <linux/spinlock.h>
0021 
0022 #include <pcmcia/ss.h>
0023 #include <pcmcia/cistpl.h>
0024 
0025 #include <asm/irq.h>
0026 #include <asm/mach-au1x00/au1000.h>
0027 
0028 #define MEM_MAP_SIZE    0x400000
0029 #define IO_MAP_SIZE 0x1000
0030 
0031 
0032 /*
0033  * 3.3V cards only; all interfacing is done via gpios:
0034  *
0035  * 0/1:  carddetect (00 = card present, xx = huh)
0036  * 4:    card irq
0037  * 204:  reset (high-act)
0038  * 205:  buffer enable (low-act)
0039  * 208/209: card voltage key (00,01,10,11)
0040  * 210:  battwarn
0041  * 211:  batdead
0042  * 214:  power (low-act)
0043  */
0044 #define GPIO_CDA    0
0045 #define GPIO_CDB    1
0046 #define GPIO_CARDIRQ    4
0047 #define GPIO_RESET  204
0048 #define GPIO_OUTEN  205
0049 #define GPIO_VSL    208
0050 #define GPIO_VSH    209
0051 #define GPIO_BATTDEAD   210
0052 #define GPIO_BATTWARN   211
0053 #define GPIO_POWER  214
0054 
0055 struct xxs1500_pcmcia_sock {
0056     struct pcmcia_socket    socket;
0057     void        *virt_io;
0058 
0059     phys_addr_t phys_io;
0060     phys_addr_t phys_attr;
0061     phys_addr_t phys_mem;
0062 
0063     /* previous flags for set_socket() */
0064     unsigned int old_flags;
0065 };
0066 
0067 #define to_xxs_socket(x) container_of(x, struct xxs1500_pcmcia_sock, socket)
0068 
0069 static irqreturn_t cdirq(int irq, void *data)
0070 {
0071     struct xxs1500_pcmcia_sock *sock = data;
0072 
0073     pcmcia_parse_events(&sock->socket, SS_DETECT);
0074 
0075     return IRQ_HANDLED;
0076 }
0077 
0078 static int xxs1500_pcmcia_configure(struct pcmcia_socket *skt,
0079                     struct socket_state_t *state)
0080 {
0081     struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
0082     unsigned int changed;
0083 
0084     /* power control */
0085     switch (state->Vcc) {
0086     case 0:
0087         gpio_set_value(GPIO_POWER, 1);  /* power off */
0088         break;
0089     case 33:
0090         gpio_set_value(GPIO_POWER, 0);  /* power on */
0091         break;
0092     case 50:
0093     default:
0094         return -EINVAL;
0095     }
0096 
0097     changed = state->flags ^ sock->old_flags;
0098 
0099     if (changed & SS_RESET) {
0100         if (state->flags & SS_RESET) {
0101             gpio_set_value(GPIO_RESET, 1);  /* assert reset */
0102             gpio_set_value(GPIO_OUTEN, 1);  /* buffers off */
0103         } else {
0104             gpio_set_value(GPIO_RESET, 0);  /* deassert reset */
0105             gpio_set_value(GPIO_OUTEN, 0);  /* buffers on */
0106             msleep(500);
0107         }
0108     }
0109 
0110     sock->old_flags = state->flags;
0111 
0112     return 0;
0113 }
0114 
0115 static int xxs1500_pcmcia_get_status(struct pcmcia_socket *skt,
0116                      unsigned int *value)
0117 {
0118     unsigned int status;
0119     int i;
0120 
0121     status = 0;
0122 
0123     /* check carddetects: GPIO[0:1] must both be low */
0124     if (!gpio_get_value(GPIO_CDA) && !gpio_get_value(GPIO_CDB))
0125         status |= SS_DETECT;
0126 
0127     /* determine card voltage: GPIO[208:209] binary value */
0128     i = (!!gpio_get_value(GPIO_VSL)) | ((!!gpio_get_value(GPIO_VSH)) << 1);
0129 
0130     switch (i) {
0131     case 0:
0132     case 1:
0133     case 2:
0134         status |= SS_3VCARD;    /* 3V card */
0135         break;
0136     case 3:             /* 5V card, unsupported */
0137     default:
0138         status |= SS_XVCARD;    /* treated as unsupported in core */
0139     }
0140 
0141     /* GPIO214: low active power switch */
0142     status |= gpio_get_value(GPIO_POWER) ? 0 : SS_POWERON;
0143 
0144     /* GPIO204: high-active reset line */
0145     status |= gpio_get_value(GPIO_RESET) ? SS_RESET : SS_READY;
0146 
0147     /* other stuff */
0148     status |= gpio_get_value(GPIO_BATTDEAD) ? 0 : SS_BATDEAD;
0149     status |= gpio_get_value(GPIO_BATTWARN) ? 0 : SS_BATWARN;
0150 
0151     *value = status;
0152 
0153     return 0;
0154 }
0155 
0156 static int xxs1500_pcmcia_sock_init(struct pcmcia_socket *skt)
0157 {
0158     gpio_direction_input(GPIO_CDA);
0159     gpio_direction_input(GPIO_CDB);
0160     gpio_direction_input(GPIO_VSL);
0161     gpio_direction_input(GPIO_VSH);
0162     gpio_direction_input(GPIO_BATTDEAD);
0163     gpio_direction_input(GPIO_BATTWARN);
0164     gpio_direction_output(GPIO_RESET, 1);   /* assert reset */
0165     gpio_direction_output(GPIO_OUTEN, 1);   /* disable buffers */
0166     gpio_direction_output(GPIO_POWER, 1);   /* power off */
0167 
0168     return 0;
0169 }
0170 
0171 static int xxs1500_pcmcia_sock_suspend(struct pcmcia_socket *skt)
0172 {
0173     return 0;
0174 }
0175 
0176 static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
0177                     struct pccard_io_map *map)
0178 {
0179     struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
0180 
0181     map->start = (u32)sock->virt_io;
0182     map->stop = map->start + IO_MAP_SIZE;
0183 
0184     return 0;
0185 }
0186 
0187 static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
0188                      struct pccard_mem_map *map)
0189 {
0190     struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
0191 
0192     if (map->flags & MAP_ATTRIB)
0193         map->static_start = sock->phys_attr + map->card_start;
0194     else
0195         map->static_start = sock->phys_mem + map->card_start;
0196 
0197     return 0;
0198 }
0199 
0200 static struct pccard_operations xxs1500_pcmcia_operations = {
0201     .init           = xxs1500_pcmcia_sock_init,
0202     .suspend        = xxs1500_pcmcia_sock_suspend,
0203     .get_status     = xxs1500_pcmcia_get_status,
0204     .set_socket     = xxs1500_pcmcia_configure,
0205     .set_io_map     = au1x00_pcmcia_set_io_map,
0206     .set_mem_map        = au1x00_pcmcia_set_mem_map,
0207 };
0208 
0209 static int xxs1500_pcmcia_probe(struct platform_device *pdev)
0210 {
0211     struct xxs1500_pcmcia_sock *sock;
0212     struct resource *r;
0213     int ret, irq;
0214 
0215     sock = kzalloc(sizeof(struct xxs1500_pcmcia_sock), GFP_KERNEL);
0216     if (!sock)
0217         return -ENOMEM;
0218 
0219     ret = -ENODEV;
0220 
0221     /* 36bit PCMCIA Attribute area address */
0222     r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
0223     if (!r) {
0224         dev_err(&pdev->dev, "missing 'pcmcia-attr' resource!\n");
0225         goto out0;
0226     }
0227     sock->phys_attr = r->start;
0228 
0229     /* 36bit PCMCIA Memory area address */
0230     r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
0231     if (!r) {
0232         dev_err(&pdev->dev, "missing 'pcmcia-mem' resource!\n");
0233         goto out0;
0234     }
0235     sock->phys_mem = r->start;
0236 
0237     /* 36bit PCMCIA IO area address */
0238     r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
0239     if (!r) {
0240         dev_err(&pdev->dev, "missing 'pcmcia-io' resource!\n");
0241         goto out0;
0242     }
0243     sock->phys_io = r->start;
0244 
0245 
0246     /*
0247      * PCMCIA client drivers use the inb/outb macros to access
0248      * the IO registers.  Since mips_io_port_base is added
0249      * to the access address of the mips implementation of
0250      * inb/outb, we need to subtract it here because we want
0251      * to access the I/O or MEM address directly, without
0252      * going through this "mips_io_port_base" mechanism.
0253      */
0254     sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
0255                  mips_io_port_base);
0256 
0257     if (!sock->virt_io) {
0258         dev_err(&pdev->dev, "cannot remap IO area\n");
0259         ret = -ENOMEM;
0260         goto out0;
0261     }
0262 
0263     sock->socket.ops    = &xxs1500_pcmcia_operations;
0264     sock->socket.owner  = THIS_MODULE;
0265     sock->socket.pci_irq    = gpio_to_irq(GPIO_CARDIRQ);
0266     sock->socket.features   = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
0267     sock->socket.map_size   = MEM_MAP_SIZE;
0268     sock->socket.io_offset  = (unsigned long)sock->virt_io;
0269     sock->socket.dev.parent = &pdev->dev;
0270     sock->socket.resource_ops = &pccard_static_ops;
0271 
0272     platform_set_drvdata(pdev, sock);
0273 
0274     /* setup carddetect irq: use one of the 2 GPIOs as an
0275      * edge detector.
0276      */
0277     irq = gpio_to_irq(GPIO_CDA);
0278     irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
0279     ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
0280     if (ret) {
0281         dev_err(&pdev->dev, "cannot setup cd irq\n");
0282         goto out1;
0283     }
0284 
0285     ret = pcmcia_register_socket(&sock->socket);
0286     if (ret) {
0287         dev_err(&pdev->dev, "failed to register\n");
0288         goto out2;
0289     }
0290 
0291     printk(KERN_INFO "MyCable XXS1500 PCMCIA socket services\n");
0292 
0293     return 0;
0294 
0295 out2:
0296     free_irq(gpio_to_irq(GPIO_CDA), sock);
0297 out1:
0298     iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
0299 out0:
0300     kfree(sock);
0301     return ret;
0302 }
0303 
0304 static int xxs1500_pcmcia_remove(struct platform_device *pdev)
0305 {
0306     struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
0307 
0308     pcmcia_unregister_socket(&sock->socket);
0309     free_irq(gpio_to_irq(GPIO_CDA), sock);
0310     iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
0311     kfree(sock);
0312 
0313     return 0;
0314 }
0315 
0316 static struct platform_driver xxs1500_pcmcia_socket_driver = {
0317     .driver = {
0318         .name   = "xxs1500_pcmcia",
0319     },
0320     .probe      = xxs1500_pcmcia_probe,
0321     .remove     = xxs1500_pcmcia_remove,
0322 };
0323 
0324 module_platform_driver(xxs1500_pcmcia_socket_driver);
0325 
0326 MODULE_LICENSE("GPL");
0327 MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems");
0328 MODULE_AUTHOR("Manuel Lauss");