Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.14-rc2 813 lines 20 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Kontron PLD MFD core driver 4 * 5 * Copyright (c) 2010-2013 Kontron Europe GmbH 6 * Author: Michael Brunner <michael.brunner@kontron.com> 7 */ 8 9#include <linux/err.h> 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> 17#include <linux/io.h> 18#include <linux/delay.h> 19#include <linux/sysfs.h> 20 21#define MAX_ID_LEN 4 22static char force_device_id[MAX_ID_LEN + 1] = ""; 23module_param_string(force_device_id, force_device_id, 24 sizeof(force_device_id), 0); 25MODULE_PARM_DESC(force_device_id, "Override detected product"); 26 27/* 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. 31 */ 32static void kempld_get_hardware_mutex(struct kempld_device_data *pld) 33{ 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); 37} 38 39static void kempld_release_hardware_mutex(struct kempld_device_data *pld) 40{ 41 /* The harware mutex is released when 1 is written to the mutex bit. */ 42 iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); 43} 44 45static int kempld_get_info_generic(struct kempld_device_data *pld) 46{ 47 u16 version; 48 u8 spec; 49 50 kempld_get_mutex(pld); 51 52 version = kempld_read16(pld, KEMPLD_VERSION); 53 spec = kempld_read8(pld, KEMPLD_SPEC); 54 pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR); 55 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); 60 61 if (spec == 0xff) { 62 pld->info.spec_minor = 0; 63 pld->info.spec_major = 1; 64 } else { 65 pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec); 66 pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec); 67 } 68 69 if (pld->info.spec_major > 0) 70 pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE); 71 else 72 pld->feature_mask = 0; 73 74 kempld_release_mutex(pld); 75 76 return 0; 77} 78 79enum kempld_cells { 80 KEMPLD_I2C = 0, 81 KEMPLD_WDT, 82 KEMPLD_GPIO, 83 KEMPLD_UART, 84}; 85 86static 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", 91}; 92 93#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_dev_names) 94 95static int kempld_register_cells_generic(struct kempld_device_data *pld) 96{ 97 struct mfd_cell devs[KEMPLD_MAX_DEVS] = {}; 98 int i = 0; 99 100 if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C) 101 devs[i++].name = kempld_dev_names[KEMPLD_I2C]; 102 103 if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG) 104 devs[i++].name = kempld_dev_names[KEMPLD_WDT]; 105 106 if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO) 107 devs[i++].name = kempld_dev_names[KEMPLD_GPIO]; 108 109 if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART) 110 devs[i++].name = kempld_dev_names[KEMPLD_UART]; 111 112 return mfd_add_devices(pld->dev, PLATFORM_DEVID_NONE, devs, i, NULL, 0, NULL); 113} 114 115static struct resource kempld_ioresource = { 116 .start = KEMPLD_IOINDEX, 117 .end = KEMPLD_IODATA, 118 .flags = IORESOURCE_IO, 119}; 120 121static 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, 128}; 129 130static struct platform_device *kempld_pdev; 131 132static int kempld_create_platform_device(const struct kempld_platform_data *pdata) 133{ 134 const struct platform_device_info pdevinfo = { 135 .name = "kempld", 136 .id = PLATFORM_DEVID_NONE, 137 .res = pdata->ioresource, 138 .num_res = 1, 139 .data = pdata, 140 .size_data = sizeof(*pdata), 141 }; 142 143 kempld_pdev = platform_device_register_full(&pdevinfo); 144 if (IS_ERR(kempld_pdev)) 145 return PTR_ERR(kempld_pdev); 146 147 return 0; 148} 149 150/** 151 * kempld_read8 - read 8 bit register 152 * @pld: kempld_device_data structure describing the PLD 153 * @index: register index on the chip 154 * 155 * kempld_get_mutex must be called prior to calling this function. 156 */ 157u8 kempld_read8(struct kempld_device_data *pld, u8 index) 158{ 159 iowrite8(index, pld->io_index); 160 return ioread8(pld->io_data); 161} 162EXPORT_SYMBOL_GPL(kempld_read8); 163 164/** 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 169 * 170 * kempld_get_mutex must be called prior to calling this function. 171 */ 172void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data) 173{ 174 iowrite8(index, pld->io_index); 175 iowrite8(data, pld->io_data); 176} 177EXPORT_SYMBOL_GPL(kempld_write8); 178 179/** 180 * kempld_read16 - read 16 bit register 181 * @pld: kempld_device_data structure describing the PLD 182 * @index: register index on the chip 183 * 184 * kempld_get_mutex must be called prior to calling this function. 185 */ 186u16 kempld_read16(struct kempld_device_data *pld, u8 index) 187{ 188 return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8; 189} 190EXPORT_SYMBOL_GPL(kempld_read16); 191 192/** 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 197 * 198 * kempld_get_mutex must be called prior to calling this function. 199 */ 200void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data) 201{ 202 kempld_write8(pld, index, (u8)data); 203 kempld_write8(pld, index + 1, (u8)(data >> 8)); 204} 205EXPORT_SYMBOL_GPL(kempld_write16); 206 207/** 208 * kempld_read32 - read 32 bit register 209 * @pld: kempld_device_data structure describing the PLD 210 * @index: register index on the chip 211 * 212 * kempld_get_mutex must be called prior to calling this function. 213 */ 214u32 kempld_read32(struct kempld_device_data *pld, u8 index) 215{ 216 return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16; 217} 218EXPORT_SYMBOL_GPL(kempld_read32); 219 220/** 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 225 * 226 * kempld_get_mutex must be called prior to calling this function. 227 */ 228void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data) 229{ 230 kempld_write16(pld, index, (u16)data); 231 kempld_write16(pld, index + 2, (u16)(data >> 16)); 232} 233EXPORT_SYMBOL_GPL(kempld_write32); 234 235/** 236 * kempld_get_mutex - acquire PLD mutex 237 * @pld: kempld_device_data structure describing the PLD 238 */ 239void kempld_get_mutex(struct kempld_device_data *pld) 240{ 241 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 242 243 mutex_lock(&pld->lock); 244 pdata->get_hardware_mutex(pld); 245} 246EXPORT_SYMBOL_GPL(kempld_get_mutex); 247 248/** 249 * kempld_release_mutex - release PLD mutex 250 * @pld: kempld_device_data structure describing the PLD 251 */ 252void kempld_release_mutex(struct kempld_device_data *pld) 253{ 254 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 255 256 pdata->release_hardware_mutex(pld); 257 mutex_unlock(&pld->lock); 258} 259EXPORT_SYMBOL_GPL(kempld_release_mutex); 260 261/** 262 * kempld_get_info - update device specific information 263 * @pld: kempld_device_data structure describing the PLD 264 * 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. 268 */ 269static int kempld_get_info(struct kempld_device_data *pld) 270{ 271 int ret; 272 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 273 char major, minor; 274 275 ret = pdata->get_info(pld); 276 if (ret) 277 return ret; 278 279 /* The Kontron PLD firmware version string has the following format: 280 * Pwxy.zzzz 281 * P: Fixed 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 */ 286 287 if (pld->info.major < 10) 288 major = pld->info.major + '0'; 289 else 290 major = (pld->info.major - 10) + 'A'; 291 if (pld->info.minor < 10) 292 minor = pld->info.minor + '0'; 293 else 294 minor = (pld->info.minor - 10) + 'A'; 295 296 scnprintf(pld->info.version, sizeof(pld->info.version), "P%X%c%c.%04X", 297 pld->info.number, major, minor, pld->info.buildnr); 298 299 return 0; 300} 301 302/* 303 * kempld_register_cells - register cell drivers 304 * 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. 308 */ 309static int kempld_register_cells(struct kempld_device_data *pld) 310{ 311 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 312 313 return pdata->register_cells(pld); 314} 315 316static const char *kempld_get_type_string(struct kempld_device_data *pld) 317{ 318 const char *version_type; 319 320 switch (pld->info.type) { 321 case 0: 322 version_type = "release"; 323 break; 324 case 1: 325 version_type = "debug"; 326 break; 327 case 2: 328 version_type = "custom"; 329 break; 330 default: 331 version_type = "unspecified"; 332 break; 333 } 334 335 return version_type; 336} 337 338static ssize_t pld_version_show(struct device *dev, 339 struct device_attribute *attr, char *buf) 340{ 341 struct kempld_device_data *pld = dev_get_drvdata(dev); 342 343 return sysfs_emit(buf, "%s\n", pld->info.version); 344} 345 346static ssize_t pld_specification_show(struct device *dev, 347 struct device_attribute *attr, char *buf) 348{ 349 struct kempld_device_data *pld = dev_get_drvdata(dev); 350 351 return sysfs_emit(buf, "%d.%d\n", pld->info.spec_major, pld->info.spec_minor); 352} 353 354static ssize_t pld_type_show(struct device *dev, 355 struct device_attribute *attr, char *buf) 356{ 357 struct kempld_device_data *pld = dev_get_drvdata(dev); 358 359 return sysfs_emit(buf, "%s\n", kempld_get_type_string(pld)); 360} 361 362static DEVICE_ATTR_RO(pld_version); 363static DEVICE_ATTR_RO(pld_specification); 364static DEVICE_ATTR_RO(pld_type); 365 366static struct attribute *pld_attrs[] = { 367 &dev_attr_pld_version.attr, 368 &dev_attr_pld_specification.attr, 369 &dev_attr_pld_type.attr, 370 NULL 371}; 372ATTRIBUTE_GROUPS(pld); 373 374static int kempld_detect_device(struct kempld_device_data *pld) 375{ 376 u8 index_reg; 377 int ret; 378 379 mutex_lock(&pld->lock); 380 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); 385 return -ENODEV; 386 } 387 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); 393 } 394 395 mutex_unlock(&pld->lock); 396 397 ret = kempld_get_info(pld); 398 if (ret) 399 return ret; 400 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); 404 405 return kempld_register_cells(pld); 406} 407 408static int kempld_probe(struct platform_device *pdev) 409{ 410 const struct kempld_platform_data *pdata; 411 struct device *dev = &pdev->dev; 412 struct kempld_device_data *pld; 413 struct resource *ioport; 414 int ret; 415 416 if (IS_ERR_OR_NULL(kempld_pdev)) { 417 /* 418 * No kempld_pdev device has been registered in kempld_init, 419 * so we seem to be probing an ACPI platform device. 420 */ 421 pdata = device_get_match_data(dev); 422 if (!pdata) 423 return -ENODEV; 424 425 ret = platform_device_add_data(pdev, pdata, sizeof(*pdata)); 426 if (ret) 427 return ret; 428 } else if (kempld_pdev == pdev) { 429 pdata = dev_get_platdata(dev); 430 } else { 431 /* 432 * The platform device we are probing is not the one we 433 * registered in kempld_init using the DMI table, so this one 434 * comes from ACPI. 435 * As we can only probe one - abort here and use the DMI 436 * based one instead. 437 */ 438 dev_notice(dev, "platform device exists - not using ACPI\n"); 439 return -ENODEV; 440 } 441 442 pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); 443 if (!pld) 444 return -ENOMEM; 445 446 ioport = platform_get_resource(pdev, IORESOURCE_IO, 0); 447 if (!ioport) 448 return -EINVAL; 449 450 pld->io_base = devm_ioport_map(dev, ioport->start, 451 resource_size(ioport)); 452 if (!pld->io_base) 453 return -ENOMEM; 454 455 pld->io_index = pld->io_base; 456 pld->io_data = pld->io_base + 1; 457 pld->pld_clock = pdata->pld_clock; 458 pld->dev = dev; 459 460 mutex_init(&pld->lock); 461 platform_set_drvdata(pdev, pld); 462 463 return kempld_detect_device(pld); 464} 465 466static void kempld_remove(struct platform_device *pdev) 467{ 468 struct kempld_device_data *pld = platform_get_drvdata(pdev); 469 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 470 471 mfd_remove_devices(&pdev->dev); 472 pdata->release_hardware_mutex(pld); 473} 474 475static 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 }, 478 {} 479}; 480MODULE_DEVICE_TABLE(acpi, kempld_acpi_table); 481 482static struct platform_driver kempld_driver = { 483 .driver = { 484 .name = "kempld", 485 .acpi_match_table = kempld_acpi_table, 486 .dev_groups = pld_groups, 487 }, 488 .probe = kempld_probe, 489 .remove = kempld_remove, 490}; 491 492static const struct dmi_system_id kempld_dmi_table[] __initconst = { 493 { 494 .ident = "BBD6", 495 .matches = { 496 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 497 DMI_MATCH(DMI_BOARD_NAME, "COMe-bBD"), 498 }, 499 }, { 500 .ident = "BBL6", 501 .matches = { 502 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 503 DMI_MATCH(DMI_BOARD_NAME, "COMe-bBL6"), 504 }, 505 }, { 506 .ident = "BDV7", 507 .matches = { 508 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 509 DMI_MATCH(DMI_BOARD_NAME, "COMe-bDV7"), 510 }, 511 }, { 512 .ident = "BHL6", 513 .matches = { 514 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 515 DMI_MATCH(DMI_BOARD_NAME, "COMe-bHL6"), 516 }, 517 }, { 518 .ident = "BKL6", 519 .matches = { 520 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 521 DMI_MATCH(DMI_BOARD_NAME, "COMe-bKL6"), 522 }, 523 }, { 524 .ident = "BSL6", 525 .matches = { 526 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 527 DMI_MATCH(DMI_BOARD_NAME, "COMe-bSL6"), 528 }, 529 }, { 530 .ident = "CAL6", 531 .matches = { 532 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 533 DMI_MATCH(DMI_BOARD_NAME, "COMe-cAL"), 534 }, 535 }, { 536 .ident = "CBL6", 537 .matches = { 538 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 539 DMI_MATCH(DMI_BOARD_NAME, "COMe-cBL6"), 540 }, 541 }, { 542 .ident = "CBW6", 543 .matches = { 544 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 545 DMI_MATCH(DMI_BOARD_NAME, "COMe-cBW6"), 546 }, 547 }, { 548 .ident = "CCR2", 549 .matches = { 550 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 551 DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"), 552 }, 553 }, { 554 .ident = "CCR6", 555 .matches = { 556 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 557 DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"), 558 }, 559 }, { 560 .ident = "CDV7", 561 .matches = { 562 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 563 DMI_MATCH(DMI_BOARD_NAME, "COMe-cDV7"), 564 }, 565 }, { 566 .ident = "CHL6", 567 .matches = { 568 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 569 DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"), 570 }, 571 }, { 572 .ident = "CHR2", 573 .matches = { 574 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 575 DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"), 576 }, 577 }, { 578 .ident = "CHR2", 579 .matches = { 580 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 581 DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"), 582 }, 583 }, { 584 .ident = "CHR2", 585 .matches = { 586 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 587 DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"), 588 }, 589 }, { 590 .ident = "CHR6", 591 .matches = { 592 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 593 DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"), 594 }, 595 }, { 596 .ident = "CHR6", 597 .matches = { 598 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 599 DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"), 600 }, 601 }, { 602 .ident = "CHR6", 603 .matches = { 604 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 605 DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"), 606 }, 607 }, { 608 .ident = "CKL6", 609 .matches = { 610 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 611 DMI_MATCH(DMI_BOARD_NAME, "COMe-cKL6"), 612 }, 613 }, { 614 .ident = "CNTG", 615 .matches = { 616 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 617 DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"), 618 }, 619 }, { 620 .ident = "CNTG", 621 .matches = { 622 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 623 DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"), 624 }, 625 }, { 626 .ident = "CNTX", 627 .matches = { 628 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 629 DMI_MATCH(DMI_BOARD_NAME, "PXT"), 630 }, 631 }, { 632 .ident = "CSL6", 633 .matches = { 634 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 635 DMI_MATCH(DMI_BOARD_NAME, "COMe-cSL6"), 636 }, 637 }, { 638 .ident = "CVV6", 639 .matches = { 640 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 641 DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"), 642 }, 643 }, { 644 .ident = "FRI2", 645 .matches = { 646 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 647 DMI_MATCH(DMI_BIOS_VERSION, "FRI2"), 648 }, 649 }, { 650 .ident = "FRI2", 651 .matches = { 652 DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"), 653 }, 654 }, { 655 .ident = "A203", 656 .matches = { 657 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 658 DMI_MATCH(DMI_BOARD_NAME, "KBox A-203"), 659 }, 660 }, { 661 .ident = "M4A1", 662 .matches = { 663 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 664 DMI_MATCH(DMI_BOARD_NAME, "COMe-m4AL"), 665 }, 666 }, { 667 .ident = "MAL1", 668 .matches = { 669 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 670 DMI_MATCH(DMI_BOARD_NAME, "COMe-mAL10"), 671 }, 672 }, { 673 .ident = "MAPL", 674 .matches = { 675 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 676 DMI_MATCH(DMI_BOARD_NAME, "mITX-APL"), 677 }, 678 }, { 679 .ident = "MBR1", 680 .matches = { 681 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 682 DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"), 683 }, 684 }, { 685 .ident = "MVV1", 686 .matches = { 687 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 688 DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"), 689 }, 690 }, { 691 .ident = "NTC1", 692 .matches = { 693 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 694 DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"), 695 }, 696 }, { 697 .ident = "NTC1", 698 .matches = { 699 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 700 DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"), 701 }, 702 }, { 703 .ident = "NTC1", 704 .matches = { 705 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 706 DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"), 707 }, 708 }, { 709 .ident = "NUP1", 710 .matches = { 711 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 712 DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"), 713 }, 714 }, { 715 .ident = "PAPL", 716 .matches = { 717 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 718 DMI_MATCH(DMI_BOARD_NAME, "pITX-APL"), 719 }, 720 }, { 721 .ident = "SXAL", 722 .matches = { 723 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 724 DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXAL"), 725 }, 726 }, { 727 .ident = "SXAL4", 728 .matches = { 729 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 730 DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXA4"), 731 }, 732 }, { 733 .ident = "UNP1", 734 .matches = { 735 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 736 DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"), 737 }, 738 }, { 739 .ident = "UNP1", 740 .matches = { 741 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 742 DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"), 743 }, 744 }, { 745 .ident = "UNTG", 746 .matches = { 747 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 748 DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"), 749 }, 750 }, { 751 .ident = "UNTG", 752 .matches = { 753 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 754 DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"), 755 }, 756 }, { 757 .ident = "UUP6", 758 .matches = { 759 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 760 DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"), 761 }, 762 }, { 763 .ident = "UTH6", 764 .matches = { 765 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 766 DMI_MATCH(DMI_BOARD_NAME, "COMe-cTH6"), 767 }, 768 }, { 769 .ident = "Q7AL", 770 .matches = { 771 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), 772 DMI_MATCH(DMI_BOARD_NAME, "Qseven-Q7AL"), 773 }, 774 }, 775 {} 776}; 777MODULE_DEVICE_TABLE(dmi, kempld_dmi_table); 778 779static int __init kempld_init(void) 780{ 781 const struct dmi_system_id *id; 782 int ret = -ENODEV; 783 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)) 787 continue; 788 789 ret = kempld_create_platform_device(&kempld_platform_data_generic); 790 if (ret) 791 continue; 792 793 break; 794 } 795 if (ret) 796 return ret; 797 798 return platform_driver_register(&kempld_driver); 799} 800 801static void __exit kempld_exit(void) 802{ 803 platform_device_unregister(kempld_pdev); 804 platform_driver_unregister(&kempld_driver); 805} 806 807module_init(kempld_init); 808module_exit(kempld_exit); 809 810MODULE_DESCRIPTION("KEM PLD Core Driver"); 811MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>"); 812MODULE_LICENSE("GPL"); 813MODULE_ALIAS("platform:kempld-core");