2 * Industry-pack bus support functions.
4 * Copyright (C) 2011-2012 CERN (www.cern.ch)
5 * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; version 2 of the License.
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/idr.h>
16 #include <linux/ipack.h>
18 #define to_ipack_dev(device) container_of(device, struct ipack_device, dev)
19 #define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver)
21 static DEFINE_IDA(ipack_ida
);
23 static void ipack_device_release(struct device
*dev
)
25 struct ipack_device
*device
= to_ipack_dev(dev
);
27 device
->release(device
);
30 static inline const struct ipack_device_id
*
31 ipack_match_one_device(const struct ipack_device_id
*id
,
32 const struct ipack_device
*device
)
34 if ((id
->format
== IPACK_ANY_FORMAT
||
35 id
->format
== device
->id_format
) &&
36 (id
->vendor
== IPACK_ANY_ID
|| id
->vendor
== device
->id_vendor
) &&
37 (id
->device
== IPACK_ANY_ID
|| id
->device
== device
->id_device
))
42 static const struct ipack_device_id
*
43 ipack_match_id(const struct ipack_device_id
*ids
, struct ipack_device
*idev
)
46 while (ids
->vendor
|| ids
->device
) {
47 if (ipack_match_one_device(ids
, idev
))
55 static int ipack_bus_match(struct device
*dev
, struct device_driver
*drv
)
57 struct ipack_device
*idev
= to_ipack_dev(dev
);
58 struct ipack_driver
*idrv
= to_ipack_driver(drv
);
59 const struct ipack_device_id
*found_id
;
61 found_id
= ipack_match_id(idrv
->id_table
, idev
);
62 return found_id
? 1 : 0;
65 static int ipack_bus_probe(struct device
*device
)
67 struct ipack_device
*dev
= to_ipack_dev(device
);
68 struct ipack_driver
*drv
= to_ipack_driver(device
->driver
);
73 return drv
->ops
->probe(dev
);
76 static int ipack_bus_remove(struct device
*device
)
78 struct ipack_device
*dev
= to_ipack_dev(device
);
79 struct ipack_driver
*drv
= to_ipack_driver(device
->driver
);
81 if (!drv
->ops
->remove
)
84 drv
->ops
->remove(dev
);
88 static int ipack_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
90 struct ipack_device
*idev
;
95 idev
= to_ipack_dev(dev
);
97 if (add_uevent_var(env
,
98 "MODALIAS=ipack:f%02Xv%08Xd%08X", idev
->id_format
,
99 idev
->id_vendor
, idev
->id_device
))
105 #define ipack_device_attr(field, format_string) \
107 field##_show(struct device *dev, struct device_attribute *attr, \
110 struct ipack_device *idev = to_ipack_dev(dev); \
111 return sprintf(buf, format_string, idev->field); \
114 static ssize_t
id_show(struct device
*dev
,
115 struct device_attribute
*attr
, char *buf
)
117 unsigned int i
, c
, l
, s
;
118 struct ipack_device
*idev
= to_ipack_dev(dev
);
121 switch (idev
->id_format
) {
122 case IPACK_ID_VERSION_1
:
123 l
= 0x7; s
= 1; break;
124 case IPACK_ID_VERSION_2
:
125 l
= 0xf; s
= 2; break;
130 for (i
= 0; i
< idev
->id_avail
; i
++) {
134 else if ((i
& s
) == 0)
137 sprintf(&buf
[c
], "%02x", idev
->id
[i
]);
145 id_vendor_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
147 struct ipack_device
*idev
= to_ipack_dev(dev
);
148 switch (idev
->id_format
) {
149 case IPACK_ID_VERSION_1
:
150 return sprintf(buf
, "0x%02x\n", idev
->id_vendor
);
151 case IPACK_ID_VERSION_2
:
152 return sprintf(buf
, "0x%06x\n", idev
->id_vendor
);
159 id_device_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
161 struct ipack_device
*idev
= to_ipack_dev(dev
);
162 switch (idev
->id_format
) {
163 case IPACK_ID_VERSION_1
:
164 return sprintf(buf
, "0x%02x\n", idev
->id_device
);
165 case IPACK_ID_VERSION_2
:
166 return sprintf(buf
, "0x%04x\n", idev
->id_device
);
172 static ssize_t
modalias_show(struct device
*dev
, struct device_attribute
*attr
,
175 struct ipack_device
*idev
= to_ipack_dev(dev
);
177 return sprintf(buf
, "ipac:f%02Xv%08Xd%08X", idev
->id_format
,
178 idev
->id_vendor
, idev
->id_device
);
181 ipack_device_attr(id_format
, "0x%hhx\n");
183 static DEVICE_ATTR_RO(id
);
184 static DEVICE_ATTR_RO(id_device
);
185 static DEVICE_ATTR_RO(id_format
);
186 static DEVICE_ATTR_RO(id_vendor
);
187 static DEVICE_ATTR_RO(modalias
);
189 static struct attribute
*ipack_attrs
[] = {
191 &dev_attr_id_device
.attr
,
192 &dev_attr_id_format
.attr
,
193 &dev_attr_id_vendor
.attr
,
194 &dev_attr_modalias
.attr
,
197 ATTRIBUTE_GROUPS(ipack
);
199 static struct bus_type ipack_bus_type
= {
201 .probe
= ipack_bus_probe
,
202 .match
= ipack_bus_match
,
203 .remove
= ipack_bus_remove
,
204 .dev_groups
= ipack_groups
,
205 .uevent
= ipack_uevent
,
208 struct ipack_bus_device
*ipack_bus_register(struct device
*parent
, int slots
,
209 const struct ipack_bus_ops
*ops
,
210 struct module
*owner
)
213 struct ipack_bus_device
*bus
;
215 bus
= kzalloc(sizeof(*bus
), GFP_KERNEL
);
219 bus_nr
= ida_simple_get(&ipack_ida
, 0, 0, GFP_KERNEL
);
225 bus
->bus_nr
= bus_nr
;
226 bus
->parent
= parent
;
232 EXPORT_SYMBOL_GPL(ipack_bus_register
);
234 static int ipack_unregister_bus_member(struct device
*dev
, void *data
)
236 struct ipack_device
*idev
= to_ipack_dev(dev
);
237 struct ipack_bus_device
*bus
= data
;
239 if (idev
->bus
== bus
)
240 ipack_device_del(idev
);
245 int ipack_bus_unregister(struct ipack_bus_device
*bus
)
247 bus_for_each_dev(&ipack_bus_type
, NULL
, bus
,
248 ipack_unregister_bus_member
);
249 ida_simple_remove(&ipack_ida
, bus
->bus_nr
);
253 EXPORT_SYMBOL_GPL(ipack_bus_unregister
);
255 int ipack_driver_register(struct ipack_driver
*edrv
, struct module
*owner
,
258 edrv
->driver
.owner
= owner
;
259 edrv
->driver
.name
= name
;
260 edrv
->driver
.bus
= &ipack_bus_type
;
261 return driver_register(&edrv
->driver
);
263 EXPORT_SYMBOL_GPL(ipack_driver_register
);
265 void ipack_driver_unregister(struct ipack_driver
*edrv
)
267 driver_unregister(&edrv
->driver
);
269 EXPORT_SYMBOL_GPL(ipack_driver_unregister
);
271 static u16
ipack_crc_byte(u16 crc
, u8 c
)
276 for (i
= 0; i
< 8; i
++)
277 crc
= (crc
<< 1) ^ ((crc
& 0x8000) ? 0x1021 : 0);
282 * The algorithm in lib/crc-ccitt.c does not seem to apply since it uses the
283 * opposite bit ordering.
285 static u8
ipack_calc_crc1(struct ipack_device
*dev
)
292 for (i
= 0; i
< dev
->id_avail
; i
++) {
293 c
= (i
!= 11) ? dev
->id
[i
] : 0;
294 crc
= ipack_crc_byte(crc
, c
);
300 static u16
ipack_calc_crc2(struct ipack_device
*dev
)
307 for (i
= 0; i
< dev
->id_avail
; i
++) {
308 c
= ((i
!= 0x18) && (i
!= 0x19)) ? dev
->id
[i
] : 0;
309 crc
= ipack_crc_byte(crc
, c
);
315 static void ipack_parse_id1(struct ipack_device
*dev
)
320 dev
->id_vendor
= id
[4];
321 dev
->id_device
= id
[5];
323 dev
->speed_32mhz
= (id
[7] == 'H');
324 crc
= ipack_calc_crc1(dev
);
325 dev
->id_crc_correct
= (crc
== id
[11]);
326 if (!dev
->id_crc_correct
) {
327 dev_warn(&dev
->dev
, "ID CRC invalid found 0x%x, expected 0x%x.\n",
332 static void ipack_parse_id2(struct ipack_device
*dev
)
334 __be16
*id
= (__be16
*) dev
->id
;
337 dev
->id_vendor
= ((be16_to_cpu(id
[3]) & 0xff) << 16)
338 + be16_to_cpu(id
[4]);
339 dev
->id_device
= be16_to_cpu(id
[5]);
340 flags
= be16_to_cpu(id
[10]);
341 dev
->speed_8mhz
= !!(flags
& 2);
342 dev
->speed_32mhz
= !!(flags
& 4);
343 crc
= ipack_calc_crc2(dev
);
344 dev
->id_crc_correct
= (crc
== be16_to_cpu(id
[12]));
345 if (!dev
->id_crc_correct
) {
346 dev_warn(&dev
->dev
, "ID CRC invalid found 0x%x, expected 0x%x.\n",
351 static int ipack_device_read_id(struct ipack_device
*dev
)
357 idmem
= ioremap(dev
->region
[IPACK_ID_SPACE
].start
,
358 dev
->region
[IPACK_ID_SPACE
].size
);
360 dev_err(&dev
->dev
, "error mapping memory\n");
364 /* Determine ID PROM Data Format. If we find the ids "IPAC" or "IPAH"
365 * we are dealing with a IndustryPack format 1 device. If we detect
366 * "VITA4 " (16 bit big endian formatted) we are dealing with a
367 * IndustryPack format 2 device */
368 if ((ioread8(idmem
+ 1) == 'I') &&
369 (ioread8(idmem
+ 3) == 'P') &&
370 (ioread8(idmem
+ 5) == 'A') &&
371 ((ioread8(idmem
+ 7) == 'C') ||
372 (ioread8(idmem
+ 7) == 'H'))) {
373 dev
->id_format
= IPACK_ID_VERSION_1
;
374 dev
->id_avail
= ioread8(idmem
+ 0x15);
375 if ((dev
->id_avail
< 0x0c) || (dev
->id_avail
> 0x40)) {
376 dev_warn(&dev
->dev
, "invalid id size");
377 dev
->id_avail
= 0x0c;
379 } else if ((ioread8(idmem
+ 0) == 'I') &&
380 (ioread8(idmem
+ 1) == 'V') &&
381 (ioread8(idmem
+ 2) == 'A') &&
382 (ioread8(idmem
+ 3) == 'T') &&
383 (ioread8(idmem
+ 4) == ' ') &&
384 (ioread8(idmem
+ 5) == '4')) {
385 dev
->id_format
= IPACK_ID_VERSION_2
;
386 dev
->id_avail
= ioread16be(idmem
+ 0x16);
387 if ((dev
->id_avail
< 0x1a) || (dev
->id_avail
> 0x40)) {
388 dev_warn(&dev
->dev
, "invalid id size");
389 dev
->id_avail
= 0x1a;
392 dev
->id_format
= IPACK_ID_VERSION_INVALID
;
396 if (!dev
->id_avail
) {
401 /* Obtain the amount of memory required to store a copy of the complete
403 dev
->id
= kmalloc(dev
->id_avail
, GFP_KERNEL
);
408 for (i
= 0; i
< dev
->id_avail
; i
++) {
409 if (dev
->id_format
== IPACK_ID_VERSION_1
)
410 dev
->id
[i
] = ioread8(idmem
+ (i
<< 1) + 1);
412 dev
->id
[i
] = ioread8(idmem
+ i
);
415 /* now we can finally work with the copy */
416 switch (dev
->id_format
) {
417 case IPACK_ID_VERSION_1
:
418 ipack_parse_id1(dev
);
420 case IPACK_ID_VERSION_2
:
421 ipack_parse_id2(dev
);
431 int ipack_device_init(struct ipack_device
*dev
)
435 dev
->dev
.bus
= &ipack_bus_type
;
436 dev
->dev
.release
= ipack_device_release
;
437 dev
->dev
.parent
= dev
->bus
->parent
;
438 dev_set_name(&dev
->dev
,
439 "ipack-dev.%u.%u", dev
->bus
->bus_nr
, dev
->slot
);
440 device_initialize(&dev
->dev
);
442 if (dev
->bus
->ops
->set_clockrate(dev
, 8))
443 dev_warn(&dev
->dev
, "failed to switch to 8 MHz operation for reading of device ID.\n");
444 if (dev
->bus
->ops
->reset_timeout(dev
))
445 dev_warn(&dev
->dev
, "failed to reset potential timeout.");
447 ret
= ipack_device_read_id(dev
);
449 dev_err(&dev
->dev
, "error reading device id section.\n");
453 /* if the device supports 32 MHz operation, use it. */
454 if (dev
->speed_32mhz
) {
455 ret
= dev
->bus
->ops
->set_clockrate(dev
, 32);
457 dev_err(&dev
->dev
, "failed to switch to 32 MHz operation.\n");
462 EXPORT_SYMBOL_GPL(ipack_device_init
);
464 int ipack_device_add(struct ipack_device
*dev
)
466 return device_add(&dev
->dev
);
468 EXPORT_SYMBOL_GPL(ipack_device_add
);
470 void ipack_device_del(struct ipack_device
*dev
)
472 device_del(&dev
->dev
);
473 ipack_put_device(dev
);
475 EXPORT_SYMBOL_GPL(ipack_device_del
);
477 void ipack_get_device(struct ipack_device
*dev
)
479 get_device(&dev
->dev
);
481 EXPORT_SYMBOL_GPL(ipack_get_device
);
483 void ipack_put_device(struct ipack_device
*dev
)
485 put_device(&dev
->dev
);
487 EXPORT_SYMBOL_GPL(ipack_put_device
);
489 static int __init
ipack_init(void)
491 ida_init(&ipack_ida
);
492 return bus_register(&ipack_bus_type
);
495 static void __exit
ipack_exit(void)
497 bus_unregister(&ipack_bus_type
);
498 ida_destroy(&ipack_ida
);
501 module_init(ipack_init
);
502 module_exit(ipack_exit
);
504 MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>");
505 MODULE_LICENSE("GPL");
506 MODULE_DESCRIPTION("Industry-pack bus core");