bcm63xx_pcmcia.c (13603B)
1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 7 */ 8 9#include <linux/kernel.h> 10#include <linux/module.h> 11#include <linux/ioport.h> 12#include <linux/timer.h> 13#include <linux/platform_device.h> 14#include <linux/slab.h> 15#include <linux/delay.h> 16#include <linux/pci.h> 17#include <linux/gpio.h> 18 19#include <bcm63xx_regs.h> 20#include <bcm63xx_io.h> 21#include "bcm63xx_pcmcia.h" 22 23#define PFX "bcm63xx_pcmcia: " 24 25#ifdef CONFIG_CARDBUS 26/* if cardbus is used, platform device needs reference to actual pci 27 * device */ 28static struct pci_dev *bcm63xx_cb_dev; 29#endif 30 31/* 32 * read/write helper for pcmcia regs 33 */ 34static inline u32 pcmcia_readl(struct bcm63xx_pcmcia_socket *skt, u32 off) 35{ 36 return bcm_readl(skt->base + off); 37} 38 39static inline void pcmcia_writel(struct bcm63xx_pcmcia_socket *skt, 40 u32 val, u32 off) 41{ 42 bcm_writel(val, skt->base + off); 43} 44 45/* 46 * This callback should (re-)initialise the socket, turn on status 47 * interrupts and PCMCIA bus, and wait for power to stabilise so that 48 * the card status signals report correctly. 49 * 50 * Hardware cannot do that. 51 */ 52static int bcm63xx_pcmcia_sock_init(struct pcmcia_socket *sock) 53{ 54 return 0; 55} 56 57/* 58 * This callback should remove power on the socket, disable IRQs from 59 * the card, turn off status interrupts, and disable the PCMCIA bus. 60 * 61 * Hardware cannot do that. 62 */ 63static int bcm63xx_pcmcia_suspend(struct pcmcia_socket *sock) 64{ 65 return 0; 66} 67 68/* 69 * Implements the set_socket() operation for the in-kernel PCMCIA 70 * service (formerly SS_SetSocket in Card Services). We more or 71 * less punt all of this work and let the kernel handle the details 72 * of power configuration, reset, &c. We also record the value of 73 * `state' in order to regurgitate it to the PCMCIA core later. 74 */ 75static int bcm63xx_pcmcia_set_socket(struct pcmcia_socket *sock, 76 socket_state_t *state) 77{ 78 struct bcm63xx_pcmcia_socket *skt; 79 unsigned long flags; 80 u32 val; 81 82 skt = sock->driver_data; 83 84 spin_lock_irqsave(&skt->lock, flags); 85 86 /* note: hardware cannot control socket power, so we will 87 * always report SS_POWERON */ 88 89 /* apply socket reset */ 90 val = pcmcia_readl(skt, PCMCIA_C1_REG); 91 if (state->flags & SS_RESET) 92 val |= PCMCIA_C1_RESET_MASK; 93 else 94 val &= ~PCMCIA_C1_RESET_MASK; 95 96 /* reverse reset logic for cardbus card */ 97 if (skt->card_detected && (skt->card_type & CARD_CARDBUS)) 98 val ^= PCMCIA_C1_RESET_MASK; 99 100 pcmcia_writel(skt, val, PCMCIA_C1_REG); 101 102 /* keep requested state for event reporting */ 103 skt->requested_state = *state; 104 105 spin_unlock_irqrestore(&skt->lock, flags); 106 107 return 0; 108} 109 110/* 111 * identity cardtype from VS[12] input, CD[12] input while only VS2 is 112 * floating, and CD[12] input while only VS1 is floating 113 */ 114enum { 115 IN_VS1 = (1 << 0), 116 IN_VS2 = (1 << 1), 117 IN_CD1_VS2H = (1 << 2), 118 IN_CD2_VS2H = (1 << 3), 119 IN_CD1_VS1H = (1 << 4), 120 IN_CD2_VS1H = (1 << 5), 121}; 122 123static const u8 vscd_to_cardtype[] = { 124 125 /* VS1 float, VS2 float */ 126 [IN_VS1 | IN_VS2] = (CARD_PCCARD | CARD_5V), 127 128 /* VS1 grounded, VS2 float */ 129 [IN_VS2] = (CARD_PCCARD | CARD_5V | CARD_3V), 130 131 /* VS1 grounded, VS2 grounded */ 132 [0] = (CARD_PCCARD | CARD_5V | CARD_3V | CARD_XV), 133 134 /* VS1 tied to CD1, VS2 float */ 135 [IN_VS1 | IN_VS2 | IN_CD1_VS1H] = (CARD_CARDBUS | CARD_3V), 136 137 /* VS1 grounded, VS2 tied to CD2 */ 138 [IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V | CARD_XV), 139 140 /* VS1 tied to CD2, VS2 grounded */ 141 [IN_VS1 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_3V | CARD_XV | CARD_YV), 142 143 /* VS1 float, VS2 grounded */ 144 [IN_VS1] = (CARD_PCCARD | CARD_XV), 145 146 /* VS1 float, VS2 tied to CD2 */ 147 [IN_VS1 | IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V), 148 149 /* VS1 float, VS2 tied to CD1 */ 150 [IN_VS1 | IN_VS2 | IN_CD1_VS2H] = (CARD_CARDBUS | CARD_XV | CARD_YV), 151 152 /* VS1 tied to CD2, VS2 float */ 153 [IN_VS1 | IN_VS2 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_YV), 154 155 /* VS2 grounded, VS1 is tied to CD1, CD2 is grounded */ 156 [IN_VS1 | IN_CD1_VS1H] = 0, /* ignore cardbay */ 157}; 158 159/* 160 * poll hardware to check card insertion status 161 */ 162static unsigned int __get_socket_status(struct bcm63xx_pcmcia_socket *skt) 163{ 164 unsigned int stat; 165 u32 val; 166 167 stat = 0; 168 169 /* check CD for card presence */ 170 val = pcmcia_readl(skt, PCMCIA_C1_REG); 171 172 if (!(val & PCMCIA_C1_CD1_MASK) && !(val & PCMCIA_C1_CD2_MASK)) 173 stat |= SS_DETECT; 174 175 /* if new insertion, detect cardtype */ 176 if ((stat & SS_DETECT) && !skt->card_detected) { 177 unsigned int stat = 0; 178 179 /* float VS1, float VS2 */ 180 val |= PCMCIA_C1_VS1OE_MASK; 181 val |= PCMCIA_C1_VS2OE_MASK; 182 pcmcia_writel(skt, val, PCMCIA_C1_REG); 183 184 /* wait for output to stabilize and read VS[12] */ 185 udelay(10); 186 val = pcmcia_readl(skt, PCMCIA_C1_REG); 187 stat |= (val & PCMCIA_C1_VS1_MASK) ? IN_VS1 : 0; 188 stat |= (val & PCMCIA_C1_VS2_MASK) ? IN_VS2 : 0; 189 190 /* drive VS1 low, float VS2 */ 191 val &= ~PCMCIA_C1_VS1OE_MASK; 192 val |= PCMCIA_C1_VS2OE_MASK; 193 pcmcia_writel(skt, val, PCMCIA_C1_REG); 194 195 /* wait for output to stabilize and read CD[12] */ 196 udelay(10); 197 val = pcmcia_readl(skt, PCMCIA_C1_REG); 198 stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS2H : 0; 199 stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS2H : 0; 200 201 /* float VS1, drive VS2 low */ 202 val |= PCMCIA_C1_VS1OE_MASK; 203 val &= ~PCMCIA_C1_VS2OE_MASK; 204 pcmcia_writel(skt, val, PCMCIA_C1_REG); 205 206 /* wait for output to stabilize and read CD[12] */ 207 udelay(10); 208 val = pcmcia_readl(skt, PCMCIA_C1_REG); 209 stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS1H : 0; 210 stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS1H : 0; 211 212 /* guess cardtype from all this */ 213 skt->card_type = vscd_to_cardtype[stat]; 214 if (!skt->card_type) 215 dev_err(&skt->socket.dev, "unsupported card type\n"); 216 217 /* drive both VS pin to 0 again */ 218 val &= ~(PCMCIA_C1_VS1OE_MASK | PCMCIA_C1_VS2OE_MASK); 219 220 /* enable correct logic */ 221 val &= ~(PCMCIA_C1_EN_PCMCIA_MASK | PCMCIA_C1_EN_CARDBUS_MASK); 222 if (skt->card_type & CARD_PCCARD) 223 val |= PCMCIA_C1_EN_PCMCIA_MASK; 224 else 225 val |= PCMCIA_C1_EN_CARDBUS_MASK; 226 227 pcmcia_writel(skt, val, PCMCIA_C1_REG); 228 } 229 skt->card_detected = (stat & SS_DETECT) ? 1 : 0; 230 231 /* report card type/voltage */ 232 if (skt->card_type & CARD_CARDBUS) 233 stat |= SS_CARDBUS; 234 if (skt->card_type & CARD_3V) 235 stat |= SS_3VCARD; 236 if (skt->card_type & CARD_XV) 237 stat |= SS_XVCARD; 238 stat |= SS_POWERON; 239 240 if (gpio_get_value(skt->pd->ready_gpio)) 241 stat |= SS_READY; 242 243 return stat; 244} 245 246/* 247 * core request to get current socket status 248 */ 249static int bcm63xx_pcmcia_get_status(struct pcmcia_socket *sock, 250 unsigned int *status) 251{ 252 struct bcm63xx_pcmcia_socket *skt; 253 254 skt = sock->driver_data; 255 256 spin_lock_bh(&skt->lock); 257 *status = __get_socket_status(skt); 258 spin_unlock_bh(&skt->lock); 259 260 return 0; 261} 262 263/* 264 * socket polling timer callback 265 */ 266static void bcm63xx_pcmcia_poll(struct timer_list *t) 267{ 268 struct bcm63xx_pcmcia_socket *skt; 269 unsigned int stat, events; 270 271 skt = from_timer(skt, t, timer); 272 273 spin_lock_bh(&skt->lock); 274 275 stat = __get_socket_status(skt); 276 277 /* keep only changed bits, and mask with required one from the 278 * core */ 279 events = (stat ^ skt->old_status) & skt->requested_state.csc_mask; 280 skt->old_status = stat; 281 spin_unlock_bh(&skt->lock); 282 283 if (events) 284 pcmcia_parse_events(&skt->socket, events); 285 286 mod_timer(&skt->timer, 287 jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE)); 288} 289 290static int bcm63xx_pcmcia_set_io_map(struct pcmcia_socket *sock, 291 struct pccard_io_map *map) 292{ 293 /* this doesn't seem to be called by pcmcia layer if static 294 * mapping is used */ 295 return 0; 296} 297 298static int bcm63xx_pcmcia_set_mem_map(struct pcmcia_socket *sock, 299 struct pccard_mem_map *map) 300{ 301 struct bcm63xx_pcmcia_socket *skt; 302 struct resource *res; 303 304 skt = sock->driver_data; 305 if (map->flags & MAP_ATTRIB) 306 res = skt->attr_res; 307 else 308 res = skt->common_res; 309 310 map->static_start = res->start + map->card_start; 311 return 0; 312} 313 314static struct pccard_operations bcm63xx_pcmcia_operations = { 315 .init = bcm63xx_pcmcia_sock_init, 316 .suspend = bcm63xx_pcmcia_suspend, 317 .get_status = bcm63xx_pcmcia_get_status, 318 .set_socket = bcm63xx_pcmcia_set_socket, 319 .set_io_map = bcm63xx_pcmcia_set_io_map, 320 .set_mem_map = bcm63xx_pcmcia_set_mem_map, 321}; 322 323/* 324 * register pcmcia socket to core 325 */ 326static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev) 327{ 328 struct bcm63xx_pcmcia_socket *skt; 329 struct pcmcia_socket *sock; 330 struct resource *res; 331 unsigned int regmem_size = 0, iomem_size = 0; 332 u32 val; 333 int ret; 334 int irq; 335 336 skt = kzalloc(sizeof(*skt), GFP_KERNEL); 337 if (!skt) 338 return -ENOMEM; 339 spin_lock_init(&skt->lock); 340 sock = &skt->socket; 341 sock->driver_data = skt; 342 343 /* make sure we have all resources we need */ 344 skt->common_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 345 skt->attr_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); 346 irq = platform_get_irq(pdev, 0); 347 skt->pd = pdev->dev.platform_data; 348 if (!skt->common_res || !skt->attr_res || (irq < 0) || !skt->pd) { 349 ret = -EINVAL; 350 goto err; 351 } 352 353 /* remap pcmcia registers */ 354 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 355 regmem_size = resource_size(res); 356 if (!request_mem_region(res->start, regmem_size, "bcm63xx_pcmcia")) { 357 ret = -EINVAL; 358 goto err; 359 } 360 skt->reg_res = res; 361 362 skt->base = ioremap(res->start, regmem_size); 363 if (!skt->base) { 364 ret = -ENOMEM; 365 goto err; 366 } 367 368 /* remap io registers */ 369 res = platform_get_resource(pdev, IORESOURCE_MEM, 3); 370 iomem_size = resource_size(res); 371 skt->io_base = ioremap(res->start, iomem_size); 372 if (!skt->io_base) { 373 ret = -ENOMEM; 374 goto err; 375 } 376 377 /* resources are static */ 378 sock->resource_ops = &pccard_static_ops; 379 sock->ops = &bcm63xx_pcmcia_operations; 380 sock->owner = THIS_MODULE; 381 sock->dev.parent = &pdev->dev; 382 sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD; 383 sock->io_offset = (unsigned long)skt->io_base; 384 sock->pci_irq = irq; 385 386#ifdef CONFIG_CARDBUS 387 sock->cb_dev = bcm63xx_cb_dev; 388 if (bcm63xx_cb_dev) 389 sock->features |= SS_CAP_CARDBUS; 390#endif 391 392 /* assume common & attribute memory have the same size */ 393 sock->map_size = resource_size(skt->common_res); 394 395 /* initialize polling timer */ 396 timer_setup(&skt->timer, bcm63xx_pcmcia_poll, 0); 397 398 /* initialize pcmcia control register, drive VS[12] to 0, 399 * leave CB IDSEL to the old value since it is set by the PCI 400 * layer */ 401 val = pcmcia_readl(skt, PCMCIA_C1_REG); 402 val &= PCMCIA_C1_CBIDSEL_MASK; 403 val |= PCMCIA_C1_EN_PCMCIA_GPIO_MASK; 404 pcmcia_writel(skt, val, PCMCIA_C1_REG); 405 406 /* 407 * Hardware has only one set of timings registers, not one for 408 * each memory access type, so we configure them for the 409 * slowest one: attribute memory. 410 */ 411 val = PCMCIA_C2_DATA16_MASK; 412 val |= 10 << PCMCIA_C2_RWCOUNT_SHIFT; 413 val |= 6 << PCMCIA_C2_INACTIVE_SHIFT; 414 val |= 3 << PCMCIA_C2_SETUP_SHIFT; 415 val |= 3 << PCMCIA_C2_HOLD_SHIFT; 416 pcmcia_writel(skt, val, PCMCIA_C2_REG); 417 418 ret = pcmcia_register_socket(sock); 419 if (ret) 420 goto err; 421 422 /* start polling socket */ 423 mod_timer(&skt->timer, 424 jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE)); 425 426 platform_set_drvdata(pdev, skt); 427 return 0; 428 429err: 430 if (skt->io_base) 431 iounmap(skt->io_base); 432 if (skt->base) 433 iounmap(skt->base); 434 if (skt->reg_res) 435 release_mem_region(skt->reg_res->start, regmem_size); 436 kfree(skt); 437 return ret; 438} 439 440static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev) 441{ 442 struct bcm63xx_pcmcia_socket *skt; 443 struct resource *res; 444 445 skt = platform_get_drvdata(pdev); 446 del_timer_sync(&skt->timer); 447 iounmap(skt->base); 448 iounmap(skt->io_base); 449 res = skt->reg_res; 450 release_mem_region(res->start, resource_size(res)); 451 kfree(skt); 452 return 0; 453} 454 455struct platform_driver bcm63xx_pcmcia_driver = { 456 .probe = bcm63xx_drv_pcmcia_probe, 457 .remove = bcm63xx_drv_pcmcia_remove, 458 .driver = { 459 .name = "bcm63xx_pcmcia", 460 .owner = THIS_MODULE, 461 }, 462}; 463 464#ifdef CONFIG_CARDBUS 465static int bcm63xx_cb_probe(struct pci_dev *dev, 466 const struct pci_device_id *id) 467{ 468 /* keep pci device */ 469 bcm63xx_cb_dev = dev; 470 return platform_driver_register(&bcm63xx_pcmcia_driver); 471} 472 473static void bcm63xx_cb_exit(struct pci_dev *dev) 474{ 475 platform_driver_unregister(&bcm63xx_pcmcia_driver); 476 bcm63xx_cb_dev = NULL; 477} 478 479static const struct pci_device_id bcm63xx_cb_table[] = { 480 { 481 .vendor = PCI_VENDOR_ID_BROADCOM, 482 .device = BCM6348_CPU_ID, 483 .subvendor = PCI_VENDOR_ID_BROADCOM, 484 .subdevice = PCI_ANY_ID, 485 .class = PCI_CLASS_BRIDGE_CARDBUS << 8, 486 .class_mask = ~0, 487 }, 488 489 { 490 .vendor = PCI_VENDOR_ID_BROADCOM, 491 .device = BCM6358_CPU_ID, 492 .subvendor = PCI_VENDOR_ID_BROADCOM, 493 .subdevice = PCI_ANY_ID, 494 .class = PCI_CLASS_BRIDGE_CARDBUS << 8, 495 .class_mask = ~0, 496 }, 497 498 { }, 499}; 500 501MODULE_DEVICE_TABLE(pci, bcm63xx_cb_table); 502 503static struct pci_driver bcm63xx_cardbus_driver = { 504 .name = "bcm63xx_cardbus", 505 .id_table = bcm63xx_cb_table, 506 .probe = bcm63xx_cb_probe, 507 .remove = bcm63xx_cb_exit, 508}; 509#endif 510 511/* 512 * if cardbus support is enabled, register our platform device after 513 * our fake cardbus bridge has been registered 514 */ 515static int __init bcm63xx_pcmcia_init(void) 516{ 517#ifdef CONFIG_CARDBUS 518 return pci_register_driver(&bcm63xx_cardbus_driver); 519#else 520 return platform_driver_register(&bcm63xx_pcmcia_driver); 521#endif 522} 523 524static void __exit bcm63xx_pcmcia_exit(void) 525{ 526#ifdef CONFIG_CARDBUS 527 return pci_unregister_driver(&bcm63xx_cardbus_driver); 528#else 529 platform_driver_unregister(&bcm63xx_pcmcia_driver); 530#endif 531} 532 533module_init(bcm63xx_pcmcia_init); 534module_exit(bcm63xx_pcmcia_exit); 535 536MODULE_LICENSE("GPL"); 537MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>"); 538MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm63xx Socket Controller");