diff options
Diffstat (limited to 'drivers/mfd/kempld-core.c')
| -rw-r--r-- | drivers/mfd/kempld-core.c | 160 | 
1 files changed, 136 insertions, 24 deletions
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c index d3e23278d29..f7ff0188603 100644 --- a/drivers/mfd/kempld-core.c +++ b/drivers/mfd/kempld-core.c @@ -86,7 +86,7 @@ enum kempld_cells {  	KEMPLD_UART,  }; -static struct mfd_cell kempld_devs[] = { +static const struct mfd_cell kempld_devs[] = {  	[KEMPLD_I2C] = {  		.name = "kempld-i2c",  	}, @@ -288,9 +288,38 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);   */  static int kempld_get_info(struct kempld_device_data *pld)  { +	int ret;  	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); +	char major, minor; + +	ret = pdata->get_info(pld); +	if (ret) +		return ret; + +	/* The Kontron PLD firmware version string has the following format: +	 * Pwxy.zzzz +	 *   P:    Fixed +	 *   w:    PLD number    - 1 hex digit +	 *   x:    Major version - 1 alphanumerical digit (0-9A-V) +	 *   y:    Minor version - 1 alphanumerical digit (0-9A-V) +	 *   zzzz: Build number  - 4 zero padded hex digits */ -	return pdata->get_info(pld); +	if (pld->info.major < 10) +		major = pld->info.major + '0'; +	else +		major = (pld->info.major - 10) + 'A'; +	if (pld->info.minor < 10) +		minor = pld->info.minor + '0'; +	else +		minor = (pld->info.minor - 10) + 'A'; + +	ret = scnprintf(pld->info.version, sizeof(pld->info.version), +			"P%X%c%c.%04X", pld->info.number, major, minor, +			pld->info.buildnr); +	if (ret < 0) +		return ret; + +	return 0;  }  /* @@ -307,9 +336,71 @@ static int kempld_register_cells(struct kempld_device_data *pld)  	return pdata->register_cells(pld);  } +static const char *kempld_get_type_string(struct kempld_device_data *pld) +{ +	const char *version_type; + +	switch (pld->info.type) { +	case 0: +		version_type = "release"; +		break; +	case 1: +		version_type = "debug"; +		break; +	case 2: +		version_type = "custom"; +		break; +	default: +		version_type = "unspecified"; +		break; +	} + +	return version_type; +} + +static ssize_t kempld_version_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	struct kempld_device_data *pld = dev_get_drvdata(dev); + +	return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version); +} + +static ssize_t kempld_specification_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	struct kempld_device_data *pld = dev_get_drvdata(dev); + +	return scnprintf(buf, PAGE_SIZE, "%d.%d\n", pld->info.spec_major, +		       pld->info.spec_minor); +} + +static ssize_t kempld_type_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	struct kempld_device_data *pld = dev_get_drvdata(dev); + +	return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld)); +} + +static DEVICE_ATTR(pld_version, S_IRUGO, kempld_version_show, NULL); +static DEVICE_ATTR(pld_specification, S_IRUGO, kempld_specification_show, +		   NULL); +static DEVICE_ATTR(pld_type, S_IRUGO, kempld_type_show, NULL); + +static struct attribute *pld_attributes[] = { +	&dev_attr_pld_version.attr, +	&dev_attr_pld_specification.attr, +	&dev_attr_pld_type.attr, +	NULL +}; + +static const struct attribute_group pld_attr_group = { +	.attrs = pld_attributes, +}; +  static int kempld_detect_device(struct kempld_device_data *pld)  { -	char *version_type;  	u8 index_reg;  	int ret; @@ -322,9 +413,12 @@ static int kempld_detect_device(struct kempld_device_data *pld)  		return -ENODEV;  	} -	/* Release hardware mutex if aquired */ -	if (!(index_reg & KEMPLD_MUTEX_KEY)) +	/* Release hardware mutex if acquired */ +	if (!(index_reg & KEMPLD_MUTEX_KEY)) { +		iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); +		/* PXT and COMe-cPC2 boards may require a second release */  		iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); +	}  	mutex_unlock(&pld->lock); @@ -332,27 +426,19 @@ static int kempld_detect_device(struct kempld_device_data *pld)  	if (ret)  		return ret; -	switch (pld->info.type) { -	case 0: -		version_type = "release"; -		break; -	case 1: -		version_type = "debug"; -		break; -	case 2: -		version_type = "custom"; -		break; -	default: -		version_type = "unspecified"; -	} +	dev_info(pld->dev, "Found Kontron PLD - %s (%s), spec %d.%d\n", +		 pld->info.version, kempld_get_type_string(pld), +		 pld->info.spec_major, pld->info.spec_minor); -	dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number); -	dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n", -		 version_type, pld->info.major, pld->info.minor, -		 pld->info.buildnr, pld->info.spec_major, -		 pld->info.spec_minor); +	ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group); +	if (ret) +		return ret; -	return kempld_register_cells(pld); +	ret = kempld_register_cells(pld); +	if (ret) +		sysfs_remove_group(&pld->dev->kobj, &pld_attr_group); + +	return ret;  }  static int kempld_probe(struct platform_device *pdev) @@ -396,6 +482,8 @@ static int kempld_remove(struct platform_device *pdev)  	struct kempld_device_data *pld = platform_get_drvdata(pdev);  	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); +	sysfs_remove_group(&pld->dev->kobj, &pld_attr_group); +  	mfd_remove_devices(&pdev->dev);  	pdata->release_hardware_mutex(pld); @@ -438,6 +526,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {  		.driver_data = (void *)&kempld_platform_data_generic,  		.callback = kempld_create_platform_device,  	}, { +		.ident = "CHL6", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), +			DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"), +		}, +		.driver_data = (void *)&kempld_platform_data_generic, +		.callback = kempld_create_platform_device, +	}, {  		.ident = "CHR2",  		.matches = {  			DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), @@ -510,6 +606,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {  		.driver_data = (void *)&kempld_platform_data_generic,  		.callback = kempld_create_platform_device,  	}, { +		.ident = "CVV6", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), +			DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"), +		}, +		.driver_data = (void *)&kempld_platform_data_generic, +		.callback = kempld_create_platform_device, +	}, {  		.ident = "FRI2",  		.matches = {  			DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), @@ -533,6 +637,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {  		.driver_data = (void *)&kempld_platform_data_generic,  		.callback = kempld_create_platform_device,  	}, { +		.ident = "MVV1", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), +			DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"), +		}, +		.driver_data = (void *)&kempld_platform_data_generic, +		.callback = kempld_create_platform_device, +	}, {  		.ident = "NTC1",  		.matches = {  			DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),  | 
