Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/pcmcia/pxa2xx_balloon3.c
0004  *
0005  * Balloon3 PCMCIA specific routines.
0006  *
0007  *  Author: Nick Bane
0008  *  Created:    June, 2006
0009  *  Copyright:  Toby Churchill Ltd
0010  *  Derived from pxa2xx_mainstone.c, by Nico Pitre
0011  *
0012  * Various modification by Marek Vasut <marek.vasut@gmail.com>
0013  */
0014 
0015 #include <linux/module.h>
0016 #include <linux/gpio.h>
0017 #include <linux/errno.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/irq.h>
0021 #include <linux/io.h>
0022 
0023 #include "balloon3.h"
0024 
0025 #include <asm/mach-types.h>
0026 
0027 #include <pcmcia/soc_common.h>
0028 
0029 static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
0030 {
0031     uint16_t ver;
0032 
0033     ver = __raw_readw(BALLOON3_FPGA_VER);
0034     if (ver < 0x4f08)
0035         pr_warn("The FPGA code, version 0x%04x, is too old. "
0036             "PCMCIA/CF support might be broken in this version!",
0037             ver);
0038 
0039     skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ;
0040     skt->stat[SOC_STAT_CD].gpio = BALLOON3_GPIO_S0_CD;
0041     skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD";
0042     skt->stat[SOC_STAT_BVD1].irq = BALLOON3_BP_NSTSCHG_IRQ;
0043     skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG";
0044 
0045     return 0;
0046 }
0047 
0048 static unsigned long balloon3_pcmcia_status[2] = {
0049     BALLOON3_CF_nSTSCHG_BVD1,
0050     BALLOON3_CF_nSTSCHG_BVD1
0051 };
0052 
0053 static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
0054                     struct pcmcia_state *state)
0055 {
0056     uint16_t status;
0057     int flip;
0058 
0059     /* This actually reads the STATUS register */
0060     status = __raw_readw(BALLOON3_CF_STATUS_REG);
0061     flip = (status ^ balloon3_pcmcia_status[skt->nr])
0062         & BALLOON3_CF_nSTSCHG_BVD1;
0063     /*
0064      * Workaround for STSCHG which can't be deasserted:
0065      * We therefore disable/enable corresponding IRQs
0066      * as needed to avoid IRQ locks.
0067      */
0068     if (flip) {
0069         balloon3_pcmcia_status[skt->nr] = status;
0070         if (status & BALLOON3_CF_nSTSCHG_BVD1)
0071             enable_irq(BALLOON3_BP_NSTSCHG_IRQ);
0072         else
0073             disable_irq(BALLOON3_BP_NSTSCHG_IRQ);
0074     }
0075 
0076     state->ready    = !!(status & BALLOON3_CF_nIRQ);
0077     state->bvd1 = !!(status & BALLOON3_CF_nSTSCHG_BVD1);
0078     state->bvd2 = 0;    /* not available */
0079     state->vs_3v    = 1;    /* Always true its a CF card */
0080     state->vs_Xv    = 0;    /* not available */
0081 }
0082 
0083 static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
0084                        const socket_state_t *state)
0085 {
0086     __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG +
0087             ((state->flags & SS_RESET) ?
0088             BALLOON3_FPGA_SETnCLR : 0));
0089     return 0;
0090 }
0091 
0092 static struct pcmcia_low_level balloon3_pcmcia_ops = {
0093     .owner          = THIS_MODULE,
0094     .hw_init        = balloon3_pcmcia_hw_init,
0095     .socket_state       = balloon3_pcmcia_socket_state,
0096     .configure_socket   = balloon3_pcmcia_configure_socket,
0097     .first          = 0,
0098     .nr         = 1,
0099 };
0100 
0101 static struct platform_device *balloon3_pcmcia_device;
0102 
0103 static int __init balloon3_pcmcia_init(void)
0104 {
0105     int ret;
0106 
0107     if (!machine_is_balloon3())
0108         return -ENODEV;
0109 
0110     balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
0111     if (!balloon3_pcmcia_device)
0112         return -ENOMEM;
0113 
0114     ret = platform_device_add_data(balloon3_pcmcia_device,
0115             &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops));
0116 
0117     if (!ret)
0118         ret = platform_device_add(balloon3_pcmcia_device);
0119 
0120     if (ret)
0121         platform_device_put(balloon3_pcmcia_device);
0122 
0123     return ret;
0124 }
0125 
0126 static void __exit balloon3_pcmcia_exit(void)
0127 {
0128     platform_device_unregister(balloon3_pcmcia_device);
0129 }
0130 
0131 module_init(balloon3_pcmcia_init);
0132 module_exit(balloon3_pcmcia_exit);
0133 
0134 MODULE_LICENSE("GPL");
0135 MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>");
0136 MODULE_ALIAS("platform:pxa2xx-pcmcia");
0137 MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver");