kempld-core.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  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 <[email protected]>
  7. */
  8. #include <linux/platform_device.h>
  9. #include <linux/mfd/core.h>
  10. #include <linux/mfd/kempld.h>
  11. #include <linux/module.h>
  12. #include <linux/dmi.h>
  13. #include <linux/io.h>
  14. #include <linux/delay.h>
  15. #include <linux/acpi.h>
  16. #define MAX_ID_LEN 4
  17. static char force_device_id[MAX_ID_LEN + 1] = "";
  18. module_param_string(force_device_id, force_device_id,
  19. sizeof(force_device_id), 0);
  20. MODULE_PARM_DESC(force_device_id, "Override detected product");
  21. /*
  22. * Get hardware mutex to block firmware from accessing the pld.
  23. * It is possible for the firmware may hold the mutex for an extended length of
  24. * time. This function will block until access has been granted.
  25. */
  26. static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
  27. {
  28. /* The mutex bit will read 1 until access has been granted */
  29. while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
  30. usleep_range(1000, 3000);
  31. }
  32. static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
  33. {
  34. /* The harware mutex is released when 1 is written to the mutex bit. */
  35. iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
  36. }
  37. static int kempld_get_info_generic(struct kempld_device_data *pld)
  38. {
  39. u16 version;
  40. u8 spec;
  41. kempld_get_mutex(pld);
  42. version = kempld_read16(pld, KEMPLD_VERSION);
  43. spec = kempld_read8(pld, KEMPLD_SPEC);
  44. pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR);
  45. pld->info.minor = KEMPLD_VERSION_GET_MINOR(version);
  46. pld->info.major = KEMPLD_VERSION_GET_MAJOR(version);
  47. pld->info.number = KEMPLD_VERSION_GET_NUMBER(version);
  48. pld->info.type = KEMPLD_VERSION_GET_TYPE(version);
  49. if (spec == 0xff) {
  50. pld->info.spec_minor = 0;
  51. pld->info.spec_major = 1;
  52. } else {
  53. pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec);
  54. pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec);
  55. }
  56. if (pld->info.spec_major > 0)
  57. pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE);
  58. else
  59. pld->feature_mask = 0;
  60. kempld_release_mutex(pld);
  61. return 0;
  62. }
  63. enum kempld_cells {
  64. KEMPLD_I2C = 0,
  65. KEMPLD_WDT,
  66. KEMPLD_GPIO,
  67. KEMPLD_UART,
  68. };
  69. static const char *kempld_dev_names[] = {
  70. [KEMPLD_I2C] = "kempld-i2c",
  71. [KEMPLD_WDT] = "kempld-wdt",
  72. [KEMPLD_GPIO] = "kempld-gpio",
  73. [KEMPLD_UART] = "kempld-uart",
  74. };
  75. #define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_dev_names)
  76. static int kempld_register_cells_generic(struct kempld_device_data *pld)
  77. {
  78. struct mfd_cell devs[KEMPLD_MAX_DEVS] = {};
  79. int i = 0;
  80. if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C)
  81. devs[i++].name = kempld_dev_names[KEMPLD_I2C];
  82. if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG)
  83. devs[i++].name = kempld_dev_names[KEMPLD_WDT];
  84. if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO)
  85. devs[i++].name = kempld_dev_names[KEMPLD_GPIO];
  86. if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
  87. devs[i++].name = kempld_dev_names[KEMPLD_UART];
  88. return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
  89. }
  90. static struct resource kempld_ioresource = {
  91. .start = KEMPLD_IOINDEX,
  92. .end = KEMPLD_IODATA,
  93. .flags = IORESOURCE_IO,
  94. };
  95. static const struct kempld_platform_data kempld_platform_data_generic = {
  96. .pld_clock = KEMPLD_CLK,
  97. .ioresource = &kempld_ioresource,
  98. .get_hardware_mutex = kempld_get_hardware_mutex,
  99. .release_hardware_mutex = kempld_release_hardware_mutex,
  100. .get_info = kempld_get_info_generic,
  101. .register_cells = kempld_register_cells_generic,
  102. };
  103. static struct platform_device *kempld_pdev;
  104. static int kempld_create_platform_device(const struct dmi_system_id *id)
  105. {
  106. const struct kempld_platform_data *pdata = id->driver_data;
  107. int ret;
  108. kempld_pdev = platform_device_alloc("kempld", -1);
  109. if (!kempld_pdev)
  110. return -ENOMEM;
  111. ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata));
  112. if (ret)
  113. goto err;
  114. ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1);
  115. if (ret)
  116. goto err;
  117. ret = platform_device_add(kempld_pdev);
  118. if (ret)
  119. goto err;
  120. return 0;
  121. err:
  122. platform_device_put(kempld_pdev);
  123. return ret;
  124. }
  125. /**
  126. * kempld_read8 - read 8 bit register
  127. * @pld: kempld_device_data structure describing the PLD
  128. * @index: register index on the chip
  129. *
  130. * kempld_get_mutex must be called prior to calling this function.
  131. */
  132. u8 kempld_read8(struct kempld_device_data *pld, u8 index)
  133. {
  134. iowrite8(index, pld->io_index);
  135. return ioread8(pld->io_data);
  136. }
  137. EXPORT_SYMBOL_GPL(kempld_read8);
  138. /**
  139. * kempld_write8 - write 8 bit register
  140. * @pld: kempld_device_data structure describing the PLD
  141. * @index: register index on the chip
  142. * @data: new register value
  143. *
  144. * kempld_get_mutex must be called prior to calling this function.
  145. */
  146. void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data)
  147. {
  148. iowrite8(index, pld->io_index);
  149. iowrite8(data, pld->io_data);
  150. }
  151. EXPORT_SYMBOL_GPL(kempld_write8);
  152. /**
  153. * kempld_read16 - read 16 bit register
  154. * @pld: kempld_device_data structure describing the PLD
  155. * @index: register index on the chip
  156. *
  157. * kempld_get_mutex must be called prior to calling this function.
  158. */
  159. u16 kempld_read16(struct kempld_device_data *pld, u8 index)
  160. {
  161. return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8;
  162. }
  163. EXPORT_SYMBOL_GPL(kempld_read16);
  164. /**
  165. * kempld_write16 - write 16 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. */
  172. void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data)
  173. {
  174. kempld_write8(pld, index, (u8)data);
  175. kempld_write8(pld, index + 1, (u8)(data >> 8));
  176. }
  177. EXPORT_SYMBOL_GPL(kempld_write16);
  178. /**
  179. * kempld_read32 - read 32 bit register
  180. * @pld: kempld_device_data structure describing the PLD
  181. * @index: register index on the chip
  182. *
  183. * kempld_get_mutex must be called prior to calling this function.
  184. */
  185. u32 kempld_read32(struct kempld_device_data *pld, u8 index)
  186. {
  187. return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16;
  188. }
  189. EXPORT_SYMBOL_GPL(kempld_read32);
  190. /**
  191. * kempld_write32 - write 32 bit register
  192. * @pld: kempld_device_data structure describing the PLD
  193. * @index: register index on the chip
  194. * @data: new register value
  195. *
  196. * kempld_get_mutex must be called prior to calling this function.
  197. */
  198. void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data)
  199. {
  200. kempld_write16(pld, index, (u16)data);
  201. kempld_write16(pld, index + 2, (u16)(data >> 16));
  202. }
  203. EXPORT_SYMBOL_GPL(kempld_write32);
  204. /**
  205. * kempld_get_mutex - acquire PLD mutex
  206. * @pld: kempld_device_data structure describing the PLD
  207. */
  208. void kempld_get_mutex(struct kempld_device_data *pld)
  209. {
  210. const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
  211. mutex_lock(&pld->lock);
  212. pdata->get_hardware_mutex(pld);
  213. }
  214. EXPORT_SYMBOL_GPL(kempld_get_mutex);
  215. /**
  216. * kempld_release_mutex - release PLD mutex
  217. * @pld: kempld_device_data structure describing the PLD
  218. */
  219. void kempld_release_mutex(struct kempld_device_data *pld)
  220. {
  221. const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
  222. pdata->release_hardware_mutex(pld);
  223. mutex_unlock(&pld->lock);
  224. }
  225. EXPORT_SYMBOL_GPL(kempld_release_mutex);
  226. /**
  227. * kempld_get_info - update device specific information
  228. * @pld: kempld_device_data structure describing the PLD
  229. *
  230. * This function calls the configured board specific kempld_get_info_XXXX
  231. * function which is responsible for gathering information about the specific
  232. * hardware. The information is then stored within the pld structure.
  233. */
  234. static int kempld_get_info(struct kempld_device_data *pld)
  235. {
  236. int ret;
  237. const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
  238. char major, minor;
  239. ret = pdata->get_info(pld);
  240. if (ret)
  241. return ret;
  242. /* The Kontron PLD firmware version string has the following format:
  243. * Pwxy.zzzz
  244. * P: Fixed
  245. * w: PLD number - 1 hex digit
  246. * x: Major version - 1 alphanumerical digit (0-9A-V)
  247. * y: Minor version - 1 alphanumerical digit (0-9A-V)
  248. * zzzz: Build number - 4 zero padded hex digits */
  249. if (pld->info.major < 10)
  250. major = pld->info.major + '0';
  251. else
  252. major = (pld->info.major - 10) + 'A';
  253. if (pld->info.minor < 10)
  254. minor = pld->info.minor + '0';
  255. else
  256. minor = (pld->info.minor - 10) + 'A';
  257. ret = scnprintf(pld->info.version, sizeof(pld->info.version),
  258. "P%X%c%c.%04X", pld->info.number, major, minor,
  259. pld->info.buildnr);
  260. if (ret < 0)
  261. return ret;
  262. return 0;
  263. }
  264. /*
  265. * kempld_register_cells - register cell drivers
  266. *
  267. * This function registers cell drivers for the detected hardware by calling
  268. * the configured kempld_register_cells_XXXX function which is responsible
  269. * to detect and register the needed cell drivers.
  270. */
  271. static int kempld_register_cells(struct kempld_device_data *pld)
  272. {
  273. const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
  274. return pdata->register_cells(pld);
  275. }
  276. static const char *kempld_get_type_string(struct kempld_device_data *pld)
  277. {
  278. const char *version_type;
  279. switch (pld->info.type) {
  280. case 0:
  281. version_type = "release";
  282. break;
  283. case 1:
  284. version_type = "debug";
  285. break;
  286. case 2:
  287. version_type = "custom";
  288. break;
  289. default:
  290. version_type = "unspecified";
  291. break;
  292. }
  293. return version_type;
  294. }
  295. static ssize_t pld_version_show(struct device *dev,
  296. struct device_attribute *attr, char *buf)
  297. {
  298. struct kempld_device_data *pld = dev_get_drvdata(dev);
  299. return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version);
  300. }
  301. static ssize_t pld_specification_show(struct device *dev,
  302. struct device_attribute *attr, char *buf)
  303. {
  304. struct kempld_device_data *pld = dev_get_drvdata(dev);
  305. return scnprintf(buf, PAGE_SIZE, "%d.%d\n", pld->info.spec_major,
  306. pld->info.spec_minor);
  307. }
  308. static ssize_t pld_type_show(struct device *dev,
  309. struct device_attribute *attr, char *buf)
  310. {
  311. struct kempld_device_data *pld = dev_get_drvdata(dev);
  312. return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld));
  313. }
  314. static DEVICE_ATTR_RO(pld_version);
  315. static DEVICE_ATTR_RO(pld_specification);
  316. static DEVICE_ATTR_RO(pld_type);
  317. static struct attribute *pld_attributes[] = {
  318. &dev_attr_pld_version.attr,
  319. &dev_attr_pld_specification.attr,
  320. &dev_attr_pld_type.attr,
  321. NULL
  322. };
  323. static const struct attribute_group pld_attr_group = {
  324. .attrs = pld_attributes,
  325. };
  326. static int kempld_detect_device(struct kempld_device_data *pld)
  327. {
  328. u8 index_reg;
  329. int ret;
  330. mutex_lock(&pld->lock);
  331. /* Check for empty IO space */
  332. index_reg = ioread8(pld->io_index);
  333. if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) {
  334. mutex_unlock(&pld->lock);
  335. return -ENODEV;
  336. }
  337. /* Release hardware mutex if acquired */
  338. if (!(index_reg & KEMPLD_MUTEX_KEY)) {
  339. iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
  340. /* PXT and COMe-cPC2 boards may require a second release */
  341. iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
  342. }
  343. mutex_unlock(&pld->lock);
  344. ret = kempld_get_info(pld);
  345. if (ret)
  346. return ret;
  347. dev_info(pld->dev, "Found Kontron PLD - %s (%s), spec %d.%d\n",
  348. pld->info.version, kempld_get_type_string(pld),
  349. pld->info.spec_major, pld->info.spec_minor);
  350. ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group);
  351. if (ret)
  352. return ret;
  353. ret = kempld_register_cells(pld);
  354. if (ret)
  355. sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
  356. return ret;
  357. }
  358. #ifdef CONFIG_ACPI
  359. static int kempld_get_acpi_data(struct platform_device *pdev)
  360. {
  361. struct list_head resource_list;
  362. struct resource *resources;
  363. struct resource_entry *rentry;
  364. struct device *dev = &pdev->dev;
  365. struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
  366. const struct kempld_platform_data *pdata;
  367. int ret;
  368. int count;
  369. pdata = acpi_device_get_match_data(dev);
  370. ret = platform_device_add_data(pdev, pdata,
  371. sizeof(struct kempld_platform_data));
  372. if (ret)
  373. return ret;
  374. INIT_LIST_HEAD(&resource_list);
  375. ret = acpi_dev_get_resources(acpi_dev, &resource_list, NULL, NULL);
  376. if (ret < 0)
  377. goto out;
  378. count = ret;
  379. if (count == 0) {
  380. ret = platform_device_add_resources(pdev, pdata->ioresource, 1);
  381. goto out;
  382. }
  383. resources = devm_kcalloc(&acpi_dev->dev, count, sizeof(*resources),
  384. GFP_KERNEL);
  385. if (!resources) {
  386. ret = -ENOMEM;
  387. goto out;
  388. }
  389. count = 0;
  390. list_for_each_entry(rentry, &resource_list, node) {
  391. memcpy(&resources[count], rentry->res,
  392. sizeof(*resources));
  393. count++;
  394. }
  395. ret = platform_device_add_resources(pdev, resources, count);
  396. out:
  397. acpi_dev_free_resource_list(&resource_list);
  398. return ret;
  399. }
  400. #else
  401. static int kempld_get_acpi_data(struct platform_device *pdev)
  402. {
  403. return -ENODEV;
  404. }
  405. #endif /* CONFIG_ACPI */
  406. static int kempld_probe(struct platform_device *pdev)
  407. {
  408. const struct kempld_platform_data *pdata;
  409. struct device *dev = &pdev->dev;
  410. struct kempld_device_data *pld;
  411. struct resource *ioport;
  412. int ret;
  413. if (kempld_pdev == NULL) {
  414. /*
  415. * No kempld_pdev device has been registered in kempld_init,
  416. * so we seem to be probing an ACPI platform device.
  417. */
  418. ret = kempld_get_acpi_data(pdev);
  419. if (ret)
  420. return ret;
  421. } else if (kempld_pdev != pdev) {
  422. /*
  423. * The platform device we are probing is not the one we
  424. * registered in kempld_init using the DMI table, so this one
  425. * comes from ACPI.
  426. * As we can only probe one - abort here and use the DMI
  427. * based one instead.
  428. */
  429. dev_notice(dev, "platform device exists - not using ACPI\n");
  430. return -ENODEV;
  431. }
  432. pdata = dev_get_platdata(dev);
  433. pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
  434. if (!pld)
  435. return -ENOMEM;
  436. ioport = platform_get_resource(pdev, IORESOURCE_IO, 0);
  437. if (!ioport)
  438. return -EINVAL;
  439. pld->io_base = devm_ioport_map(dev, ioport->start,
  440. resource_size(ioport));
  441. if (!pld->io_base)
  442. return -ENOMEM;
  443. pld->io_index = pld->io_base;
  444. pld->io_data = pld->io_base + 1;
  445. pld->pld_clock = pdata->pld_clock;
  446. pld->dev = dev;
  447. mutex_init(&pld->lock);
  448. platform_set_drvdata(pdev, pld);
  449. return kempld_detect_device(pld);
  450. }
  451. static int kempld_remove(struct platform_device *pdev)
  452. {
  453. struct kempld_device_data *pld = platform_get_drvdata(pdev);
  454. const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
  455. sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
  456. mfd_remove_devices(&pdev->dev);
  457. pdata->release_hardware_mutex(pld);
  458. return 0;
  459. }
  460. #ifdef CONFIG_ACPI
  461. static const struct acpi_device_id kempld_acpi_table[] = {
  462. { "KEM0000", (kernel_ulong_t)&kempld_platform_data_generic },
  463. { "KEM0001", (kernel_ulong_t)&kempld_platform_data_generic },
  464. {}
  465. };
  466. MODULE_DEVICE_TABLE(acpi, kempld_acpi_table);
  467. #endif
  468. static struct platform_driver kempld_driver = {
  469. .driver = {
  470. .name = "kempld",
  471. .acpi_match_table = ACPI_PTR(kempld_acpi_table),
  472. },
  473. .probe = kempld_probe,
  474. .remove = kempld_remove,
  475. };
  476. static const struct dmi_system_id kempld_dmi_table[] __initconst = {
  477. {
  478. .ident = "BBD6",
  479. .matches = {
  480. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  481. DMI_MATCH(DMI_BOARD_NAME, "COMe-bBD"),
  482. },
  483. .driver_data = (void *)&kempld_platform_data_generic,
  484. .callback = kempld_create_platform_device,
  485. }, {
  486. .ident = "BBL6",
  487. .matches = {
  488. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  489. DMI_MATCH(DMI_BOARD_NAME, "COMe-bBL6"),
  490. },
  491. .driver_data = (void *)&kempld_platform_data_generic,
  492. .callback = kempld_create_platform_device,
  493. }, {
  494. .ident = "BDV7",
  495. .matches = {
  496. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  497. DMI_MATCH(DMI_BOARD_NAME, "COMe-bDV7"),
  498. },
  499. .driver_data = (void *)&kempld_platform_data_generic,
  500. .callback = kempld_create_platform_device,
  501. }, {
  502. .ident = "BHL6",
  503. .matches = {
  504. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  505. DMI_MATCH(DMI_BOARD_NAME, "COMe-bHL6"),
  506. },
  507. .driver_data = (void *)&kempld_platform_data_generic,
  508. .callback = kempld_create_platform_device,
  509. }, {
  510. .ident = "BKL6",
  511. .matches = {
  512. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  513. DMI_MATCH(DMI_BOARD_NAME, "COMe-bKL6"),
  514. },
  515. .driver_data = (void *)&kempld_platform_data_generic,
  516. .callback = kempld_create_platform_device,
  517. }, {
  518. .ident = "BSL6",
  519. .matches = {
  520. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  521. DMI_MATCH(DMI_BOARD_NAME, "COMe-bSL6"),
  522. },
  523. .driver_data = (void *)&kempld_platform_data_generic,
  524. .callback = kempld_create_platform_device,
  525. }, {
  526. .ident = "CAL6",
  527. .matches = {
  528. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  529. DMI_MATCH(DMI_BOARD_NAME, "COMe-cAL"),
  530. },
  531. .driver_data = (void *)&kempld_platform_data_generic,
  532. .callback = kempld_create_platform_device,
  533. }, {
  534. .ident = "CBL6",
  535. .matches = {
  536. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  537. DMI_MATCH(DMI_BOARD_NAME, "COMe-cBL6"),
  538. },
  539. .driver_data = (void *)&kempld_platform_data_generic,
  540. .callback = kempld_create_platform_device,
  541. }, {
  542. .ident = "CBW6",
  543. .matches = {
  544. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  545. DMI_MATCH(DMI_BOARD_NAME, "COMe-cBW6"),
  546. },
  547. .driver_data = (void *)&kempld_platform_data_generic,
  548. .callback = kempld_create_platform_device,
  549. }, {
  550. .ident = "CCR2",
  551. .matches = {
  552. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  553. DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"),
  554. },
  555. .driver_data = (void *)&kempld_platform_data_generic,
  556. .callback = kempld_create_platform_device,
  557. }, {
  558. .ident = "CCR6",
  559. .matches = {
  560. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  561. DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"),
  562. },
  563. .driver_data = (void *)&kempld_platform_data_generic,
  564. .callback = kempld_create_platform_device,
  565. }, {
  566. .ident = "CDV7",
  567. .matches = {
  568. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  569. DMI_MATCH(DMI_BOARD_NAME, "COMe-cDV7"),
  570. },
  571. .driver_data = (void *)&kempld_platform_data_generic,
  572. .callback = kempld_create_platform_device,
  573. }, {
  574. .ident = "CHL6",
  575. .matches = {
  576. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  577. DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"),
  578. },
  579. .driver_data = (void *)&kempld_platform_data_generic,
  580. .callback = kempld_create_platform_device,
  581. }, {
  582. .ident = "CHR2",
  583. .matches = {
  584. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  585. DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"),
  586. },
  587. .driver_data = (void *)&kempld_platform_data_generic,
  588. .callback = kempld_create_platform_device,
  589. }, {
  590. .ident = "CHR2",
  591. .matches = {
  592. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  593. DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"),
  594. },
  595. .driver_data = (void *)&kempld_platform_data_generic,
  596. .callback = kempld_create_platform_device,
  597. }, {
  598. .ident = "CHR2",
  599. .matches = {
  600. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  601. DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"),
  602. },
  603. .driver_data = (void *)&kempld_platform_data_generic,
  604. .callback = kempld_create_platform_device,
  605. }, {
  606. .ident = "CHR6",
  607. .matches = {
  608. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  609. DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"),
  610. },
  611. .driver_data = (void *)&kempld_platform_data_generic,
  612. .callback = kempld_create_platform_device,
  613. }, {
  614. .ident = "CHR6",
  615. .matches = {
  616. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  617. DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"),
  618. },
  619. .driver_data = (void *)&kempld_platform_data_generic,
  620. .callback = kempld_create_platform_device,
  621. }, {
  622. .ident = "CHR6",
  623. .matches = {
  624. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  625. DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"),
  626. },
  627. .driver_data = (void *)&kempld_platform_data_generic,
  628. .callback = kempld_create_platform_device,
  629. }, {
  630. .ident = "CKL6",
  631. .matches = {
  632. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  633. DMI_MATCH(DMI_BOARD_NAME, "COMe-cKL6"),
  634. },
  635. .driver_data = (void *)&kempld_platform_data_generic,
  636. .callback = kempld_create_platform_device,
  637. }, {
  638. .ident = "CNTG",
  639. .matches = {
  640. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  641. DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"),
  642. },
  643. .driver_data = (void *)&kempld_platform_data_generic,
  644. .callback = kempld_create_platform_device,
  645. }, {
  646. .ident = "CNTG",
  647. .matches = {
  648. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  649. DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"),
  650. },
  651. .driver_data = (void *)&kempld_platform_data_generic,
  652. .callback = kempld_create_platform_device,
  653. }, {
  654. .ident = "CNTX",
  655. .matches = {
  656. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  657. DMI_MATCH(DMI_BOARD_NAME, "PXT"),
  658. },
  659. .driver_data = (void *)&kempld_platform_data_generic,
  660. .callback = kempld_create_platform_device,
  661. }, {
  662. .ident = "CSL6",
  663. .matches = {
  664. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  665. DMI_MATCH(DMI_BOARD_NAME, "COMe-cSL6"),
  666. },
  667. .driver_data = (void *)&kempld_platform_data_generic,
  668. .callback = kempld_create_platform_device,
  669. }, {
  670. .ident = "CVV6",
  671. .matches = {
  672. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  673. DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"),
  674. },
  675. .driver_data = (void *)&kempld_platform_data_generic,
  676. .callback = kempld_create_platform_device,
  677. }, {
  678. .ident = "FRI2",
  679. .matches = {
  680. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  681. DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
  682. },
  683. .driver_data = (void *)&kempld_platform_data_generic,
  684. .callback = kempld_create_platform_device,
  685. }, {
  686. .ident = "FRI2",
  687. .matches = {
  688. DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
  689. },
  690. .driver_data = (void *)&kempld_platform_data_generic,
  691. .callback = kempld_create_platform_device,
  692. }, {
  693. .ident = "A203",
  694. .matches = {
  695. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  696. DMI_MATCH(DMI_BOARD_NAME, "KBox A-203"),
  697. },
  698. .driver_data = (void *)&kempld_platform_data_generic,
  699. .callback = kempld_create_platform_device,
  700. }, {
  701. .ident = "M4A1",
  702. .matches = {
  703. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  704. DMI_MATCH(DMI_BOARD_NAME, "COMe-m4AL"),
  705. },
  706. .driver_data = (void *)&kempld_platform_data_generic,
  707. .callback = kempld_create_platform_device,
  708. }, {
  709. .ident = "MAL1",
  710. .matches = {
  711. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  712. DMI_MATCH(DMI_BOARD_NAME, "COMe-mAL10"),
  713. },
  714. .driver_data = (void *)&kempld_platform_data_generic,
  715. .callback = kempld_create_platform_device,
  716. }, {
  717. .ident = "MAPL",
  718. .matches = {
  719. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  720. DMI_MATCH(DMI_BOARD_NAME, "mITX-APL"),
  721. },
  722. .driver_data = (void *)&kempld_platform_data_generic,
  723. .callback = kempld_create_platform_device,
  724. }, {
  725. .ident = "MBR1",
  726. .matches = {
  727. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  728. DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"),
  729. },
  730. .driver_data = (void *)&kempld_platform_data_generic,
  731. .callback = kempld_create_platform_device,
  732. }, {
  733. .ident = "MVV1",
  734. .matches = {
  735. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  736. DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"),
  737. },
  738. .driver_data = (void *)&kempld_platform_data_generic,
  739. .callback = kempld_create_platform_device,
  740. }, {
  741. .ident = "NTC1",
  742. .matches = {
  743. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  744. DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
  745. },
  746. .driver_data = (void *)&kempld_platform_data_generic,
  747. .callback = kempld_create_platform_device,
  748. }, {
  749. .ident = "NTC1",
  750. .matches = {
  751. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  752. DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"),
  753. },
  754. .driver_data = (void *)&kempld_platform_data_generic,
  755. .callback = kempld_create_platform_device,
  756. }, {
  757. .ident = "NTC1",
  758. .matches = {
  759. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  760. DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
  761. },
  762. .driver_data = (void *)&kempld_platform_data_generic,
  763. .callback = kempld_create_platform_device,
  764. }, {
  765. .ident = "NUP1",
  766. .matches = {
  767. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  768. DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"),
  769. },
  770. .driver_data = (void *)&kempld_platform_data_generic,
  771. .callback = kempld_create_platform_device,
  772. }, {
  773. .ident = "PAPL",
  774. .matches = {
  775. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  776. DMI_MATCH(DMI_BOARD_NAME, "pITX-APL"),
  777. },
  778. .driver_data = (void *)&kempld_platform_data_generic,
  779. .callback = kempld_create_platform_device,
  780. }, {
  781. .ident = "SXAL",
  782. .matches = {
  783. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  784. DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXAL"),
  785. },
  786. .driver_data = (void *)&kempld_platform_data_generic,
  787. .callback = kempld_create_platform_device,
  788. }, {
  789. .ident = "SXAL4",
  790. .matches = {
  791. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  792. DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXA4"),
  793. },
  794. .driver_data = (void *)&kempld_platform_data_generic,
  795. .callback = kempld_create_platform_device,
  796. }, {
  797. .ident = "UNP1",
  798. .matches = {
  799. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  800. DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"),
  801. },
  802. .driver_data = (void *)&kempld_platform_data_generic,
  803. .callback = kempld_create_platform_device,
  804. }, {
  805. .ident = "UNP1",
  806. .matches = {
  807. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  808. DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"),
  809. },
  810. .driver_data = (void *)&kempld_platform_data_generic,
  811. .callback = kempld_create_platform_device,
  812. }, {
  813. .ident = "UNTG",
  814. .matches = {
  815. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  816. DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"),
  817. },
  818. .driver_data = (void *)&kempld_platform_data_generic,
  819. .callback = kempld_create_platform_device,
  820. }, {
  821. .ident = "UNTG",
  822. .matches = {
  823. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  824. DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"),
  825. },
  826. .driver_data = (void *)&kempld_platform_data_generic,
  827. .callback = kempld_create_platform_device,
  828. }, {
  829. .ident = "UUP6",
  830. .matches = {
  831. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  832. DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"),
  833. },
  834. .driver_data = (void *)&kempld_platform_data_generic,
  835. .callback = kempld_create_platform_device,
  836. }, {
  837. .ident = "UTH6",
  838. .matches = {
  839. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  840. DMI_MATCH(DMI_BOARD_NAME, "COMe-cTH6"),
  841. },
  842. .driver_data = (void *)&kempld_platform_data_generic,
  843. .callback = kempld_create_platform_device,
  844. }, {
  845. .ident = "Q7AL",
  846. .matches = {
  847. DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
  848. DMI_MATCH(DMI_BOARD_NAME, "Qseven-Q7AL"),
  849. },
  850. .driver_data = (void *)&kempld_platform_data_generic,
  851. .callback = kempld_create_platform_device,
  852. },
  853. {}
  854. };
  855. MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
  856. static int __init kempld_init(void)
  857. {
  858. const struct dmi_system_id *id;
  859. if (force_device_id[0]) {
  860. for (id = kempld_dmi_table;
  861. id->matches[0].slot != DMI_NONE; id++)
  862. if (strstr(id->ident, force_device_id))
  863. if (id->callback && !id->callback(id))
  864. break;
  865. if (id->matches[0].slot == DMI_NONE)
  866. return -ENODEV;
  867. } else {
  868. dmi_check_system(kempld_dmi_table);
  869. }
  870. return platform_driver_register(&kempld_driver);
  871. }
  872. static void __exit kempld_exit(void)
  873. {
  874. if (kempld_pdev)
  875. platform_device_unregister(kempld_pdev);
  876. platform_driver_unregister(&kempld_driver);
  877. }
  878. module_init(kempld_init);
  879. module_exit(kempld_exit);
  880. MODULE_DESCRIPTION("KEM PLD Core Driver");
  881. MODULE_AUTHOR("Michael Brunner <[email protected]>");
  882. MODULE_LICENSE("GPL");
  883. MODULE_ALIAS("platform:kempld-core");