1 // SPDX-License-Identifier: GPL-2.0-only
3 * Industry-pack bus support functions.
5 * Copyright (C) 2011-2012 CERN (www.cern.ch)
6 * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/idr.h>
13 #include <linux/ipack.h>
15 #define to_ipack_dev(device) container_of(device, struct ipack_device, dev)
16 #define to_ipack_driver(drv) container_of_const(drv, struct ipack_driver, driver)
18 static DEFINE_IDA(ipack_ida
);
20 static void ipack_device_release(struct device
*dev
)
22 struct ipack_device
*device
= to_ipack_dev(dev
);
24 device
->release(device
);
27 static inline const struct ipack_device_id
*
28 ipack_match_one_device(const struct ipack_device_id
*id
,
29 const struct ipack_device
*device
)
31 if ((id
->format
== IPACK_ANY_FORMAT
||
32 id
->format
== device
->id_format
) &&
33 (id
->vendor
== IPACK_ANY_ID
|| id
->vendor
== device
->id_vendor
) &&
34 (id
->device
== IPACK_ANY_ID
|| id
->device
== device
->id_device
))
39 static const struct ipack_device_id
*
40 ipack_match_id(const struct ipack_device_id
*ids
, struct ipack_device
*idev
)
43 while (ids
->vendor
|| ids
->device
) {
44 if (ipack_match_one_device(ids
, idev
))
52 static int ipack_bus_match(struct device
*dev
, const struct device_driver
*drv
)
54 struct ipack_device
*idev
= to_ipack_dev(dev
);
55 const struct ipack_driver
*idrv
= to_ipack_driver(drv
);
56 const struct ipack_device_id
*found_id
;
58 found_id
= ipack_match_id(idrv
->id_table
, idev
);
59 return found_id
? 1 : 0;
62 static int ipack_bus_probe(struct device
*device
)
64 struct ipack_device
*dev
= to_ipack_dev(device
);
65 struct ipack_driver
*drv
= to_ipack_driver(device
->driver
);
67 return drv
->ops
->probe(dev
);
70 static void ipack_bus_remove(struct device
*device
)
72 struct ipack_device
*dev
= to_ipack_dev(device
);
73 struct ipack_driver
*drv
= to_ipack_driver(device
->driver
);
76 drv
->ops
->remove(dev
);
79 static int ipack_uevent(const struct device
*dev
, struct kobj_uevent_env
*env
)
81 const struct ipack_device
*idev
;
86 idev
= to_ipack_dev(dev
);
88 if (add_uevent_var(env
,
89 "MODALIAS=ipack:f%02Xv%08Xd%08X", idev
->id_format
,
90 idev
->id_vendor
, idev
->id_device
))
96 #define ipack_device_attr(field, format_string) \
98 field##_show(struct device *dev, struct device_attribute *attr, \
101 struct ipack_device *idev = to_ipack_dev(dev); \
102 return sprintf(buf, format_string, idev->field); \
105 static ssize_t
id_show(struct device
*dev
,
106 struct device_attribute
*attr
, char *buf
)
108 unsigned int i
, c
, l
, s
;
109 struct ipack_device
*idev
= to_ipack_dev(dev
);
112 switch (idev
->id_format
) {
113 case IPACK_ID_VERSION_1
:
114 l
= 0x7; s
= 1; break;
115 case IPACK_ID_VERSION_2
:
116 l
= 0xf; s
= 2; break;
121 for (i
= 0; i
< idev
->id_avail
; i
++) {
125 else if ((i
& s
) == 0)
128 sprintf(&buf
[c
], "%02x", idev
->id
[i
]);
136 id_vendor_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
138 struct ipack_device
*idev
= to_ipack_dev(dev
);
139 switch (idev
->id_format
) {
140 case IPACK_ID_VERSION_1
:
141 return sprintf(buf
, "0x%02x\n", idev
->id_vendor
);
142 case IPACK_ID_VERSION_2
:
143 return sprintf(buf
, "0x%06x\n", idev
->id_vendor
);
150 id_device_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
152 struct ipack_device
*idev
= to_ipack_dev(dev
);
153 switch (idev
->id_format
) {
154 case IPACK_ID_VERSION_1
:
155 return sprintf(buf
, "0x%02x\n", idev
->id_device
);
156 case IPACK_ID_VERSION_2
:
157 return sprintf(buf
, "0x%04x\n", idev
->id_device
);
163 static ssize_t
modalias_show(struct device
*dev
, struct device_attribute
*attr
,
166 struct ipack_device
*idev
= to_ipack_dev(dev
);
168 return sprintf(buf
, "ipac:f%02Xv%08Xd%08X", idev
->id_format
,
169 idev
->id_vendor
, idev
->id_device
);
172 ipack_device_attr(id_format
, "0x%hhx\n");
174 static DEVICE_ATTR_RO(id
);
175 static DEVICE_ATTR_RO(id_device
);
176 static DEVICE_ATTR_RO(id_format
);
177 static DEVICE_ATTR_RO(id_vendor
);
178 static DEVICE_ATTR_RO(modalias
);
180 static struct attribute
*ipack_attrs
[] = {
182 &dev_attr_id_device
.attr
,
183 &dev_attr_id_format
.attr
,
184 &dev_attr_id_vendor
.attr
,
185 &dev_attr_modalias
.attr
,
188 ATTRIBUTE_GROUPS(ipack
);
190 static const struct bus_type ipack_bus_type
= {
192 .probe
= ipack_bus_probe
,
193 .match
= ipack_bus_match
,
194 .remove
= ipack_bus_remove
,
195 .dev_groups
= ipack_groups
,
196 .uevent
= ipack_uevent
,
199 struct ipack_bus_device
*ipack_bus_register(struct device
*parent
, int slots
,
200 const struct ipack_bus_ops
*ops
,
201 struct module
*owner
)
204 struct ipack_bus_device
*bus
;
206 bus
= kzalloc(sizeof(*bus
), GFP_KERNEL
);
210 bus_nr
= ida_alloc(&ipack_ida
, GFP_KERNEL
);
216 bus
->bus_nr
= bus_nr
;
217 bus
->parent
= parent
;
223 EXPORT_SYMBOL_GPL(ipack_bus_register
);
225 static int ipack_unregister_bus_member(struct device
*dev
, void *data
)
227 struct ipack_device
*idev
= to_ipack_dev(dev
);
228 struct ipack_bus_device
*bus
= data
;
230 if (idev
->bus
== bus
)
231 ipack_device_del(idev
);
236 int ipack_bus_unregister(struct ipack_bus_device
*bus
)
238 bus_for_each_dev(&ipack_bus_type
, NULL
, bus
,
239 ipack_unregister_bus_member
);
240 ida_free(&ipack_ida
, bus
->bus_nr
);
244 EXPORT_SYMBOL_GPL(ipack_bus_unregister
);
246 int ipack_driver_register(struct ipack_driver
*edrv
, struct module
*owner
,
249 if (!edrv
->ops
->probe
)
252 edrv
->driver
.owner
= owner
;
253 edrv
->driver
.name
= name
;
254 edrv
->driver
.bus
= &ipack_bus_type
;
255 return driver_register(&edrv
->driver
);
257 EXPORT_SYMBOL_GPL(ipack_driver_register
);
259 void ipack_driver_unregister(struct ipack_driver
*edrv
)
261 driver_unregister(&edrv
->driver
);
263 EXPORT_SYMBOL_GPL(ipack_driver_unregister
);
265 static u16
ipack_crc_byte(u16 crc
, u8 c
)
270 for (i
= 0; i
< 8; i
++)
271 crc
= (crc
<< 1) ^ ((crc
& 0x8000) ? 0x1021 : 0);
276 * The algorithm in lib/crc-ccitt.c does not seem to apply since it uses the
277 * opposite bit ordering.
279 static u8
ipack_calc_crc1(struct ipack_device
*dev
)
286 for (i
= 0; i
< dev
->id_avail
; i
++) {
287 c
= (i
!= 11) ? dev
->id
[i
] : 0;
288 crc
= ipack_crc_byte(crc
, c
);
294 static u16
ipack_calc_crc2(struct ipack_device
*dev
)
301 for (i
= 0; i
< dev
->id_avail
; i
++) {
302 c
= ((i
!= 0x18) && (i
!= 0x19)) ? dev
->id
[i
] : 0;
303 crc
= ipack_crc_byte(crc
, c
);
309 static void ipack_parse_id1(struct ipack_device
*dev
)
314 dev
->id_vendor
= id
[4];
315 dev
->id_device
= id
[5];
317 dev
->speed_32mhz
= (id
[7] == 'H');
318 crc
= ipack_calc_crc1(dev
);
319 dev
->id_crc_correct
= (crc
== id
[11]);
320 if (!dev
->id_crc_correct
) {
321 dev_warn(&dev
->dev
, "ID CRC invalid found 0x%x, expected 0x%x.\n",
326 static void ipack_parse_id2(struct ipack_device
*dev
)
328 __be16
*id
= (__be16
*) dev
->id
;
331 dev
->id_vendor
= ((be16_to_cpu(id
[3]) & 0xff) << 16)
332 + be16_to_cpu(id
[4]);
333 dev
->id_device
= be16_to_cpu(id
[5]);
334 flags
= be16_to_cpu(id
[10]);
335 dev
->speed_8mhz
= !!(flags
& 2);
336 dev
->speed_32mhz
= !!(flags
& 4);
337 crc
= ipack_calc_crc2(dev
);
338 dev
->id_crc_correct
= (crc
== be16_to_cpu(id
[12]));
339 if (!dev
->id_crc_correct
) {
340 dev_warn(&dev
->dev
, "ID CRC invalid found 0x%x, expected 0x%x.\n",
345 static int ipack_device_read_id(struct ipack_device
*dev
)
351 idmem
= ioremap(dev
->region
[IPACK_ID_SPACE
].start
,
352 dev
->region
[IPACK_ID_SPACE
].size
);
354 dev_err(&dev
->dev
, "error mapping memory\n");
358 /* Determine ID PROM Data Format. If we find the ids "IPAC" or "IPAH"
359 * we are dealing with a IndustryPack format 1 device. If we detect
360 * "VITA4 " (16 bit big endian formatted) we are dealing with a
361 * IndustryPack format 2 device */
362 if ((ioread8(idmem
+ 1) == 'I') &&
363 (ioread8(idmem
+ 3) == 'P') &&
364 (ioread8(idmem
+ 5) == 'A') &&
365 ((ioread8(idmem
+ 7) == 'C') ||
366 (ioread8(idmem
+ 7) == 'H'))) {
367 dev
->id_format
= IPACK_ID_VERSION_1
;
368 dev
->id_avail
= ioread8(idmem
+ 0x15);
369 if ((dev
->id_avail
< 0x0c) || (dev
->id_avail
> 0x40)) {
370 dev_warn(&dev
->dev
, "invalid id size");
371 dev
->id_avail
= 0x0c;
373 } else if ((ioread8(idmem
+ 0) == 'I') &&
374 (ioread8(idmem
+ 1) == 'V') &&
375 (ioread8(idmem
+ 2) == 'A') &&
376 (ioread8(idmem
+ 3) == 'T') &&
377 (ioread8(idmem
+ 4) == ' ') &&
378 (ioread8(idmem
+ 5) == '4')) {
379 dev
->id_format
= IPACK_ID_VERSION_2
;
380 dev
->id_avail
= ioread16be(idmem
+ 0x16);
381 if ((dev
->id_avail
< 0x1a) || (dev
->id_avail
> 0x40)) {
382 dev_warn(&dev
->dev
, "invalid id size");
383 dev
->id_avail
= 0x1a;
386 dev
->id_format
= IPACK_ID_VERSION_INVALID
;
390 if (!dev
->id_avail
) {
395 /* Obtain the amount of memory required to store a copy of the complete
397 dev
->id
= kmalloc(dev
->id_avail
, GFP_KERNEL
);
402 for (i
= 0; i
< dev
->id_avail
; i
++) {
403 if (dev
->id_format
== IPACK_ID_VERSION_1
)
404 dev
->id
[i
] = ioread8(idmem
+ (i
<< 1) + 1);
406 dev
->id
[i
] = ioread8(idmem
+ i
);
409 /* now we can finally work with the copy */
410 switch (dev
->id_format
) {
411 case IPACK_ID_VERSION_1
:
412 ipack_parse_id1(dev
);
414 case IPACK_ID_VERSION_2
:
415 ipack_parse_id2(dev
);
425 int ipack_device_init(struct ipack_device
*dev
)
429 dev
->dev
.bus
= &ipack_bus_type
;
430 dev
->dev
.release
= ipack_device_release
;
431 dev
->dev
.parent
= dev
->bus
->parent
;
432 ret
= dev_set_name(&dev
->dev
,
433 "ipack-dev.%u.%u", dev
->bus
->bus_nr
, dev
->slot
);
437 device_initialize(&dev
->dev
);
439 if (dev
->bus
->ops
->set_clockrate(dev
, 8))
440 dev_warn(&dev
->dev
, "failed to switch to 8 MHz operation for reading of device ID.\n");
441 if (dev
->bus
->ops
->reset_timeout(dev
))
442 dev_warn(&dev
->dev
, "failed to reset potential timeout.");
444 ret
= ipack_device_read_id(dev
);
446 dev_err(&dev
->dev
, "error reading device id section.\n");
450 /* if the device supports 32 MHz operation, use it. */
451 if (dev
->speed_32mhz
) {
452 ret
= dev
->bus
->ops
->set_clockrate(dev
, 32);
454 dev_err(&dev
->dev
, "failed to switch to 32 MHz operation.\n");
459 EXPORT_SYMBOL_GPL(ipack_device_init
);
461 int ipack_device_add(struct ipack_device
*dev
)
463 return device_add(&dev
->dev
);
465 EXPORT_SYMBOL_GPL(ipack_device_add
);
467 void ipack_device_del(struct ipack_device
*dev
)
469 device_del(&dev
->dev
);
470 ipack_put_device(dev
);
472 EXPORT_SYMBOL_GPL(ipack_device_del
);
474 void ipack_get_device(struct ipack_device
*dev
)
476 get_device(&dev
->dev
);
478 EXPORT_SYMBOL_GPL(ipack_get_device
);
480 void ipack_put_device(struct ipack_device
*dev
)
482 put_device(&dev
->dev
);
484 EXPORT_SYMBOL_GPL(ipack_put_device
);
486 static int __init
ipack_init(void)
488 ida_init(&ipack_ida
);
489 return bus_register(&ipack_bus_type
);
492 static void __exit
ipack_exit(void)
494 bus_unregister(&ipack_bus_type
);
495 ida_destroy(&ipack_ida
);
498 module_init(ipack_init
);
499 module_exit(ipack_exit
);
501 MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>");
502 MODULE_LICENSE("GPL");
503 MODULE_DESCRIPTION("Industry-pack bus core");