2 * Industry-pack bus support functions.
4 * (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
5 * (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
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>
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
);
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
);
90 static int ipack_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
92 struct ipack_device
*idev
;
97 idev
= to_ipack_dev(dev
);
99 if (add_uevent_var(env
,
100 "MODALIAS=ipack:f%02Xv%08Xd%08X", idev
->id_format
,
101 idev
->id_vendor
, idev
->id_device
))
107 #else /* !CONFIG_HOTPLUG */
109 #define ipack_uevent NULL
111 #endif /* !CONFIG_HOTPLUG */
113 #define ipack_device_attr(field, format_string) \
115 field##_show(struct device *dev, struct device_attribute *attr, \
118 struct ipack_device *idev = to_ipack_dev(dev); \
119 return sprintf(buf, format_string, idev->field); \
122 static ssize_t
id_show(struct device
*dev
,
123 struct device_attribute
*attr
, char *buf
)
125 unsigned int i
, c
, l
, s
;
126 struct ipack_device
*idev
= to_ipack_dev(dev
);
129 switch (idev
->id_format
) {
130 case IPACK_ID_VERSION_1
:
131 l
= 0x7; s
= 1; break;
132 case IPACK_ID_VERSION_2
:
133 l
= 0xf; s
= 2; break;
138 for (i
= 0; i
< idev
->id_avail
; i
++) {
142 else if ((i
& s
) == 0)
145 sprintf(&buf
[c
], "%02x", idev
->id
[i
]);
153 id_vendor_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
155 struct ipack_device
*idev
= to_ipack_dev(dev
);
156 switch (idev
->id_format
) {
157 case IPACK_ID_VERSION_1
:
158 return sprintf(buf
, "0x%02x\n", idev
->id_vendor
);
159 case IPACK_ID_VERSION_2
:
160 return sprintf(buf
, "0x%06x\n", idev
->id_vendor
);
167 id_device_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
169 struct ipack_device
*idev
= to_ipack_dev(dev
);
170 switch (idev
->id_format
) {
171 case IPACK_ID_VERSION_1
:
172 return sprintf(buf
, "0x%02x\n", idev
->id_device
);
173 case IPACK_ID_VERSION_2
:
174 return sprintf(buf
, "0x%04x\n", idev
->id_device
);
180 static ssize_t
modalias_show(struct device
*dev
, struct device_attribute
*attr
,
183 struct ipack_device
*idev
= to_ipack_dev(dev
);
185 return sprintf(buf
, "ipac:f%02Xv%08Xd%08X", idev
->id_format
,
186 idev
->id_vendor
, idev
->id_device
);
189 ipack_device_attr(id_format
, "0x%hhu\n");
191 static struct device_attribute ipack_dev_attrs
[] = {
193 __ATTR_RO(id_device
),
194 __ATTR_RO(id_format
),
195 __ATTR_RO(id_vendor
),
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_attrs
= ipack_dev_attrs
,
205 .uevent
= ipack_uevent
,
208 struct ipack_bus_device
*ipack_bus_register(struct device
*parent
, int slots
,
209 const struct ipack_bus_ops
*ops
)
212 struct ipack_bus_device
*bus
;
214 bus
= kzalloc(sizeof(struct ipack_bus_device
), GFP_KERNEL
);
218 bus_nr
= ida_simple_get(&ipack_ida
, 0, 0, GFP_KERNEL
);
224 bus
->bus_nr
= bus_nr
;
225 bus
->parent
= parent
;
230 EXPORT_SYMBOL_GPL(ipack_bus_register
);
232 static int ipack_unregister_bus_member(struct device
*dev
, void *data
)
234 struct ipack_device
*idev
= to_ipack_dev(dev
);
235 struct ipack_bus_device
*bus
= data
;
237 if (idev
->bus_nr
== bus
->bus_nr
)
238 ipack_device_unregister(idev
);
243 int ipack_bus_unregister(struct ipack_bus_device
*bus
)
245 bus_for_each_dev(&ipack_bus_type
, NULL
, bus
, ipack_unregister_bus_member
);
246 ida_simple_remove(&ipack_ida
, bus
->bus_nr
);
250 EXPORT_SYMBOL_GPL(ipack_bus_unregister
);
252 int ipack_driver_register(struct ipack_driver
*edrv
, struct module
*owner
,
255 edrv
->driver
.owner
= owner
;
256 edrv
->driver
.name
= name
;
257 edrv
->driver
.bus
= &ipack_bus_type
;
258 return driver_register(&edrv
->driver
);
260 EXPORT_SYMBOL_GPL(ipack_driver_register
);
262 void ipack_driver_unregister(struct ipack_driver
*edrv
)
264 driver_unregister(&edrv
->driver
);
266 EXPORT_SYMBOL_GPL(ipack_driver_unregister
);
268 static u16
ipack_crc_byte(u16 crc
, u8 c
)
273 for (i
= 0; i
< 8; i
++)
274 crc
= (crc
<< 1) ^ ((crc
& 0x8000) ? 0x1021 : 0);
279 * The algorithm in lib/crc-ccitt.c does not seem to apply since it uses the
280 * opposite bit ordering.
282 static u8
ipack_calc_crc1(struct ipack_device
*dev
)
289 for (i
= 0; i
< dev
->id_avail
; i
++) {
290 c
= (i
!= 11) ? dev
->id
[i
] : 0;
291 crc
= ipack_crc_byte(crc
, c
);
297 static u16
ipack_calc_crc2(struct ipack_device
*dev
)
304 for (i
= 0; i
< dev
->id_avail
; i
++) {
305 c
= ((i
!= 0x18) && (i
!= 0x19)) ? dev
->id
[i
] : 0;
306 crc
= ipack_crc_byte(crc
, c
);
312 static void ipack_parse_id1(struct ipack_device
*dev
)
317 dev
->id_vendor
= id
[4];
318 dev
->id_device
= id
[5];
320 dev
->speed_32mhz
= (id
[7] == 'H');
321 crc
= ipack_calc_crc1(dev
);
322 dev
->id_crc_correct
= (crc
== id
[11]);
323 if (!dev
->id_crc_correct
) {
324 dev_warn(&dev
->dev
, "ID CRC invalid found 0x%x, expected 0x%x.\n",
329 static void ipack_parse_id2(struct ipack_device
*dev
)
331 __be16
*id
= (__be16
*) dev
->id
;
334 dev
->id_vendor
= ((be16_to_cpu(id
[3]) & 0xff) << 16)
335 + be16_to_cpu(id
[4]);
336 dev
->id_device
= be16_to_cpu(id
[5]);
337 flags
= be16_to_cpu(id
[10]);
338 dev
->speed_8mhz
= !!(flags
& 2);
339 dev
->speed_32mhz
= !!(flags
& 4);
340 crc
= ipack_calc_crc2(dev
);
341 dev
->id_crc_correct
= (crc
== be16_to_cpu(id
[12]));
342 if (!dev
->id_crc_correct
) {
343 dev_warn(&dev
->dev
, "ID CRC invalid found 0x%x, expected 0x%x.\n",
348 static int ipack_device_read_id(struct ipack_device
*dev
)
354 ret
= dev
->bus
->ops
->map_space(dev
, 0, IPACK_ID_SPACE
);
356 dev_err(&dev
->dev
, "error mapping memory\n");
359 idmem
= dev
->id_space
.address
;
361 /* Determine ID PROM Data Format. If we find the ids "IPAC" or "IPAH"
362 * we are dealing with a IndustryPack format 1 device. If we detect
363 * "VITA4 " (16 bit big endian formatted) we are dealing with a
364 * IndustryPack format 2 device */
365 if ((ioread8(idmem
+ 1) == 'I') &&
366 (ioread8(idmem
+ 3) == 'P') &&
367 (ioread8(idmem
+ 5) == 'A') &&
368 ((ioread8(idmem
+ 7) == 'C') ||
369 (ioread8(idmem
+ 7) == 'H'))) {
370 dev
->id_format
= IPACK_ID_VERSION_1
;
371 dev
->id_avail
= ioread8(idmem
+ 0x15);
372 if ((dev
->id_avail
< 0x0c) || (dev
->id_avail
> 0x40)) {
373 dev_warn(&dev
->dev
, "invalid id size");
374 dev
->id_avail
= 0x0c;
376 } else if ((ioread8(idmem
+ 0) == 'I') &&
377 (ioread8(idmem
+ 1) == 'V') &&
378 (ioread8(idmem
+ 2) == 'A') &&
379 (ioread8(idmem
+ 3) == 'T') &&
380 (ioread8(idmem
+ 4) == ' ') &&
381 (ioread8(idmem
+ 5) == '4')) {
382 dev
->id_format
= IPACK_ID_VERSION_2
;
383 dev
->id_avail
= ioread16be(idmem
+ 0x16);
384 if ((dev
->id_avail
< 0x1a) || (dev
->id_avail
> 0x40)) {
385 dev_warn(&dev
->dev
, "invalid id size");
386 dev
->id_avail
= 0x1a;
389 dev
->id_format
= IPACK_ID_VERSION_INVALID
;
393 if (!dev
->id_avail
) {
398 /* Obtain the amount of memory required to store a copy of the complete
400 dev
->id
= kmalloc(dev
->id_avail
, GFP_KERNEL
);
402 dev_err(&dev
->dev
, "dev->id alloc failed.\n");
406 for (i
= 0; i
< dev
->id_avail
; i
++) {
407 if (dev
->id_format
== IPACK_ID_VERSION_1
)
408 dev
->id
[i
] = ioread8(idmem
+ (i
<< 1) + 1);
410 dev
->id
[i
] = ioread8(idmem
+ i
);
413 /* now we can finally work with the copy */
414 switch (dev
->id_format
) {
415 case IPACK_ID_VERSION_1
:
416 ipack_parse_id1(dev
);
418 case IPACK_ID_VERSION_2
:
419 ipack_parse_id2(dev
);
424 dev
->bus
->ops
->unmap_space(dev
, IPACK_ID_SPACE
);
429 struct ipack_device
*ipack_device_register(struct ipack_bus_device
*bus
,
433 struct ipack_device
*dev
;
435 dev
= kzalloc(sizeof(struct ipack_device
), GFP_KERNEL
);
439 dev
->dev
.bus
= &ipack_bus_type
;
440 dev
->dev
.release
= ipack_device_release
;
441 dev
->dev
.parent
= bus
->parent
;
443 dev
->bus_nr
= bus
->bus_nr
;
445 dev_set_name(&dev
->dev
,
446 "ipack-dev.%u.%u", dev
->bus_nr
, dev
->slot
);
448 if (bus
->ops
->set_clockrate(dev
, 8))
449 dev_warn(&dev
->dev
, "failed to switch to 8 MHz operation for reading of device ID.\n");
450 if (bus
->ops
->reset_timeout(dev
))
451 dev_warn(&dev
->dev
, "failed to reset potential timeout.");
453 ret
= ipack_device_read_id(dev
);
455 dev_err(&dev
->dev
, "error reading device id section.\n");
460 /* if the device supports 32 MHz operation, use it. */
461 if (dev
->speed_32mhz
) {
462 ret
= bus
->ops
->set_clockrate(dev
, 32);
464 dev_err(&dev
->dev
, "failed to switch to 32 MHz operation.\n");
467 ret
= device_register(&dev
->dev
);
476 EXPORT_SYMBOL_GPL(ipack_device_register
);
478 void ipack_device_unregister(struct ipack_device
*dev
)
480 device_unregister(&dev
->dev
);
482 EXPORT_SYMBOL_GPL(ipack_device_unregister
);
484 static int __init
ipack_init(void)
486 ida_init(&ipack_ida
);
487 return bus_register(&ipack_bus_type
);
490 static void __exit
ipack_exit(void)
492 bus_unregister(&ipack_bus_type
);
493 ida_destroy(&ipack_ida
);
496 module_init(ipack_init
);
497 module_exit(ipack_exit
);
499 MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>");
500 MODULE_LICENSE("GPL");
501 MODULE_DESCRIPTION("Industry-pack bus core");