aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/kempld-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/kempld-core.c')
-rw-r--r--drivers/mfd/kempld-core.c129
1 files changed, 107 insertions, 22 deletions
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 07692604e119..f7ff0188603d 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -86,7 +86,7 @@ enum kempld_cells {
86 KEMPLD_UART, 86 KEMPLD_UART,
87}; 87};
88 88
89static struct mfd_cell kempld_devs[] = { 89static const struct mfd_cell kempld_devs[] = {
90 [KEMPLD_I2C] = { 90 [KEMPLD_I2C] = {
91 .name = "kempld-i2c", 91 .name = "kempld-i2c",
92 }, 92 },
@@ -288,9 +288,38 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
288 */ 288 */
289static int kempld_get_info(struct kempld_device_data *pld) 289static int kempld_get_info(struct kempld_device_data *pld)
290{ 290{
291 int ret;
291 struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 292 struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
293 char major, minor;
294
295 ret = pdata->get_info(pld);
296 if (ret)
297 return ret;
298
299 /* The Kontron PLD firmware version string has the following format:
300 * Pwxy.zzzz
301 * P: Fixed
302 * w: PLD number - 1 hex digit
303 * x: Major version - 1 alphanumerical digit (0-9A-V)
304 * y: Minor version - 1 alphanumerical digit (0-9A-V)
305 * zzzz: Build number - 4 zero padded hex digits */
292 306
293 return pdata->get_info(pld); 307 if (pld->info.major < 10)
308 major = pld->info.major + '0';
309 else
310 major = (pld->info.major - 10) + 'A';
311 if (pld->info.minor < 10)
312 minor = pld->info.minor + '0';
313 else
314 minor = (pld->info.minor - 10) + 'A';
315
316 ret = scnprintf(pld->info.version, sizeof(pld->info.version),
317 "P%X%c%c.%04X", pld->info.number, major, minor,
318 pld->info.buildnr);
319 if (ret < 0)
320 return ret;
321
322 return 0;
294} 323}
295 324
296/* 325/*
@@ -307,9 +336,71 @@ static int kempld_register_cells(struct kempld_device_data *pld)
307 return pdata->register_cells(pld); 336 return pdata->register_cells(pld);
308} 337}
309 338
339static const char *kempld_get_type_string(struct kempld_device_data *pld)
340{
341 const char *version_type;
342
343 switch (pld->info.type) {
344 case 0:
345 version_type = "release";
346 break;
347 case 1:
348 version_type = "debug";
349 break;
350 case 2:
351 version_type = "custom";
352 break;
353 default:
354 version_type = "unspecified";
355 break;
356 }
357
358 return version_type;
359}
360
361static ssize_t kempld_version_show(struct device *dev,
362 struct device_attribute *attr, char *buf)
363{
364 struct kempld_device_data *pld = dev_get_drvdata(dev);
365
366 return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version);
367}
368
369static ssize_t kempld_specification_show(struct device *dev,
370 struct device_attribute *attr, char *buf)
371{
372 struct kempld_device_data *pld = dev_get_drvdata(dev);
373
374 return scnprintf(buf, PAGE_SIZE, "%d.%d\n", pld->info.spec_major,
375 pld->info.spec_minor);
376}
377
378static ssize_t kempld_type_show(struct device *dev,
379 struct device_attribute *attr, char *buf)
380{
381 struct kempld_device_data *pld = dev_get_drvdata(dev);
382
383 return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld));
384}
385
386static DEVICE_ATTR(pld_version, S_IRUGO, kempld_version_show, NULL);
387static DEVICE_ATTR(pld_specification, S_IRUGO, kempld_specification_show,
388 NULL);
389static DEVICE_ATTR(pld_type, S_IRUGO, kempld_type_show, NULL);
390
391static struct attribute *pld_attributes[] = {
392 &dev_attr_pld_version.attr,
393 &dev_attr_pld_specification.attr,
394 &dev_attr_pld_type.attr,
395 NULL
396};
397
398static const struct attribute_group pld_attr_group = {
399 .attrs = pld_attributes,
400};
401
310static int kempld_detect_device(struct kempld_device_data *pld) 402static int kempld_detect_device(struct kempld_device_data *pld)
311{ 403{
312 char *version_type;
313 u8 index_reg; 404 u8 index_reg;
314 int ret; 405 int ret;
315 406
@@ -335,27 +426,19 @@ static int kempld_detect_device(struct kempld_device_data *pld)
335 if (ret) 426 if (ret)
336 return ret; 427 return ret;
337 428
338 switch (pld->info.type) { 429 dev_info(pld->dev, "Found Kontron PLD - %s (%s), spec %d.%d\n",
339 case 0: 430 pld->info.version, kempld_get_type_string(pld),
340 version_type = "release"; 431 pld->info.spec_major, pld->info.spec_minor);
341 break; 432
342 case 1: 433 ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group);
343 version_type = "debug"; 434 if (ret)
344 break; 435 return ret;
345 case 2:
346 version_type = "custom";
347 break;
348 default:
349 version_type = "unspecified";
350 }
351 436
352 dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number); 437 ret = kempld_register_cells(pld);
353 dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n", 438 if (ret)
354 version_type, pld->info.major, pld->info.minor, 439 sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
355 pld->info.buildnr, pld->info.spec_major,
356 pld->info.spec_minor);
357 440
358 return kempld_register_cells(pld); 441 return ret;
359} 442}
360 443
361static int kempld_probe(struct platform_device *pdev) 444static int kempld_probe(struct platform_device *pdev)
@@ -399,6 +482,8 @@ static int kempld_remove(struct platform_device *pdev)
399 struct kempld_device_data *pld = platform_get_drvdata(pdev); 482 struct kempld_device_data *pld = platform_get_drvdata(pdev);
400 struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); 483 struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
401 484
485 sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
486
402 mfd_remove_devices(&pdev->dev); 487 mfd_remove_devices(&pdev->dev);
403 pdata->release_hardware_mutex(pld); 488 pdata->release_hardware_mutex(pld);
404 489