1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2007 PA Semi, Inc 4 * 5 * Maintained by: Olof Johansson <olof@lixom.net> 6 * 7 * Based on drivers/pcmcia/omap_cf.c 8 */ 9 10 #include <linux/module.h> 11 #include <linux/kernel.h> 12 #include <linux/sched.h> 13 #include <linux/platform_device.h> 14 #include <linux/errno.h> 15 #include <linux/init.h> 16 #include <linux/delay.h> 17 #include <linux/interrupt.h> 18 #include <linux/mm.h> 19 #include <linux/vmalloc.h> 20 #include <linux/of_address.h> 21 #include <linux/of_irq.h> 22 #include <linux/of_platform.h> 23 #include <linux/slab.h> 24 25 #include <pcmcia/ss.h> 26 27 static const char driver_name[] = "electra-cf"; 28 29 struct electra_cf_socket { 30 struct pcmcia_socket socket; 31 32 struct timer_list timer; 33 unsigned present:1; 34 unsigned active:1; 35 36 struct platform_device *ofdev; 37 unsigned long mem_phys; 38 void __iomem *mem_base; 39 unsigned long mem_size; 40 void __iomem *io_virt; 41 unsigned int io_base; 42 unsigned int io_size; 43 u_int irq; 44 struct resource iomem; 45 void __iomem *gpio_base; 46 int gpio_detect; 47 int gpio_vsense; 48 int gpio_3v; 49 int gpio_5v; 50 }; 51 52 #define POLL_INTERVAL (2 * HZ) 53 54 55 static int electra_cf_present(struct electra_cf_socket *cf) 56 { 57 unsigned int gpio; 58 59 gpio = in_le32(cf->gpio_base+0x40); 60 return !(gpio & (1 << cf->gpio_detect)); 61 } 62 63 static int electra_cf_ss_init(struct pcmcia_socket *s) 64 { 65 return 0; 66 } 67 68 /* the timer is primarily to kick this socket's pccardd */ 69 static void electra_cf_timer(struct timer_list *t) 70 { 71 struct electra_cf_socket *cf = from_timer(cf, t, timer); 72 int present = electra_cf_present(cf); 73 74 if (present != cf->present) { 75 cf->present = present; 76 pcmcia_parse_events(&cf->socket, SS_DETECT); 77 } 78 79 if (cf->active) 80 mod_timer(&cf->timer, jiffies + POLL_INTERVAL); 81 } 82 83 static irqreturn_t electra_cf_irq(int irq, void *_cf) 84 { 85 struct electra_cf_socket *cf = _cf; 86 87 electra_cf_timer(&cf->timer); 88 return IRQ_HANDLED; 89 } 90 91 static int electra_cf_get_status(struct pcmcia_socket *s, u_int *sp) 92 { 93 struct electra_cf_socket *cf; 94 95 if (!sp) 96 return -EINVAL; 97 98 cf = container_of(s, struct electra_cf_socket, socket); 99 100 /* NOTE CF is always 3VCARD */ 101 if (electra_cf_present(cf)) { 102 *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; 103 104 s->pci_irq = cf->irq; 105 } else 106 *sp = 0; 107 return 0; 108 } 109 110 static int electra_cf_set_socket(struct pcmcia_socket *sock, 111 struct socket_state_t *s) 112 { 113 unsigned int gpio; 114 unsigned int vcc; 115 struct electra_cf_socket *cf; 116 117 cf = container_of(sock, struct electra_cf_socket, socket); 118 119 /* "reset" means no power in our case */ 120 vcc = (s->flags & SS_RESET) ? 0 : s->Vcc; 121 122 switch (vcc) { 123 case 0: 124 gpio = 0; 125 break; 126 case 33: 127 gpio = (1 << cf->gpio_3v); 128 break; 129 case 5: 130 gpio = (1 << cf->gpio_5v); 131 break; 132 default: 133 return -EINVAL; 134 } 135 136 gpio |= 1 << (cf->gpio_3v + 16); /* enwr */ 137 gpio |= 1 << (cf->gpio_5v + 16); /* enwr */ 138 out_le32(cf->gpio_base+0x90, gpio); 139 140 pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", 141 driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); 142 143 return 0; 144 } 145 146 static int electra_cf_set_io_map(struct pcmcia_socket *s, 147 struct pccard_io_map *io) 148 { 149 return 0; 150 } 151 152 static int electra_cf_set_mem_map(struct pcmcia_socket *s, 153 struct pccard_mem_map *map) 154 { 155 struct electra_cf_socket *cf; 156 157 if (map->card_start) 158 return -EINVAL; 159 cf = container_of(s, struct electra_cf_socket, socket); 160 map->static_start = cf->mem_phys; 161 map->flags &= MAP_ACTIVE|MAP_ATTRIB; 162 if (!(map->flags & MAP_ATTRIB)) 163 map->static_start += 0x800; 164 return 0; 165 } 166 167 static struct pccard_operations electra_cf_ops = { 168 .init = electra_cf_ss_init, 169 .get_status = electra_cf_get_status, 170 .set_socket = electra_cf_set_socket, 171 .set_io_map = electra_cf_set_io_map, 172 .set_mem_map = electra_cf_set_mem_map, 173 }; 174 175 static int electra_cf_probe(struct platform_device *ofdev) 176 { 177 struct device *device = &ofdev->dev; 178 struct device_node *np = ofdev->dev.of_node; 179 struct electra_cf_socket *cf; 180 struct resource mem, io; 181 int status = -ENOMEM; 182 const unsigned int *prop; 183 int err; 184 185 err = of_address_to_resource(np, 0, &mem); 186 if (err) 187 return -EINVAL; 188 189 err = of_address_to_resource(np, 1, &io); 190 if (err) 191 return -EINVAL; 192 193 cf = kzalloc(sizeof(*cf), GFP_KERNEL); 194 if (!cf) 195 return -ENOMEM; 196 197 timer_setup(&cf->timer, electra_cf_timer, 0); 198 cf->irq = 0; 199 200 cf->ofdev = ofdev; 201 cf->mem_phys = mem.start; 202 cf->mem_size = PAGE_ALIGN(resource_size(&mem)); 203 cf->mem_base = ioremap(cf->mem_phys, cf->mem_size); 204 if (!cf->mem_base) 205 goto out_free_cf; 206 cf->io_size = PAGE_ALIGN(resource_size(&io)); 207 cf->io_virt = ioremap_phb(io.start, cf->io_size); 208 if (!cf->io_virt) 209 goto out_unmap_mem; 210 211 cf->gpio_base = ioremap(0xfc103000, 0x1000); 212 if (!cf->gpio_base) 213 goto out_unmap_virt; 214 dev_set_drvdata(device, cf); 215 216 cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END; 217 cf->iomem.start = (unsigned long)cf->mem_base; 218 cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start); 219 cf->iomem.flags = IORESOURCE_MEM; 220 221 cf->irq = irq_of_parse_and_map(np, 0); 222 223 status = request_irq(cf->irq, electra_cf_irq, IRQF_SHARED, 224 driver_name, cf); 225 if (status < 0) { 226 dev_err(device, "request_irq failed\n"); 227 goto fail1; 228 } 229 230 cf->socket.pci_irq = cf->irq; 231 232 prop = of_get_property(np, "card-detect-gpio", NULL); 233 if (!prop) 234 goto fail1; 235 cf->gpio_detect = *prop; 236 237 prop = of_get_property(np, "card-vsense-gpio", NULL); 238 if (!prop) 239 goto fail1; 240 cf->gpio_vsense = *prop; 241 242 prop = of_get_property(np, "card-3v-gpio", NULL); 243 if (!prop) 244 goto fail1; 245 cf->gpio_3v = *prop; 246 247 prop = of_get_property(np, "card-5v-gpio", NULL); 248 if (!prop) 249 goto fail1; 250 cf->gpio_5v = *prop; 251 252 cf->socket.io_offset = cf->io_base; 253 254 /* reserve chip-select regions */ 255 if (!request_mem_region(cf->mem_phys, cf->mem_size, driver_name)) { 256 status = -ENXIO; 257 dev_err(device, "Can't claim memory region\n"); 258 goto fail1; 259 } 260 261 if (!request_region(cf->io_base, cf->io_size, driver_name)) { 262 status = -ENXIO; 263 dev_err(device, "Can't claim I/O region\n"); 264 goto fail2; 265 } 266 267 cf->socket.owner = THIS_MODULE; 268 cf->socket.dev.parent = &ofdev->dev; 269 cf->socket.ops = &electra_cf_ops; 270 cf->socket.resource_ops = &pccard_static_ops; 271 cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | 272 SS_CAP_MEM_ALIGN; 273 cf->socket.map_size = 0x800; 274 275 status = pcmcia_register_socket(&cf->socket); 276 if (status < 0) { 277 dev_err(device, "pcmcia_register_socket failed\n"); 278 goto fail3; 279 } 280 281 dev_info(device, "at mem 0x%lx io 0x%llx irq %d\n", 282 cf->mem_phys, io.start, cf->irq); 283 284 cf->active = 1; 285 electra_cf_timer(&cf->timer); 286 return 0; 287 288 fail3: 289 release_region(cf->io_base, cf->io_size); 290 fail2: 291 release_mem_region(cf->mem_phys, cf->mem_size); 292 fail1: 293 if (cf->irq) 294 free_irq(cf->irq, cf); 295 296 iounmap(cf->gpio_base); 297 out_unmap_virt: 298 device_init_wakeup(&ofdev->dev, 0); 299 iounmap(cf->io_virt); 300 out_unmap_mem: 301 iounmap(cf->mem_base); 302 out_free_cf: 303 kfree(cf); 304 return status; 305 306 } 307 308 static int electra_cf_remove(struct platform_device *ofdev) 309 { 310 struct device *device = &ofdev->dev; 311 struct electra_cf_socket *cf; 312 313 cf = dev_get_drvdata(device); 314 315 cf->active = 0; 316 pcmcia_unregister_socket(&cf->socket); 317 free_irq(cf->irq, cf); 318 del_timer_sync(&cf->timer); 319 320 iounmap(cf->io_virt); 321 iounmap(cf->mem_base); 322 iounmap(cf->gpio_base); 323 release_mem_region(cf->mem_phys, cf->mem_size); 324 release_region(cf->io_base, cf->io_size); 325 326 kfree(cf); 327 328 return 0; 329 } 330 331 static const struct of_device_id electra_cf_match[] = { 332 { 333 .compatible = "electra-cf", 334 }, 335 {}, 336 }; 337 MODULE_DEVICE_TABLE(of, electra_cf_match); 338 339 static struct platform_driver electra_cf_driver = { 340 .driver = { 341 .name = driver_name, 342 .of_match_table = electra_cf_match, 343 }, 344 .probe = electra_cf_probe, 345 .remove = electra_cf_remove, 346 }; 347 348 module_platform_driver(electra_cf_driver); 349 350 MODULE_LICENSE("GPL"); 351 MODULE_AUTHOR("Olof Johansson <olof@lixom.net>"); 352 MODULE_DESCRIPTION("PA Semi Electra CF driver"); 353