0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/platform_device.h>
0010 #include <linux/mfd/core.h>
0011 #include <linux/mfd/kempld.h>
0012 #include <linux/module.h>
0013 #include <linux/dmi.h>
0014 #include <linux/io.h>
0015 #include <linux/delay.h>
0016 #include <linux/acpi.h>
0017
0018 #define MAX_ID_LEN 4
0019 static char force_device_id[MAX_ID_LEN + 1] = "";
0020 module_param_string(force_device_id, force_device_id,
0021 sizeof(force_device_id), 0);
0022 MODULE_PARM_DESC(force_device_id, "Override detected product");
0023
0024
0025
0026
0027
0028
0029 static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
0030 {
0031
0032 while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
0033 usleep_range(1000, 3000);
0034 }
0035
0036 static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
0037 {
0038
0039 iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
0040 }
0041
0042 static int kempld_get_info_generic(struct kempld_device_data *pld)
0043 {
0044 u16 version;
0045 u8 spec;
0046
0047 kempld_get_mutex(pld);
0048
0049 version = kempld_read16(pld, KEMPLD_VERSION);
0050 spec = kempld_read8(pld, KEMPLD_SPEC);
0051 pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR);
0052
0053 pld->info.minor = KEMPLD_VERSION_GET_MINOR(version);
0054 pld->info.major = KEMPLD_VERSION_GET_MAJOR(version);
0055 pld->info.number = KEMPLD_VERSION_GET_NUMBER(version);
0056 pld->info.type = KEMPLD_VERSION_GET_TYPE(version);
0057
0058 if (spec == 0xff) {
0059 pld->info.spec_minor = 0;
0060 pld->info.spec_major = 1;
0061 } else {
0062 pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec);
0063 pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec);
0064 }
0065
0066 if (pld->info.spec_major > 0)
0067 pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE);
0068 else
0069 pld->feature_mask = 0;
0070
0071 kempld_release_mutex(pld);
0072
0073 return 0;
0074 }
0075
0076 enum kempld_cells {
0077 KEMPLD_I2C = 0,
0078 KEMPLD_WDT,
0079 KEMPLD_GPIO,
0080 KEMPLD_UART,
0081 };
0082
0083 static const char *kempld_dev_names[] = {
0084 [KEMPLD_I2C] = "kempld-i2c",
0085 [KEMPLD_WDT] = "kempld-wdt",
0086 [KEMPLD_GPIO] = "kempld-gpio",
0087 [KEMPLD_UART] = "kempld-uart",
0088 };
0089
0090 #define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_dev_names)
0091
0092 static int kempld_register_cells_generic(struct kempld_device_data *pld)
0093 {
0094 struct mfd_cell devs[KEMPLD_MAX_DEVS] = {};
0095 int i = 0;
0096
0097 if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C)
0098 devs[i++].name = kempld_dev_names[KEMPLD_I2C];
0099
0100 if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG)
0101 devs[i++].name = kempld_dev_names[KEMPLD_WDT];
0102
0103 if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO)
0104 devs[i++].name = kempld_dev_names[KEMPLD_GPIO];
0105
0106 if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
0107 devs[i++].name = kempld_dev_names[KEMPLD_UART];
0108
0109 return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
0110 }
0111
0112 static struct resource kempld_ioresource = {
0113 .start = KEMPLD_IOINDEX,
0114 .end = KEMPLD_IODATA,
0115 .flags = IORESOURCE_IO,
0116 };
0117
0118 static const struct kempld_platform_data kempld_platform_data_generic = {
0119 .pld_clock = KEMPLD_CLK,
0120 .ioresource = &kempld_ioresource,
0121 .get_hardware_mutex = kempld_get_hardware_mutex,
0122 .release_hardware_mutex = kempld_release_hardware_mutex,
0123 .get_info = kempld_get_info_generic,
0124 .register_cells = kempld_register_cells_generic,
0125 };
0126
0127 static struct platform_device *kempld_pdev;
0128
0129 static int kempld_create_platform_device(const struct dmi_system_id *id)
0130 {
0131 const struct kempld_platform_data *pdata = id->driver_data;
0132 int ret;
0133
0134 kempld_pdev = platform_device_alloc("kempld", -1);
0135 if (!kempld_pdev)
0136 return -ENOMEM;
0137
0138 ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata));
0139 if (ret)
0140 goto err;
0141
0142 ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1);
0143 if (ret)
0144 goto err;
0145
0146 ret = platform_device_add(kempld_pdev);
0147 if (ret)
0148 goto err;
0149
0150 return 0;
0151 err:
0152 platform_device_put(kempld_pdev);
0153 return ret;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163 u8 kempld_read8(struct kempld_device_data *pld, u8 index)
0164 {
0165 iowrite8(index, pld->io_index);
0166 return ioread8(pld->io_data);
0167 }
0168 EXPORT_SYMBOL_GPL(kempld_read8);
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data)
0179 {
0180 iowrite8(index, pld->io_index);
0181 iowrite8(data, pld->io_data);
0182 }
0183 EXPORT_SYMBOL_GPL(kempld_write8);
0184
0185
0186
0187
0188
0189
0190
0191
0192 u16 kempld_read16(struct kempld_device_data *pld, u8 index)
0193 {
0194 return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8;
0195 }
0196 EXPORT_SYMBOL_GPL(kempld_read16);
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data)
0207 {
0208 kempld_write8(pld, index, (u8)data);
0209 kempld_write8(pld, index + 1, (u8)(data >> 8));
0210 }
0211 EXPORT_SYMBOL_GPL(kempld_write16);
0212
0213
0214
0215
0216
0217
0218
0219
0220 u32 kempld_read32(struct kempld_device_data *pld, u8 index)
0221 {
0222 return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16;
0223 }
0224 EXPORT_SYMBOL_GPL(kempld_read32);
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data)
0235 {
0236 kempld_write16(pld, index, (u16)data);
0237 kempld_write16(pld, index + 2, (u16)(data >> 16));
0238 }
0239 EXPORT_SYMBOL_GPL(kempld_write32);
0240
0241
0242
0243
0244
0245 void kempld_get_mutex(struct kempld_device_data *pld)
0246 {
0247 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
0248
0249 mutex_lock(&pld->lock);
0250 pdata->get_hardware_mutex(pld);
0251 }
0252 EXPORT_SYMBOL_GPL(kempld_get_mutex);
0253
0254
0255
0256
0257
0258 void kempld_release_mutex(struct kempld_device_data *pld)
0259 {
0260 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
0261
0262 pdata->release_hardware_mutex(pld);
0263 mutex_unlock(&pld->lock);
0264 }
0265 EXPORT_SYMBOL_GPL(kempld_release_mutex);
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static int kempld_get_info(struct kempld_device_data *pld)
0276 {
0277 int ret;
0278 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
0279 char major, minor;
0280
0281 ret = pdata->get_info(pld);
0282 if (ret)
0283 return ret;
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293 if (pld->info.major < 10)
0294 major = pld->info.major + '0';
0295 else
0296 major = (pld->info.major - 10) + 'A';
0297 if (pld->info.minor < 10)
0298 minor = pld->info.minor + '0';
0299 else
0300 minor = (pld->info.minor - 10) + 'A';
0301
0302 ret = scnprintf(pld->info.version, sizeof(pld->info.version),
0303 "P%X%c%c.%04X", pld->info.number, major, minor,
0304 pld->info.buildnr);
0305 if (ret < 0)
0306 return ret;
0307
0308 return 0;
0309 }
0310
0311
0312
0313
0314
0315
0316
0317
0318 static int kempld_register_cells(struct kempld_device_data *pld)
0319 {
0320 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
0321
0322 return pdata->register_cells(pld);
0323 }
0324
0325 static const char *kempld_get_type_string(struct kempld_device_data *pld)
0326 {
0327 const char *version_type;
0328
0329 switch (pld->info.type) {
0330 case 0:
0331 version_type = "release";
0332 break;
0333 case 1:
0334 version_type = "debug";
0335 break;
0336 case 2:
0337 version_type = "custom";
0338 break;
0339 default:
0340 version_type = "unspecified";
0341 break;
0342 }
0343
0344 return version_type;
0345 }
0346
0347 static ssize_t pld_version_show(struct device *dev,
0348 struct device_attribute *attr, char *buf)
0349 {
0350 struct kempld_device_data *pld = dev_get_drvdata(dev);
0351
0352 return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version);
0353 }
0354
0355 static ssize_t pld_specification_show(struct device *dev,
0356 struct device_attribute *attr, char *buf)
0357 {
0358 struct kempld_device_data *pld = dev_get_drvdata(dev);
0359
0360 return scnprintf(buf, PAGE_SIZE, "%d.%d\n", pld->info.spec_major,
0361 pld->info.spec_minor);
0362 }
0363
0364 static ssize_t pld_type_show(struct device *dev,
0365 struct device_attribute *attr, char *buf)
0366 {
0367 struct kempld_device_data *pld = dev_get_drvdata(dev);
0368
0369 return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld));
0370 }
0371
0372 static DEVICE_ATTR_RO(pld_version);
0373 static DEVICE_ATTR_RO(pld_specification);
0374 static DEVICE_ATTR_RO(pld_type);
0375
0376 static struct attribute *pld_attributes[] = {
0377 &dev_attr_pld_version.attr,
0378 &dev_attr_pld_specification.attr,
0379 &dev_attr_pld_type.attr,
0380 NULL
0381 };
0382
0383 static const struct attribute_group pld_attr_group = {
0384 .attrs = pld_attributes,
0385 };
0386
0387 static int kempld_detect_device(struct kempld_device_data *pld)
0388 {
0389 u8 index_reg;
0390 int ret;
0391
0392 mutex_lock(&pld->lock);
0393
0394
0395 index_reg = ioread8(pld->io_index);
0396 if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) {
0397 mutex_unlock(&pld->lock);
0398 return -ENODEV;
0399 }
0400
0401
0402 if (!(index_reg & KEMPLD_MUTEX_KEY)) {
0403 iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
0404
0405 iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
0406 }
0407
0408 mutex_unlock(&pld->lock);
0409
0410 ret = kempld_get_info(pld);
0411 if (ret)
0412 return ret;
0413
0414 dev_info(pld->dev, "Found Kontron PLD - %s (%s), spec %d.%d\n",
0415 pld->info.version, kempld_get_type_string(pld),
0416 pld->info.spec_major, pld->info.spec_minor);
0417
0418 ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group);
0419 if (ret)
0420 return ret;
0421
0422 ret = kempld_register_cells(pld);
0423 if (ret)
0424 sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
0425
0426 return ret;
0427 }
0428
0429 #ifdef CONFIG_ACPI
0430 static int kempld_get_acpi_data(struct platform_device *pdev)
0431 {
0432 struct list_head resource_list;
0433 struct resource *resources;
0434 struct resource_entry *rentry;
0435 struct device *dev = &pdev->dev;
0436 struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
0437 const struct kempld_platform_data *pdata;
0438 int ret;
0439 int count;
0440
0441 pdata = acpi_device_get_match_data(dev);
0442 ret = platform_device_add_data(pdev, pdata,
0443 sizeof(struct kempld_platform_data));
0444 if (ret)
0445 return ret;
0446
0447 INIT_LIST_HEAD(&resource_list);
0448 ret = acpi_dev_get_resources(acpi_dev, &resource_list, NULL, NULL);
0449 if (ret < 0)
0450 goto out;
0451
0452 count = ret;
0453
0454 if (count == 0) {
0455 ret = platform_device_add_resources(pdev, pdata->ioresource, 1);
0456 goto out;
0457 }
0458
0459 resources = devm_kcalloc(&acpi_dev->dev, count, sizeof(*resources),
0460 GFP_KERNEL);
0461 if (!resources) {
0462 ret = -ENOMEM;
0463 goto out;
0464 }
0465
0466 count = 0;
0467 list_for_each_entry(rentry, &resource_list, node) {
0468 memcpy(&resources[count], rentry->res,
0469 sizeof(*resources));
0470 count++;
0471 }
0472 ret = platform_device_add_resources(pdev, resources, count);
0473
0474 out:
0475 acpi_dev_free_resource_list(&resource_list);
0476
0477 return ret;
0478 }
0479 #else
0480 static int kempld_get_acpi_data(struct platform_device *pdev)
0481 {
0482 return -ENODEV;
0483 }
0484 #endif
0485
0486 static int kempld_probe(struct platform_device *pdev)
0487 {
0488 const struct kempld_platform_data *pdata;
0489 struct device *dev = &pdev->dev;
0490 struct kempld_device_data *pld;
0491 struct resource *ioport;
0492 int ret;
0493
0494 if (kempld_pdev == NULL) {
0495
0496
0497
0498
0499 ret = kempld_get_acpi_data(pdev);
0500 if (ret)
0501 return ret;
0502 } else if (kempld_pdev != pdev) {
0503
0504
0505
0506
0507
0508
0509
0510 dev_notice(dev, "platform device exists - not using ACPI\n");
0511 return -ENODEV;
0512 }
0513 pdata = dev_get_platdata(dev);
0514
0515 pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
0516 if (!pld)
0517 return -ENOMEM;
0518
0519 ioport = platform_get_resource(pdev, IORESOURCE_IO, 0);
0520 if (!ioport)
0521 return -EINVAL;
0522
0523 pld->io_base = devm_ioport_map(dev, ioport->start,
0524 resource_size(ioport));
0525 if (!pld->io_base)
0526 return -ENOMEM;
0527
0528 pld->io_index = pld->io_base;
0529 pld->io_data = pld->io_base + 1;
0530 pld->pld_clock = pdata->pld_clock;
0531 pld->dev = dev;
0532
0533 mutex_init(&pld->lock);
0534 platform_set_drvdata(pdev, pld);
0535
0536 return kempld_detect_device(pld);
0537 }
0538
0539 static int kempld_remove(struct platform_device *pdev)
0540 {
0541 struct kempld_device_data *pld = platform_get_drvdata(pdev);
0542 const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
0543
0544 sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
0545
0546 mfd_remove_devices(&pdev->dev);
0547 pdata->release_hardware_mutex(pld);
0548
0549 return 0;
0550 }
0551
0552 #ifdef CONFIG_ACPI
0553 static const struct acpi_device_id kempld_acpi_table[] = {
0554 { "KEM0000", (kernel_ulong_t)&kempld_platform_data_generic },
0555 { "KEM0001", (kernel_ulong_t)&kempld_platform_data_generic },
0556 {}
0557 };
0558 MODULE_DEVICE_TABLE(acpi, kempld_acpi_table);
0559 #endif
0560
0561 static struct platform_driver kempld_driver = {
0562 .driver = {
0563 .name = "kempld",
0564 .acpi_match_table = ACPI_PTR(kempld_acpi_table),
0565 },
0566 .probe = kempld_probe,
0567 .remove = kempld_remove,
0568 };
0569
0570 static const struct dmi_system_id kempld_dmi_table[] __initconst = {
0571 {
0572 .ident = "BBD6",
0573 .matches = {
0574 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0575 DMI_MATCH(DMI_BOARD_NAME, "COMe-bBD"),
0576 },
0577 .driver_data = (void *)&kempld_platform_data_generic,
0578 .callback = kempld_create_platform_device,
0579 }, {
0580 .ident = "BBL6",
0581 .matches = {
0582 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0583 DMI_MATCH(DMI_BOARD_NAME, "COMe-bBL6"),
0584 },
0585 .driver_data = (void *)&kempld_platform_data_generic,
0586 .callback = kempld_create_platform_device,
0587 }, {
0588 .ident = "BDV7",
0589 .matches = {
0590 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0591 DMI_MATCH(DMI_BOARD_NAME, "COMe-bDV7"),
0592 },
0593 .driver_data = (void *)&kempld_platform_data_generic,
0594 .callback = kempld_create_platform_device,
0595 }, {
0596 .ident = "BHL6",
0597 .matches = {
0598 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0599 DMI_MATCH(DMI_BOARD_NAME, "COMe-bHL6"),
0600 },
0601 .driver_data = (void *)&kempld_platform_data_generic,
0602 .callback = kempld_create_platform_device,
0603 }, {
0604 .ident = "BKL6",
0605 .matches = {
0606 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0607 DMI_MATCH(DMI_BOARD_NAME, "COMe-bKL6"),
0608 },
0609 .driver_data = (void *)&kempld_platform_data_generic,
0610 .callback = kempld_create_platform_device,
0611 }, {
0612 .ident = "BSL6",
0613 .matches = {
0614 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0615 DMI_MATCH(DMI_BOARD_NAME, "COMe-bSL6"),
0616 },
0617 .driver_data = (void *)&kempld_platform_data_generic,
0618 .callback = kempld_create_platform_device,
0619 }, {
0620 .ident = "CAL6",
0621 .matches = {
0622 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0623 DMI_MATCH(DMI_BOARD_NAME, "COMe-cAL"),
0624 },
0625 .driver_data = (void *)&kempld_platform_data_generic,
0626 .callback = kempld_create_platform_device,
0627 }, {
0628 .ident = "CBL6",
0629 .matches = {
0630 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0631 DMI_MATCH(DMI_BOARD_NAME, "COMe-cBL6"),
0632 },
0633 .driver_data = (void *)&kempld_platform_data_generic,
0634 .callback = kempld_create_platform_device,
0635 }, {
0636 .ident = "CBW6",
0637 .matches = {
0638 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0639 DMI_MATCH(DMI_BOARD_NAME, "COMe-cBW6"),
0640 },
0641 .driver_data = (void *)&kempld_platform_data_generic,
0642 .callback = kempld_create_platform_device,
0643 }, {
0644 .ident = "CCR2",
0645 .matches = {
0646 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0647 DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"),
0648 },
0649 .driver_data = (void *)&kempld_platform_data_generic,
0650 .callback = kempld_create_platform_device,
0651 }, {
0652 .ident = "CCR6",
0653 .matches = {
0654 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0655 DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"),
0656 },
0657 .driver_data = (void *)&kempld_platform_data_generic,
0658 .callback = kempld_create_platform_device,
0659 }, {
0660 .ident = "CDV7",
0661 .matches = {
0662 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0663 DMI_MATCH(DMI_BOARD_NAME, "COMe-cDV7"),
0664 },
0665 .driver_data = (void *)&kempld_platform_data_generic,
0666 .callback = kempld_create_platform_device,
0667 }, {
0668 .ident = "CHL6",
0669 .matches = {
0670 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0671 DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"),
0672 },
0673 .driver_data = (void *)&kempld_platform_data_generic,
0674 .callback = kempld_create_platform_device,
0675 }, {
0676 .ident = "CHR2",
0677 .matches = {
0678 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0679 DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"),
0680 },
0681 .driver_data = (void *)&kempld_platform_data_generic,
0682 .callback = kempld_create_platform_device,
0683 }, {
0684 .ident = "CHR2",
0685 .matches = {
0686 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0687 DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"),
0688 },
0689 .driver_data = (void *)&kempld_platform_data_generic,
0690 .callback = kempld_create_platform_device,
0691 }, {
0692 .ident = "CHR2",
0693 .matches = {
0694 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0695 DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"),
0696 },
0697 .driver_data = (void *)&kempld_platform_data_generic,
0698 .callback = kempld_create_platform_device,
0699 }, {
0700 .ident = "CHR6",
0701 .matches = {
0702 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0703 DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"),
0704 },
0705 .driver_data = (void *)&kempld_platform_data_generic,
0706 .callback = kempld_create_platform_device,
0707 }, {
0708 .ident = "CHR6",
0709 .matches = {
0710 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0711 DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"),
0712 },
0713 .driver_data = (void *)&kempld_platform_data_generic,
0714 .callback = kempld_create_platform_device,
0715 }, {
0716 .ident = "CHR6",
0717 .matches = {
0718 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0719 DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"),
0720 },
0721 .driver_data = (void *)&kempld_platform_data_generic,
0722 .callback = kempld_create_platform_device,
0723 }, {
0724 .ident = "CKL6",
0725 .matches = {
0726 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0727 DMI_MATCH(DMI_BOARD_NAME, "COMe-cKL6"),
0728 },
0729 .driver_data = (void *)&kempld_platform_data_generic,
0730 .callback = kempld_create_platform_device,
0731 }, {
0732 .ident = "CNTG",
0733 .matches = {
0734 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0735 DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"),
0736 },
0737 .driver_data = (void *)&kempld_platform_data_generic,
0738 .callback = kempld_create_platform_device,
0739 }, {
0740 .ident = "CNTG",
0741 .matches = {
0742 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0743 DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"),
0744 },
0745 .driver_data = (void *)&kempld_platform_data_generic,
0746 .callback = kempld_create_platform_device,
0747 }, {
0748 .ident = "CNTX",
0749 .matches = {
0750 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0751 DMI_MATCH(DMI_BOARD_NAME, "PXT"),
0752 },
0753 .driver_data = (void *)&kempld_platform_data_generic,
0754 .callback = kempld_create_platform_device,
0755 }, {
0756 .ident = "CSL6",
0757 .matches = {
0758 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0759 DMI_MATCH(DMI_BOARD_NAME, "COMe-cSL6"),
0760 },
0761 .driver_data = (void *)&kempld_platform_data_generic,
0762 .callback = kempld_create_platform_device,
0763 }, {
0764 .ident = "CVV6",
0765 .matches = {
0766 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0767 DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"),
0768 },
0769 .driver_data = (void *)&kempld_platform_data_generic,
0770 .callback = kempld_create_platform_device,
0771 }, {
0772 .ident = "FRI2",
0773 .matches = {
0774 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0775 DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
0776 },
0777 .driver_data = (void *)&kempld_platform_data_generic,
0778 .callback = kempld_create_platform_device,
0779 }, {
0780 .ident = "FRI2",
0781 .matches = {
0782 DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
0783 },
0784 .driver_data = (void *)&kempld_platform_data_generic,
0785 .callback = kempld_create_platform_device,
0786 }, {
0787 .ident = "A203",
0788 .matches = {
0789 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0790 DMI_MATCH(DMI_BOARD_NAME, "KBox A-203"),
0791 },
0792 .driver_data = (void *)&kempld_platform_data_generic,
0793 .callback = kempld_create_platform_device,
0794 }, {
0795 .ident = "M4A1",
0796 .matches = {
0797 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0798 DMI_MATCH(DMI_BOARD_NAME, "COMe-m4AL"),
0799 },
0800 .driver_data = (void *)&kempld_platform_data_generic,
0801 .callback = kempld_create_platform_device,
0802 }, {
0803 .ident = "MAL1",
0804 .matches = {
0805 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0806 DMI_MATCH(DMI_BOARD_NAME, "COMe-mAL10"),
0807 },
0808 .driver_data = (void *)&kempld_platform_data_generic,
0809 .callback = kempld_create_platform_device,
0810 }, {
0811 .ident = "MAPL",
0812 .matches = {
0813 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0814 DMI_MATCH(DMI_BOARD_NAME, "mITX-APL"),
0815 },
0816 .driver_data = (void *)&kempld_platform_data_generic,
0817 .callback = kempld_create_platform_device,
0818 }, {
0819 .ident = "MBR1",
0820 .matches = {
0821 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0822 DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"),
0823 },
0824 .driver_data = (void *)&kempld_platform_data_generic,
0825 .callback = kempld_create_platform_device,
0826 }, {
0827 .ident = "MVV1",
0828 .matches = {
0829 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0830 DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"),
0831 },
0832 .driver_data = (void *)&kempld_platform_data_generic,
0833 .callback = kempld_create_platform_device,
0834 }, {
0835 .ident = "NTC1",
0836 .matches = {
0837 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0838 DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
0839 },
0840 .driver_data = (void *)&kempld_platform_data_generic,
0841 .callback = kempld_create_platform_device,
0842 }, {
0843 .ident = "NTC1",
0844 .matches = {
0845 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0846 DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"),
0847 },
0848 .driver_data = (void *)&kempld_platform_data_generic,
0849 .callback = kempld_create_platform_device,
0850 }, {
0851 .ident = "NTC1",
0852 .matches = {
0853 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0854 DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
0855 },
0856 .driver_data = (void *)&kempld_platform_data_generic,
0857 .callback = kempld_create_platform_device,
0858 }, {
0859 .ident = "NUP1",
0860 .matches = {
0861 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0862 DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"),
0863 },
0864 .driver_data = (void *)&kempld_platform_data_generic,
0865 .callback = kempld_create_platform_device,
0866 }, {
0867 .ident = "PAPL",
0868 .matches = {
0869 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0870 DMI_MATCH(DMI_BOARD_NAME, "pITX-APL"),
0871 },
0872 .driver_data = (void *)&kempld_platform_data_generic,
0873 .callback = kempld_create_platform_device,
0874 }, {
0875 .ident = "SXAL",
0876 .matches = {
0877 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0878 DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXAL"),
0879 },
0880 .driver_data = (void *)&kempld_platform_data_generic,
0881 .callback = kempld_create_platform_device,
0882 }, {
0883 .ident = "SXAL4",
0884 .matches = {
0885 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0886 DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXA4"),
0887 },
0888 .driver_data = (void *)&kempld_platform_data_generic,
0889 .callback = kempld_create_platform_device,
0890 }, {
0891 .ident = "UNP1",
0892 .matches = {
0893 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0894 DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"),
0895 },
0896 .driver_data = (void *)&kempld_platform_data_generic,
0897 .callback = kempld_create_platform_device,
0898 }, {
0899 .ident = "UNP1",
0900 .matches = {
0901 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0902 DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"),
0903 },
0904 .driver_data = (void *)&kempld_platform_data_generic,
0905 .callback = kempld_create_platform_device,
0906 }, {
0907 .ident = "UNTG",
0908 .matches = {
0909 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0910 DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"),
0911 },
0912 .driver_data = (void *)&kempld_platform_data_generic,
0913 .callback = kempld_create_platform_device,
0914 }, {
0915 .ident = "UNTG",
0916 .matches = {
0917 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0918 DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"),
0919 },
0920 .driver_data = (void *)&kempld_platform_data_generic,
0921 .callback = kempld_create_platform_device,
0922 }, {
0923 .ident = "UUP6",
0924 .matches = {
0925 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0926 DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"),
0927 },
0928 .driver_data = (void *)&kempld_platform_data_generic,
0929 .callback = kempld_create_platform_device,
0930 }, {
0931 .ident = "UTH6",
0932 .matches = {
0933 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0934 DMI_MATCH(DMI_BOARD_NAME, "COMe-cTH6"),
0935 },
0936 .driver_data = (void *)&kempld_platform_data_generic,
0937 .callback = kempld_create_platform_device,
0938 }, {
0939 .ident = "Q7AL",
0940 .matches = {
0941 DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
0942 DMI_MATCH(DMI_BOARD_NAME, "Qseven-Q7AL"),
0943 },
0944 .driver_data = (void *)&kempld_platform_data_generic,
0945 .callback = kempld_create_platform_device,
0946 },
0947 {}
0948 };
0949 MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
0950
0951 static int __init kempld_init(void)
0952 {
0953 const struct dmi_system_id *id;
0954
0955 if (force_device_id[0]) {
0956 for (id = kempld_dmi_table;
0957 id->matches[0].slot != DMI_NONE; id++)
0958 if (strstr(id->ident, force_device_id))
0959 if (id->callback && !id->callback(id))
0960 break;
0961 if (id->matches[0].slot == DMI_NONE)
0962 return -ENODEV;
0963 } else {
0964 dmi_check_system(kempld_dmi_table);
0965 }
0966
0967 return platform_driver_register(&kempld_driver);
0968 }
0969
0970 static void __exit kempld_exit(void)
0971 {
0972 if (kempld_pdev)
0973 platform_device_unregister(kempld_pdev);
0974
0975 platform_driver_unregister(&kempld_driver);
0976 }
0977
0978 module_init(kempld_init);
0979 module_exit(kempld_exit);
0980
0981 MODULE_DESCRIPTION("KEM PLD Core Driver");
0982 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
0983 MODULE_LICENSE("GPL");
0984 MODULE_ALIAS("platform:kempld-core");