1/* 2 * linux/drivers/pcmcia/pxa2xx_balloon3.c 3 * 4 * Balloon3 PCMCIA specific routines. 5 * 6 * Author: Nick Bane 7 * Created: June, 2006 8 * Copyright: Toby Churchill Ltd 9 * Derived from pxa2xx_mainstone.c, by Nico Pitre 10 * 11 * Various modification by Marek Vasut <marek.vasut@gmail.com> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License version 2 as 15 * published by the Free Software Foundation. 16 */ 17 18#include <linux/module.h> 19#include <linux/gpio.h> 20#include <linux/errno.h> 21#include <linux/interrupt.h> 22#include <linux/platform_device.h> 23#include <linux/irq.h> 24#include <linux/io.h> 25 26#include <mach/balloon3.h> 27 28#include "soc_common.h" 29 30/* 31 * These are a list of interrupt sources that provokes a polled 32 * check of status 33 */ 34static struct pcmcia_irqs irqs[] = { 35 { 0, BALLOON3_S0_CD_IRQ, "PCMCIA0 CD" }, 36 { 0, BALLOON3_BP_NSTSCHG_IRQ, "PCMCIA0 STSCHG" }, 37}; 38 39static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 40{ 41 uint16_t ver; 42 int ret; 43 static void __iomem *fpga_ver; 44 45 ver = __raw_readw(BALLOON3_FPGA_VER); 46 if (ver > 0x0201) 47 pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. " 48 "PCMCIA/CF support might be broken in this version!", 49 ver); 50 51 skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ; 52 return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); 53} 54 55static void balloon3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 56{ 57 soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); 58} 59 60static unsigned long balloon3_pcmcia_status[2] = { 61 BALLOON3_CF_nSTSCHG_BVD1, 62 BALLOON3_CF_nSTSCHG_BVD1 63}; 64 65static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 66 struct pcmcia_state *state) 67{ 68 uint16_t status; 69 int flip; 70 71 /* This actually reads the STATUS register */ 72 status = __raw_readw(BALLOON3_CF_STATUS_REG); 73 flip = (status ^ balloon3_pcmcia_status[skt->nr]) 74 & BALLOON3_CF_nSTSCHG_BVD1; 75 if (flip) { 76 balloon3_pcmcia_status[skt->nr] = status; 77 if (status & BALLOON3_CF_nSTSCHG_BVD1) 78 enable_irq(BALLOON3_BP_NSTSCHG_IRQ); 79 else 80 disable_irq(BALLOON3_BP_NSTSCHG_IRQ); 81 } 82 83 state->detect = !gpio_get_value(BALLOON3_GPIO_S0_CD); 84 state->ready = !!(status & BALLOON3_CF_nIRQ); 85 state->bvd1 = !!(status & BALLOON3_CF_nSTSCHG_BVD1); 86 state->bvd2 = 0; /* not available */ 87 state->vs_3v = 1; /* Always true its a CF card */ 88 state->vs_Xv = 0; /* not available */ 89 state->wrprot = 0; /* not available */ 90} 91 92static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 93 const socket_state_t *state) 94{ 95 __raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0, 96 BALLOON3_CF_CONTROL_REG); 97 return 0; 98} 99 100static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 101{ 102} 103 104static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 105{ 106} 107 108static struct pcmcia_low_level balloon3_pcmcia_ops = { 109 .owner = THIS_MODULE, 110 .hw_init = balloon3_pcmcia_hw_init, 111 .hw_shutdown = balloon3_pcmcia_hw_shutdown, 112 .socket_state = balloon3_pcmcia_socket_state, 113 .configure_socket = balloon3_pcmcia_configure_socket, 114 .socket_init = balloon3_pcmcia_socket_init, 115 .socket_suspend = balloon3_pcmcia_socket_suspend, 116 .first = 0, 117 .nr = 1, 118}; 119 120static struct platform_device *balloon3_pcmcia_device; 121 122static int __init balloon3_pcmcia_init(void) 123{ 124 int ret; 125 126 balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); 127 if (!balloon3_pcmcia_device) 128 return -ENOMEM; 129 130 ret = platform_device_add_data(balloon3_pcmcia_device, 131 &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops)); 132 133 if (!ret) 134 ret = platform_device_add(balloon3_pcmcia_device); 135 136 if (ret) 137 platform_device_put(balloon3_pcmcia_device); 138 139 return ret; 140} 141 142static void __exit balloon3_pcmcia_exit(void) 143{ 144 platform_device_unregister(balloon3_pcmcia_device); 145} 146 147module_init(balloon3_pcmcia_init); 148module_exit(balloon3_pcmcia_exit); 149 150MODULE_LICENSE("GPL"); 151MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>"); 152MODULE_ALIAS("platform:pxa2xx-pcmcia"); 153MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver"); 154