0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ssb_private.h"
0010
0011 #include <linux/ssb/ssb.h>
0012 #include <linux/slab.h>
0013 #include <linux/module.h>
0014
0015 #include <pcmcia/cistpl.h>
0016 #include <pcmcia/ciscode.h>
0017 #include <pcmcia/ds.h>
0018 #include <pcmcia/cisreg.h>
0019
0020 static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
0021 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
0022 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
0023 PCMCIA_DEVICE_NULL,
0024 };
0025
0026 MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
0027
0028 static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
0029 {
0030 struct ssb_bus *ssb;
0031 int err = -ENOMEM;
0032 int res = 0;
0033
0034 ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
0035 if (!ssb)
0036 goto out_error;
0037
0038 err = -ENODEV;
0039
0040 dev->config_flags |= CONF_ENABLE_IRQ;
0041
0042 dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
0043 WIN_USE_WAIT;
0044 dev->resource[2]->start = 0;
0045 dev->resource[2]->end = SSB_CORE_SIZE;
0046 res = pcmcia_request_window(dev, dev->resource[2], 250);
0047 if (res != 0)
0048 goto err_kfree_ssb;
0049
0050 res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
0051 if (res != 0)
0052 goto err_disable;
0053
0054 if (!dev->irq)
0055 goto err_disable;
0056
0057 res = pcmcia_enable_device(dev);
0058 if (res != 0)
0059 goto err_disable;
0060
0061 err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
0062 if (err)
0063 goto err_disable;
0064 dev->priv = ssb;
0065
0066 return 0;
0067
0068 err_disable:
0069 pcmcia_disable_device(dev);
0070 err_kfree_ssb:
0071 kfree(ssb);
0072 out_error:
0073 dev_err(&dev->dev, "Initialization failed (%d, %d)\n", res, err);
0074 return err;
0075 }
0076
0077 static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
0078 {
0079 struct ssb_bus *ssb = dev->priv;
0080
0081 ssb_bus_unregister(ssb);
0082 pcmcia_disable_device(dev);
0083 kfree(ssb);
0084 dev->priv = NULL;
0085 }
0086
0087 #ifdef CONFIG_PM
0088 static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
0089 {
0090 struct ssb_bus *ssb = dev->priv;
0091
0092 return ssb_bus_suspend(ssb);
0093 }
0094
0095 static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
0096 {
0097 struct ssb_bus *ssb = dev->priv;
0098
0099 return ssb_bus_resume(ssb);
0100 }
0101 #else
0102 # define ssb_host_pcmcia_suspend NULL
0103 # define ssb_host_pcmcia_resume NULL
0104 #endif
0105
0106 static struct pcmcia_driver ssb_host_pcmcia_driver = {
0107 .owner = THIS_MODULE,
0108 .name = "ssb-pcmcia",
0109 .id_table = ssb_host_pcmcia_tbl,
0110 .probe = ssb_host_pcmcia_probe,
0111 .remove = ssb_host_pcmcia_remove,
0112 .suspend = ssb_host_pcmcia_suspend,
0113 .resume = ssb_host_pcmcia_resume,
0114 };
0115
0116 static int pcmcia_init_failed;
0117
0118
0119
0120
0121
0122 int ssb_host_pcmcia_init(void)
0123 {
0124 pcmcia_init_failed = pcmcia_register_driver(&ssb_host_pcmcia_driver);
0125
0126 return pcmcia_init_failed;
0127 }
0128
0129 void ssb_host_pcmcia_exit(void)
0130 {
0131 if (!pcmcia_init_failed)
0132 pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
0133 }