Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/pcmcia/pxa2xx_mainstone.c
0004  *
0005  * Mainstone PCMCIA specific routines.
0006  *
0007  * Created: May 12, 2004
0008  * Author:  Nicolas Pitre
0009  * Copyright:   MontaVista Software Inc.
0010  */
0011 #include <linux/gpio/consumer.h>
0012 #include <linux/module.h>
0013 #include <linux/init.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/kernel.h>
0016 #include <linux/errno.h>
0017 #include <linux/platform_device.h>
0018 
0019 #include <pcmcia/ss.h>
0020 
0021 #include <asm/mach-types.h>
0022 
0023 #include "soc_common.h"
0024 #include "max1600.h"
0025 
0026 static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
0027 {
0028     struct device *dev = skt->socket.dev.parent;
0029     struct max1600 *m;
0030     int ret;
0031 
0032     skt->stat[SOC_STAT_CD].name = skt->nr ? "bdetect" : "adetect";
0033     skt->stat[SOC_STAT_BVD1].name = skt->nr ? "bbvd1" : "abvd1";
0034     skt->stat[SOC_STAT_BVD2].name = skt->nr ? "bbvd2" : "abvd2";
0035     skt->stat[SOC_STAT_RDY].name = skt->nr ? "bready" : "aready";
0036     skt->stat[SOC_STAT_VS1].name = skt->nr ? "bvs1" : "avs1";
0037     skt->stat[SOC_STAT_VS2].name = skt->nr ? "bvs2" : "avs2";
0038 
0039     skt->gpio_reset = devm_gpiod_get(dev, skt->nr ? "breset" : "areset",
0040                      GPIOD_OUT_HIGH);
0041     if (IS_ERR(skt->gpio_reset))
0042         return PTR_ERR(skt->gpio_reset);
0043 
0044     ret = max1600_init(dev, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A,
0045                MAX1600_CODE_HIGH);
0046     if (ret)
0047         return ret;
0048 
0049     skt->driver_data = m;
0050 
0051     return soc_pcmcia_request_gpiods(skt);
0052 }
0053 
0054 static unsigned int mst_pcmcia_bvd1_status[2];
0055 
0056 static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
0057                     struct pcmcia_state *state)
0058 {
0059     unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1;
0060 
0061     /*
0062      * Workaround for STSCHG which can't be deasserted:
0063      * We therefore disable/enable corresponding IRQs
0064      * as needed to avoid IRQ locks.
0065      */
0066     if (flip) {
0067         mst_pcmcia_bvd1_status[skt->nr] = state->bvd1;
0068         if (state->bvd1)
0069             enable_irq(skt->stat[SOC_STAT_BVD1].irq);
0070         else
0071             disable_irq(skt->stat[SOC_STAT_BVD2].irq);
0072     }
0073 }
0074 
0075 static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
0076                        const socket_state_t *state)
0077 {
0078     return max1600_configure(skt->driver_data, state->Vcc, state->Vpp);
0079 }
0080 
0081 static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
0082     .owner          = THIS_MODULE,
0083     .hw_init        = mst_pcmcia_hw_init,
0084     .socket_state       = mst_pcmcia_socket_state,
0085     .configure_socket   = mst_pcmcia_configure_socket,
0086     .nr         = 2,
0087 };
0088 
0089 static struct platform_device *mst_pcmcia_device;
0090 
0091 static int __init mst_pcmcia_init(void)
0092 {
0093     int ret;
0094 
0095     if (!machine_is_mainstone())
0096         return -ENODEV;
0097 
0098     mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
0099     if (!mst_pcmcia_device)
0100         return -ENOMEM;
0101 
0102     ret = platform_device_add_data(mst_pcmcia_device, &mst_pcmcia_ops,
0103                        sizeof(mst_pcmcia_ops));
0104     if (ret == 0)
0105         ret = platform_device_add(mst_pcmcia_device);
0106 
0107     if (ret)
0108         platform_device_put(mst_pcmcia_device);
0109 
0110     return ret;
0111 }
0112 
0113 static void __exit mst_pcmcia_exit(void)
0114 {
0115     platform_device_unregister(mst_pcmcia_device);
0116 }
0117 
0118 fs_initcall(mst_pcmcia_init);
0119 module_exit(mst_pcmcia_exit);
0120 
0121 MODULE_LICENSE("GPL");
0122 MODULE_ALIAS("platform:pxa2xx-pcmcia");