1 // SPDX-License-Identifier: GPL-2.0-only
3 * Kontron PLD MFD core driver
5 * Copyright (c) 2010-2013 Kontron Europe GmbH
6 * Author: Michael Brunner <michael.brunner@kontron.com>
10 #include <linux/platform_device.h>
11 #include <linux/mfd/core.h>
12 #include <linux/mfd/kempld.h>
13 #include <linux/mod_devicetable.h>
14 #include <linux/module.h>
15 #include <linux/property.h>
16 #include <linux/dmi.h>
18 #include <linux/delay.h>
19 #include <linux/sysfs.h>
22 static char force_device_id
[MAX_ID_LEN
+ 1] = "";
23 module_param_string(force_device_id
, force_device_id
,
24 sizeof(force_device_id
), 0);
25 MODULE_PARM_DESC(force_device_id
, "Override detected product");
28 * Get hardware mutex to block firmware from accessing the pld.
29 * It is possible for the firmware may hold the mutex for an extended length of
30 * time. This function will block until access has been granted.
32 static void kempld_get_hardware_mutex(struct kempld_device_data
*pld
)
34 /* The mutex bit will read 1 until access has been granted */
35 while (ioread8(pld
->io_index
) & KEMPLD_MUTEX_KEY
)
36 usleep_range(1000, 3000);
39 static void kempld_release_hardware_mutex(struct kempld_device_data
*pld
)
41 /* The harware mutex is released when 1 is written to the mutex bit. */
42 iowrite8(KEMPLD_MUTEX_KEY
, pld
->io_index
);
45 static int kempld_get_info_generic(struct kempld_device_data
*pld
)
50 kempld_get_mutex(pld
);
52 version
= kempld_read16(pld
, KEMPLD_VERSION
);
53 spec
= kempld_read8(pld
, KEMPLD_SPEC
);
54 pld
->info
.buildnr
= kempld_read16(pld
, KEMPLD_BUILDNR
);
56 pld
->info
.minor
= KEMPLD_VERSION_GET_MINOR(version
);
57 pld
->info
.major
= KEMPLD_VERSION_GET_MAJOR(version
);
58 pld
->info
.number
= KEMPLD_VERSION_GET_NUMBER(version
);
59 pld
->info
.type
= KEMPLD_VERSION_GET_TYPE(version
);
62 pld
->info
.spec_minor
= 0;
63 pld
->info
.spec_major
= 1;
65 pld
->info
.spec_minor
= KEMPLD_SPEC_GET_MINOR(spec
);
66 pld
->info
.spec_major
= KEMPLD_SPEC_GET_MAJOR(spec
);
69 if (pld
->info
.spec_major
> 0)
70 pld
->feature_mask
= kempld_read16(pld
, KEMPLD_FEATURE
);
72 pld
->feature_mask
= 0;
74 kempld_release_mutex(pld
);
86 static const char *kempld_dev_names
[] = {
87 [KEMPLD_I2C
] = "kempld-i2c",
88 [KEMPLD_WDT
] = "kempld-wdt",
89 [KEMPLD_GPIO
] = "kempld-gpio",
90 [KEMPLD_UART
] = "kempld-uart",
93 #define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_dev_names)
95 static int kempld_register_cells_generic(struct kempld_device_data
*pld
)
97 struct mfd_cell devs
[KEMPLD_MAX_DEVS
] = {};
100 if (pld
->feature_mask
& KEMPLD_FEATURE_BIT_I2C
)
101 devs
[i
++].name
= kempld_dev_names
[KEMPLD_I2C
];
103 if (pld
->feature_mask
& KEMPLD_FEATURE_BIT_WATCHDOG
)
104 devs
[i
++].name
= kempld_dev_names
[KEMPLD_WDT
];
106 if (pld
->feature_mask
& KEMPLD_FEATURE_BIT_GPIO
)
107 devs
[i
++].name
= kempld_dev_names
[KEMPLD_GPIO
];
109 if (pld
->feature_mask
& KEMPLD_FEATURE_MASK_UART
)
110 devs
[i
++].name
= kempld_dev_names
[KEMPLD_UART
];
112 return mfd_add_devices(pld
->dev
, PLATFORM_DEVID_NONE
, devs
, i
, NULL
, 0, NULL
);
115 static struct resource kempld_ioresource
= {
116 .start
= KEMPLD_IOINDEX
,
117 .end
= KEMPLD_IODATA
,
118 .flags
= IORESOURCE_IO
,
121 static const struct kempld_platform_data kempld_platform_data_generic
= {
122 .pld_clock
= KEMPLD_CLK
,
123 .ioresource
= &kempld_ioresource
,
124 .get_hardware_mutex
= kempld_get_hardware_mutex
,
125 .release_hardware_mutex
= kempld_release_hardware_mutex
,
126 .get_info
= kempld_get_info_generic
,
127 .register_cells
= kempld_register_cells_generic
,
130 static struct platform_device
*kempld_pdev
;
132 static int kempld_create_platform_device(const struct kempld_platform_data
*pdata
)
134 const struct platform_device_info pdevinfo
= {
136 .id
= PLATFORM_DEVID_NONE
,
137 .res
= pdata
->ioresource
,
140 .size_data
= sizeof(*pdata
),
143 kempld_pdev
= platform_device_register_full(&pdevinfo
);
144 if (IS_ERR(kempld_pdev
))
145 return PTR_ERR(kempld_pdev
);
151 * kempld_read8 - read 8 bit register
152 * @pld: kempld_device_data structure describing the PLD
153 * @index: register index on the chip
155 * kempld_get_mutex must be called prior to calling this function.
157 u8
kempld_read8(struct kempld_device_data
*pld
, u8 index
)
159 iowrite8(index
, pld
->io_index
);
160 return ioread8(pld
->io_data
);
162 EXPORT_SYMBOL_GPL(kempld_read8
);
165 * kempld_write8 - write 8 bit register
166 * @pld: kempld_device_data structure describing the PLD
167 * @index: register index on the chip
168 * @data: new register value
170 * kempld_get_mutex must be called prior to calling this function.
172 void kempld_write8(struct kempld_device_data
*pld
, u8 index
, u8 data
)
174 iowrite8(index
, pld
->io_index
);
175 iowrite8(data
, pld
->io_data
);
177 EXPORT_SYMBOL_GPL(kempld_write8
);
180 * kempld_read16 - read 16 bit register
181 * @pld: kempld_device_data structure describing the PLD
182 * @index: register index on the chip
184 * kempld_get_mutex must be called prior to calling this function.
186 u16
kempld_read16(struct kempld_device_data
*pld
, u8 index
)
188 return kempld_read8(pld
, index
) | kempld_read8(pld
, index
+ 1) << 8;
190 EXPORT_SYMBOL_GPL(kempld_read16
);
193 * kempld_write16 - write 16 bit register
194 * @pld: kempld_device_data structure describing the PLD
195 * @index: register index on the chip
196 * @data: new register value
198 * kempld_get_mutex must be called prior to calling this function.
200 void kempld_write16(struct kempld_device_data
*pld
, u8 index
, u16 data
)
202 kempld_write8(pld
, index
, (u8
)data
);
203 kempld_write8(pld
, index
+ 1, (u8
)(data
>> 8));
205 EXPORT_SYMBOL_GPL(kempld_write16
);
208 * kempld_read32 - read 32 bit register
209 * @pld: kempld_device_data structure describing the PLD
210 * @index: register index on the chip
212 * kempld_get_mutex must be called prior to calling this function.
214 u32
kempld_read32(struct kempld_device_data
*pld
, u8 index
)
216 return kempld_read16(pld
, index
) | kempld_read16(pld
, index
+ 2) << 16;
218 EXPORT_SYMBOL_GPL(kempld_read32
);
221 * kempld_write32 - write 32 bit register
222 * @pld: kempld_device_data structure describing the PLD
223 * @index: register index on the chip
224 * @data: new register value
226 * kempld_get_mutex must be called prior to calling this function.
228 void kempld_write32(struct kempld_device_data
*pld
, u8 index
, u32 data
)
230 kempld_write16(pld
, index
, (u16
)data
);
231 kempld_write16(pld
, index
+ 2, (u16
)(data
>> 16));
233 EXPORT_SYMBOL_GPL(kempld_write32
);
236 * kempld_get_mutex - acquire PLD mutex
237 * @pld: kempld_device_data structure describing the PLD
239 void kempld_get_mutex(struct kempld_device_data
*pld
)
241 const struct kempld_platform_data
*pdata
= dev_get_platdata(pld
->dev
);
243 mutex_lock(&pld
->lock
);
244 pdata
->get_hardware_mutex(pld
);
246 EXPORT_SYMBOL_GPL(kempld_get_mutex
);
249 * kempld_release_mutex - release PLD mutex
250 * @pld: kempld_device_data structure describing the PLD
252 void kempld_release_mutex(struct kempld_device_data
*pld
)
254 const struct kempld_platform_data
*pdata
= dev_get_platdata(pld
->dev
);
256 pdata
->release_hardware_mutex(pld
);
257 mutex_unlock(&pld
->lock
);
259 EXPORT_SYMBOL_GPL(kempld_release_mutex
);
262 * kempld_get_info - update device specific information
263 * @pld: kempld_device_data structure describing the PLD
265 * This function calls the configured board specific kempld_get_info_XXXX
266 * function which is responsible for gathering information about the specific
267 * hardware. The information is then stored within the pld structure.
269 static int kempld_get_info(struct kempld_device_data
*pld
)
272 const struct kempld_platform_data
*pdata
= dev_get_platdata(pld
->dev
);
275 ret
= pdata
->get_info(pld
);
279 /* The Kontron PLD firmware version string has the following format:
282 * w: PLD number - 1 hex digit
283 * x: Major version - 1 alphanumerical digit (0-9A-V)
284 * y: Minor version - 1 alphanumerical digit (0-9A-V)
285 * zzzz: Build number - 4 zero padded hex digits */
287 if (pld
->info
.major
< 10)
288 major
= pld
->info
.major
+ '0';
290 major
= (pld
->info
.major
- 10) + 'A';
291 if (pld
->info
.minor
< 10)
292 minor
= pld
->info
.minor
+ '0';
294 minor
= (pld
->info
.minor
- 10) + 'A';
296 scnprintf(pld
->info
.version
, sizeof(pld
->info
.version
), "P%X%c%c.%04X",
297 pld
->info
.number
, major
, minor
, pld
->info
.buildnr
);
303 * kempld_register_cells - register cell drivers
305 * This function registers cell drivers for the detected hardware by calling
306 * the configured kempld_register_cells_XXXX function which is responsible
307 * to detect and register the needed cell drivers.
309 static int kempld_register_cells(struct kempld_device_data
*pld
)
311 const struct kempld_platform_data
*pdata
= dev_get_platdata(pld
->dev
);
313 return pdata
->register_cells(pld
);
316 static const char *kempld_get_type_string(struct kempld_device_data
*pld
)
318 const char *version_type
;
320 switch (pld
->info
.type
) {
322 version_type
= "release";
325 version_type
= "debug";
328 version_type
= "custom";
331 version_type
= "unspecified";
338 static ssize_t
pld_version_show(struct device
*dev
,
339 struct device_attribute
*attr
, char *buf
)
341 struct kempld_device_data
*pld
= dev_get_drvdata(dev
);
343 return sysfs_emit(buf
, "%s\n", pld
->info
.version
);
346 static ssize_t
pld_specification_show(struct device
*dev
,
347 struct device_attribute
*attr
, char *buf
)
349 struct kempld_device_data
*pld
= dev_get_drvdata(dev
);
351 return sysfs_emit(buf
, "%d.%d\n", pld
->info
.spec_major
, pld
->info
.spec_minor
);
354 static ssize_t
pld_type_show(struct device
*dev
,
355 struct device_attribute
*attr
, char *buf
)
357 struct kempld_device_data
*pld
= dev_get_drvdata(dev
);
359 return sysfs_emit(buf
, "%s\n", kempld_get_type_string(pld
));
362 static DEVICE_ATTR_RO(pld_version
);
363 static DEVICE_ATTR_RO(pld_specification
);
364 static DEVICE_ATTR_RO(pld_type
);
366 static struct attribute
*pld_attrs
[] = {
367 &dev_attr_pld_version
.attr
,
368 &dev_attr_pld_specification
.attr
,
369 &dev_attr_pld_type
.attr
,
372 ATTRIBUTE_GROUPS(pld
);
374 static int kempld_detect_device(struct kempld_device_data
*pld
)
379 mutex_lock(&pld
->lock
);
381 /* Check for empty IO space */
382 index_reg
= ioread8(pld
->io_index
);
383 if (index_reg
== 0xff && ioread8(pld
->io_data
) == 0xff) {
384 mutex_unlock(&pld
->lock
);
388 /* Release hardware mutex if acquired */
389 if (!(index_reg
& KEMPLD_MUTEX_KEY
)) {
390 iowrite8(KEMPLD_MUTEX_KEY
, pld
->io_index
);
391 /* PXT and COMe-cPC2 boards may require a second release */
392 iowrite8(KEMPLD_MUTEX_KEY
, pld
->io_index
);
395 mutex_unlock(&pld
->lock
);
397 ret
= kempld_get_info(pld
);
401 dev_info(pld
->dev
, "Found Kontron PLD - %s (%s), spec %d.%d\n",
402 pld
->info
.version
, kempld_get_type_string(pld
),
403 pld
->info
.spec_major
, pld
->info
.spec_minor
);
405 return kempld_register_cells(pld
);
408 static int kempld_probe(struct platform_device
*pdev
)
410 const struct kempld_platform_data
*pdata
;
411 struct device
*dev
= &pdev
->dev
;
412 struct kempld_device_data
*pld
;
413 struct resource
*ioport
;
416 if (IS_ERR_OR_NULL(kempld_pdev
)) {
418 * No kempld_pdev device has been registered in kempld_init,
419 * so we seem to be probing an ACPI platform device.
421 pdata
= device_get_match_data(dev
);
425 ret
= platform_device_add_data(pdev
, pdata
, sizeof(*pdata
));
428 } else if (kempld_pdev
== pdev
) {
429 pdata
= dev_get_platdata(dev
);
432 * The platform device we are probing is not the one we
433 * registered in kempld_init using the DMI table, so this one
435 * As we can only probe one - abort here and use the DMI
438 dev_notice(dev
, "platform device exists - not using ACPI\n");
442 pld
= devm_kzalloc(dev
, sizeof(*pld
), GFP_KERNEL
);
446 ioport
= platform_get_resource(pdev
, IORESOURCE_IO
, 0);
450 pld
->io_base
= devm_ioport_map(dev
, ioport
->start
,
451 resource_size(ioport
));
455 pld
->io_index
= pld
->io_base
;
456 pld
->io_data
= pld
->io_base
+ 1;
457 pld
->pld_clock
= pdata
->pld_clock
;
460 mutex_init(&pld
->lock
);
461 platform_set_drvdata(pdev
, pld
);
463 return kempld_detect_device(pld
);
466 static void kempld_remove(struct platform_device
*pdev
)
468 struct kempld_device_data
*pld
= platform_get_drvdata(pdev
);
469 const struct kempld_platform_data
*pdata
= dev_get_platdata(pld
->dev
);
471 mfd_remove_devices(&pdev
->dev
);
472 pdata
->release_hardware_mutex(pld
);
475 static const struct acpi_device_id kempld_acpi_table
[] = {
476 { "KEM0000", (kernel_ulong_t
)&kempld_platform_data_generic
},
477 { "KEM0001", (kernel_ulong_t
)&kempld_platform_data_generic
},
480 MODULE_DEVICE_TABLE(acpi
, kempld_acpi_table
);
482 static struct platform_driver kempld_driver
= {
485 .acpi_match_table
= kempld_acpi_table
,
486 .dev_groups
= pld_groups
,
488 .probe
= kempld_probe
,
489 .remove
= kempld_remove
,
492 static const struct dmi_system_id kempld_dmi_table
[] __initconst
= {
496 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
497 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bBD"),
502 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
503 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bBL6"),
508 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
509 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bDV7"),
514 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
515 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bHL6"),
520 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
521 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bKL6"),
526 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
527 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bSL6"),
532 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
533 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cAL"),
538 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
539 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cBL6"),
544 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
545 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cBW6"),
550 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
551 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bIP2"),
556 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
557 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bIP6"),
562 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
563 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cDV7"),
568 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
569 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cHL6"),
574 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
575 DMI_MATCH(DMI_BOARD_NAME
, "ETXexpress-SC T2"),
580 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
581 DMI_MATCH(DMI_BOARD_NAME
, "ETXe-SC T2"),
586 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
587 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bSC2"),
592 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
593 DMI_MATCH(DMI_BOARD_NAME
, "ETXexpress-SC T6"),
598 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
599 DMI_MATCH(DMI_BOARD_NAME
, "ETXe-SC T6"),
604 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
605 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bSC6"),
610 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
611 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cKL6"),
616 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
617 DMI_MATCH(DMI_BOARD_NAME
, "ETXexpress-PC"),
622 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
623 DMI_MATCH(DMI_BOARD_NAME
, "COMe-bPC2"),
628 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
629 DMI_MATCH(DMI_BOARD_NAME
, "PXT"),
634 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
635 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cSL6"),
640 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
641 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cBT"),
646 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
647 DMI_MATCH(DMI_BIOS_VERSION
, "FRI2"),
652 DMI_MATCH(DMI_PRODUCT_NAME
, "Fish River Island II"),
657 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
658 DMI_MATCH(DMI_BOARD_NAME
, "KBox A-203"),
663 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
664 DMI_MATCH(DMI_BOARD_NAME
, "COMe-m4AL"),
669 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
670 DMI_MATCH(DMI_BOARD_NAME
, "COMe-mAL10"),
675 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
676 DMI_MATCH(DMI_BOARD_NAME
, "mITX-APL"),
681 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
682 DMI_MATCH(DMI_BOARD_NAME
, "ETX-OH"),
687 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
688 DMI_MATCH(DMI_BOARD_NAME
, "COMe-mBT"),
693 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
694 DMI_MATCH(DMI_BOARD_NAME
, "nanoETXexpress-TT"),
699 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
700 DMI_MATCH(DMI_BOARD_NAME
, "nETXe-TT"),
705 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
706 DMI_MATCH(DMI_BOARD_NAME
, "COMe-mTT"),
711 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
712 DMI_MATCH(DMI_BOARD_NAME
, "COMe-mCT"),
717 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
718 DMI_MATCH(DMI_BOARD_NAME
, "pITX-APL"),
723 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
724 DMI_MATCH(DMI_BOARD_NAME
, "SMARC-sXAL"),
729 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
730 DMI_MATCH(DMI_BOARD_NAME
, "SMARC-sXA4"),
735 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
736 DMI_MATCH(DMI_BOARD_NAME
, "microETXexpress-DC"),
741 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
742 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cDC2"),
747 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
748 DMI_MATCH(DMI_BOARD_NAME
, "microETXexpress-PC"),
753 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
754 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cPC2"),
759 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
760 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cCT6"),
765 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
766 DMI_MATCH(DMI_BOARD_NAME
, "COMe-cTH6"),
771 DMI_MATCH(DMI_BOARD_VENDOR
, "Kontron"),
772 DMI_MATCH(DMI_BOARD_NAME
, "Qseven-Q7AL"),
777 MODULE_DEVICE_TABLE(dmi
, kempld_dmi_table
);
779 static int __init
kempld_init(void)
781 const struct dmi_system_id
*id
;
784 for (id
= dmi_first_match(kempld_dmi_table
); id
; id
= dmi_first_match(id
+ 1)) {
785 /* Check, if user asked for the exact device ID match */
786 if (force_device_id
[0] && !strstr(id
->ident
, force_device_id
))
789 ret
= kempld_create_platform_device(&kempld_platform_data_generic
);
798 return platform_driver_register(&kempld_driver
);
801 static void __exit
kempld_exit(void)
803 platform_device_unregister(kempld_pdev
);
804 platform_driver_unregister(&kempld_driver
);
807 module_init(kempld_init
);
808 module_exit(kempld_exit
);
810 MODULE_DESCRIPTION("KEM PLD Core Driver");
811 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
812 MODULE_LICENSE("GPL");
813 MODULE_ALIAS("platform:kempld-core");