0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/ptrace.h>
0017 #include <linux/slab.h>
0018 #include <linux/string.h>
0019 #include <linux/timer.h>
0020 #include <linux/ioport.h>
0021 #include <linux/platform_device.h>
0022
0023 #include <pcmcia/cistpl.h>
0024 #include <pcmcia/cisreg.h>
0025 #include <pcmcia/ds.h>
0026
0027 #include <linux/usb/sl811.h>
0028
0029 MODULE_AUTHOR("Botond Botyanszki");
0030 MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6");
0031 MODULE_LICENSE("GPL");
0032
0033
0034
0035
0036
0037
0038 #define INFO(args...) printk(KERN_INFO "sl811_cs: " args)
0039
0040
0041
0042
0043
0044 typedef struct local_info_t {
0045 struct pcmcia_device *p_dev;
0046 } local_info_t;
0047
0048 static void sl811_cs_release(struct pcmcia_device * link);
0049
0050
0051
0052 static void release_platform_dev(struct device * dev)
0053 {
0054 dev_dbg(dev, "sl811_cs platform_dev release\n");
0055 dev->parent = NULL;
0056 }
0057
0058 static struct sl811_platform_data platform_data = {
0059 .potpg = 100,
0060 .power = 50,
0061
0062 };
0063
0064 static struct resource resources[] = {
0065 [0] = {
0066 .flags = IORESOURCE_IRQ,
0067 },
0068 [1] = {
0069
0070 .flags = IORESOURCE_IO,
0071 },
0072 [2] = {
0073
0074 .flags = IORESOURCE_IO,
0075 },
0076 };
0077
0078 extern struct platform_driver sl811h_driver;
0079
0080 static struct platform_device platform_dev = {
0081 .id = -1,
0082 .dev = {
0083 .platform_data = &platform_data,
0084 .release = release_platform_dev,
0085 },
0086 .resource = resources,
0087 .num_resources = ARRAY_SIZE(resources),
0088 };
0089
0090 static int sl811_hc_init(struct device *parent, resource_size_t base_addr,
0091 int irq)
0092 {
0093 if (platform_dev.dev.parent)
0094 return -EBUSY;
0095 platform_dev.dev.parent = parent;
0096
0097
0098 resources[0].start = irq;
0099
0100 resources[1].start = base_addr;
0101 resources[1].end = base_addr;
0102
0103 resources[2].start = base_addr + 1;
0104 resources[2].end = base_addr + 1;
0105
0106
0107
0108
0109
0110 platform_dev.name = sl811h_driver.driver.name;
0111 return platform_device_register(&platform_dev);
0112 }
0113
0114
0115
0116 static void sl811_cs_detach(struct pcmcia_device *link)
0117 {
0118 dev_dbg(&link->dev, "sl811_cs_detach\n");
0119
0120 sl811_cs_release(link);
0121
0122
0123 kfree(link->priv);
0124 }
0125
0126 static void sl811_cs_release(struct pcmcia_device * link)
0127 {
0128 dev_dbg(&link->dev, "sl811_cs_release\n");
0129
0130 pcmcia_disable_device(link);
0131 platform_device_unregister(&platform_dev);
0132 }
0133
0134 static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
0135 {
0136 if (p_dev->config_index == 0)
0137 return -EINVAL;
0138
0139 return pcmcia_request_io(p_dev);
0140 }
0141
0142
0143 static int sl811_cs_config(struct pcmcia_device *link)
0144 {
0145 struct device *parent = &link->dev;
0146 int ret;
0147
0148 dev_dbg(&link->dev, "sl811_cs_config\n");
0149
0150 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
0151 CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO;
0152
0153 if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
0154 goto failed;
0155
0156
0157 if (resource_size(link->resource[0]) < 2)
0158 goto failed;
0159
0160 if (!link->irq)
0161 goto failed;
0162
0163 ret = pcmcia_enable_device(link);
0164 if (ret)
0165 goto failed;
0166
0167 if (sl811_hc_init(parent, link->resource[0]->start, link->irq)
0168 < 0) {
0169 failed:
0170 printk(KERN_WARNING "sl811_cs_config failed\n");
0171 sl811_cs_release(link);
0172 return -ENODEV;
0173 }
0174 return 0;
0175 }
0176
0177 static int sl811_cs_probe(struct pcmcia_device *link)
0178 {
0179 local_info_t *local;
0180
0181 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
0182 if (!local)
0183 return -ENOMEM;
0184 local->p_dev = link;
0185 link->priv = local;
0186
0187 return sl811_cs_config(link);
0188 }
0189
0190 static const struct pcmcia_device_id sl811_ids[] = {
0191 PCMCIA_DEVICE_MANF_CARD(0xc015, 0x0001),
0192 PCMCIA_DEVICE_NULL,
0193 };
0194 MODULE_DEVICE_TABLE(pcmcia, sl811_ids);
0195
0196 static struct pcmcia_driver sl811_cs_driver = {
0197 .owner = THIS_MODULE,
0198 .name = "sl811_cs",
0199 .probe = sl811_cs_probe,
0200 .remove = sl811_cs_detach,
0201 .id_table = sl811_ids,
0202 };
0203 module_pcmcia_driver(sl811_cs_driver);