4807f95ce33a41cb0b3d1f55bbe79c98ec601875
[openwrt/openwrt.git] / package / ucmb / src / ucmb.c
1 /*
2 * Microcontroller Message Bus
3 *
4 * Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
5 *
6 * Licensed under the GNU/GPL. See COPYING for details.
7 */
8
9 #include "ucmb.h"
10
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/miscdevice.h>
14 #include <linux/fs.h>
15 #include <linux/spi/spi.h>
16 #include <linux/spi/spi_gpio.h>
17 #include <linux/spi/spi_bitbang.h>
18 #include <linux/gfp.h>
19
20
21 #define PFX "ucmb: "
22
23
24 MODULE_LICENSE("GPL");
25 MODULE_DESCRIPTION("Microcontroller Message Bus");
26 MODULE_AUTHOR("Michael Buesch");
27
28
29 struct ucmb {
30 /* Misc character device driver */
31 struct miscdevice mdev;
32 struct file_operations mdev_fops;
33
34 /* SPI driver */
35 struct spi_device *sdev;
36
37 /* SPI-GPIO driver */
38 struct spi_gpio_platform_data spi_gpio_pdata;
39 struct platform_device spi_gpio_pdev;
40 };
41
42 static int ucmb_spi_busnum_count = 1337;
43
44
45 static struct ucmb_platform_data ucmb_list[] = {
46 { //FIXME don't define it here.
47 .name = "ucmb",
48 .gpio_sck = 0,
49 .gpio_miso = 1,
50 .gpio_mosi = 2,
51 },
52 };
53
54
55 static int __devinit ucmb_spi_probe(struct spi_device *sdev)
56 {
57 return 0;
58 }
59
60 static int __devexit ucmb_spi_remove(struct spi_device *sdev)
61 {
62 return 0;
63 }
64
65 static struct spi_driver ucmb_spi_driver = {
66 .driver = {
67 .name = "ucmb",
68 .bus = &spi_bus_type,
69 .owner = THIS_MODULE,
70 },
71 .probe = ucmb_spi_probe,
72 .remove = __devexit_p(ucmb_spi_remove),
73 };
74
75 static inline struct ucmb * filp_to_ucmb(struct file *filp)
76 {
77 return container_of(filp->f_op, struct ucmb, mdev_fops);
78 }
79
80 /* FIXME offp */
81 static ssize_t ucmb_read(struct file *filp, char __user *user_buf,
82 size_t size, loff_t *offp)
83 {
84 struct ucmb *ucmb = filp_to_ucmb(filp);
85 u8 *buf;
86 int err;
87
88 err = -E2BIG;
89 if (size > PAGE_SIZE)
90 goto out;
91
92 err = -ENOMEM;
93 buf = (char *)__get_free_page(GFP_KERNEL);
94 if (!buf)
95 goto out;
96
97 err = spi_read(ucmb->sdev, buf, size);
98 if (err)
99 goto out_free;
100
101 err = -EFAULT;
102 if (copy_to_user(user_buf, buf, size))
103 goto out_free;
104
105 err = 0;
106
107 out_free:
108 __free_page((unsigned long)buf);
109 out:
110 return err ? err : size;
111 }
112
113 /* FIXME offp */
114 static ssize_t ucmb_write(struct file *filp, const char __user *user_buf,
115 size_t size, loff_t *offp)
116 {
117 struct ucmb *ucmb = filp_to_ucmb(filp);
118 u8 *buf;
119 int err;
120
121 err = -ENOMEM;
122 buf = (char *)__get_free_page(GFP_KERNEL);
123 if (!buf)
124 goto out;
125
126 size = min(PAGE_SIZE, size);
127 err = -EFAULT;
128 if (copy_from_user(buf, user_buf, size))
129 goto out_free;
130
131 err = spi_write(ucmb->sdev, buf, size);
132
133 out_free:
134 __free_page((unsigned long)buf);
135 out:
136 return err ? err : size;
137 }
138
139 static int __devinit ucmb_probe(struct platform_device *pdev)
140 {
141 struct ucmb_platform_data *pdata;
142 struct ucmb *ucmb;
143 int err;
144 const int bus_num = ucmb_spi_busnum_count++;
145 struct spi_bitbang *bb;
146
147 pdata = pdev->dev.platform_data;
148 if (!pdata)
149 return -ENXIO;
150
151 ucmb = kzalloc(sizeof(struct ucmb), GFP_KERNEL);
152 if (!ucmb)
153 return -ENOMEM;
154
155 /* Create the SPI GPIO bus master. */
156
157 #ifdef CONFIG_SPI_GPIO_MODULE
158 err = request_module("spi_gpio");
159 if (err)
160 printk(KERN_WARNING PFX "Failed to request spi_gpio module\n");
161 #endif /* CONFIG_SPI_GPIO_MODULE */
162
163 ucmb->spi_gpio_pdata.sck = pdata->gpio_sck;
164 ucmb->spi_gpio_pdata.mosi = pdata->gpio_mosi;
165 ucmb->spi_gpio_pdata.miso = pdata->gpio_miso;
166 ucmb->spi_gpio_pdata.num_chipselect = 1;
167
168 ucmb->spi_gpio_pdev.name = "spi_gpio";
169 ucmb->spi_gpio_pdev.id = bus_num;
170 ucmb->spi_gpio_pdev.dev.platform_data = &ucmb->spi_gpio_pdata;
171
172 err = platform_device_register(&ucmb->spi_gpio_pdev);
173 if (err) {
174 printk(KERN_ERR PFX "Failed to register SPI-GPIO platform device\n");
175 goto err_free_ucmb;
176 }
177 bb = platform_get_drvdata(&ucmb->spi_gpio_pdev);
178 if (!bb || !bb->master) {
179 printk(KERN_ERR PFX "No bitbanged master device found.\n");
180 goto err_unreg_spi_gpio_pdev;
181 }
182
183 /* Create the SPI device. */
184
185 ucmb->sdev = spi_alloc_device(bb->master);
186 if (!ucmb->sdev) {
187 printk(KERN_ERR PFX "Failed to allocate SPI device\n");
188 goto err_unreg_spi_gpio_pdev;
189 }
190 ucmb->sdev->max_speed_hz = 5000000;
191 ucmb->sdev->chip_select = 0;
192 ucmb->sdev->mode = SPI_MODE_0;
193 strlcpy(ucmb->sdev->modalias, "ucmb", /* We are the SPI driver. */
194 sizeof(ucmb->sdev->modalias));
195 ucmb->sdev->controller_data = (void *)SPI_GPIO_NO_CHIPSELECT;
196 err = spi_add_device(ucmb->sdev);
197 if (err) {
198 printk(KERN_ERR PFX "Failed to add SPI device\n");
199 goto err_free_spi_device;
200 }
201
202 /* Create the Misc char device. */
203
204 ucmb->mdev.minor = MISC_DYNAMIC_MINOR;
205 ucmb->mdev.name = pdata->name;
206 ucmb->mdev.parent = &pdev->dev;
207 ucmb->mdev_fops.read = ucmb_read;
208 ucmb->mdev_fops.write = ucmb_write;
209 ucmb->mdev.fops = &ucmb->mdev_fops;
210
211 err = misc_register(&ucmb->mdev);
212 if (err) {
213 printk(KERN_ERR PFX "Failed to register miscdev %s\n",
214 ucmb->mdev.name);
215 goto err_unreg_spi_device;
216 }
217
218 platform_set_drvdata(pdev, ucmb);
219
220 printk(KERN_INFO PFX "Registered message bus \"%s\"\n", pdata->name);
221
222 return 0;
223
224 err_unreg_spi_device:
225 spi_unregister_device(ucmb->sdev);
226 err_free_spi_device:
227 spi_dev_put(ucmb->sdev);
228 err_unreg_spi_gpio_pdev:
229 platform_device_unregister(&ucmb->spi_gpio_pdev);
230 err_free_ucmb:
231 kfree(ucmb);
232
233 return err;
234 }
235
236 static int __devexit ucmb_remove(struct platform_device *pdev)
237 {
238 struct ucmb *ucmb = platform_get_drvdata(pdev);
239 int err;
240
241 err = misc_deregister(&ucmb->mdev);
242 if (err) {
243 printk(KERN_ERR PFX "Failed to unregister miscdev %s\n",
244 ucmb->mdev.name);
245 }
246 spi_unregister_device(ucmb->sdev);
247 spi_dev_put(ucmb->sdev);
248 platform_device_unregister(&ucmb->spi_gpio_pdev);
249
250 kfree(ucmb);
251 platform_set_drvdata(pdev, NULL);
252
253 return 0;
254 }
255
256 static struct platform_driver ucmb_driver = {
257 .driver = {
258 .name = "ucmb",
259 .owner = THIS_MODULE,
260 },
261 .probe = ucmb_probe,
262 .remove = __devexit_p(ucmb_probe),
263 };
264
265 static int ucmb_modinit(void)
266 {
267 struct ucmb_platform_data *pdata;
268 struct platform_device *pdev;
269 int err, i;
270
271 printk(KERN_INFO "Microcontroller message bus driver\n");
272
273 err = platform_driver_register(&ucmb_driver);
274 if (err) {
275 printk(KERN_ERR PFX "Failed to register platform driver\n");
276 return err;
277 }
278 err = spi_register_driver(&ucmb_spi_driver);
279 if (err) {
280 printk(KERN_ERR PFX "Failed to register SPI driver\n");
281 platform_driver_unregister(&ucmb_driver);
282 return err;
283 }
284
285 for (i = 0; i < ARRAY_SIZE(ucmb_list); i++) {
286 pdata = &ucmb_list[i];
287
288 pdev = platform_device_alloc("ucmb", i);
289 if (!pdev) {
290 printk(KERN_ERR PFX "Failed to allocate platform device.\n");
291 break;
292 }
293 err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
294 if (err) {
295 printk(KERN_ERR PFX "Failed to add platform data.\n");
296 platform_device_put(pdev);
297 break;
298 }
299 err = platform_device_add(pdev);
300 if (err) {
301 printk(KERN_ERR PFX "Failed to register platform device.\n");
302 platform_device_put(pdev);
303 break;
304 }
305 pdata->pdev = pdev;
306 }
307
308 return 0;
309 }
310 module_init(ucmb_modinit);
311
312 static void ucmb_modexit(void)
313 {
314 struct ucmb_platform_data *pdata;
315 int i;
316
317 for (i = 0; i < ARRAY_SIZE(ucmb_list); i++) {
318 pdata = &ucmb_list[i];
319
320 if (pdata->pdev) {
321 platform_device_unregister(pdata->pdev);
322 platform_device_put(pdata->pdev);
323 }
324 }
325 spi_unregister_driver(&ucmb_spi_driver);
326 platform_driver_unregister(&ucmb_driver);
327 }
328 module_exit(ucmb_modexit);