diff options
Diffstat (limited to 'drivers/mfd/intel_quark_i2c_gpio.c')
| -rw-r--r-- | drivers/mfd/intel_quark_i2c_gpio.c | 118 | 
1 files changed, 69 insertions, 49 deletions
| diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index fe8ca945f367..01935ae4e9e1 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -16,8 +16,9 @@  #include <linux/clkdev.h>  #include <linux/clk-provider.h>  #include <linux/dmi.h> +#include <linux/i2c.h>  #include <linux/platform_data/gpio-dwapb.h> -#include <linux/platform_data/i2c-designware.h> +#include <linux/property.h>  /* PCI BAR for register base address */  #define MFD_I2C_BAR		0 @@ -45,34 +46,54 @@  #define INTEL_QUARK_I2C_CLK_HZ	33000000  struct intel_quark_mfd { -	struct device		*dev;  	struct clk		*i2c_clk;  	struct clk_lookup	*i2c_clk_lookup;  }; +static const struct property_entry intel_quark_i2c_controller_standard_properties[] = { +	PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ), +	{ } +}; + +static const struct software_node intel_quark_i2c_controller_standard_node = { +	.name = "intel-quark-i2c-controller", +	.properties = intel_quark_i2c_controller_standard_properties, +}; + +static const struct property_entry intel_quark_i2c_controller_fast_properties[] = { +	PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_FAST_MODE_FREQ), +	{ } +}; + +static const struct software_node intel_quark_i2c_controller_fast_node = { +	.name = "intel-quark-i2c-controller", +	.properties = intel_quark_i2c_controller_fast_properties, +}; +  static const struct dmi_system_id dmi_platform_info[] = {  	{  		.matches = {  			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"),  		}, -		.driver_data = (void *)100000, +		.driver_data = (void *)&intel_quark_i2c_controller_standard_node,  	},  	{  		.matches = {  			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),  		}, -		.driver_data = (void *)400000, +		.driver_data = (void *)&intel_quark_i2c_controller_fast_node,  	},  	{  		.matches = {  			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),  		}, -		.driver_data = (void *)400000, +		.driver_data = (void *)&intel_quark_i2c_controller_fast_node,  	},  	{}  }; -static const struct resource intel_quark_i2c_res[] = { +/* This is used as a place holder and will be modified at run-time */ +static struct resource intel_quark_i2c_res[] = {  	[INTEL_QUARK_IORES_MEM] = {  		.flags = IORESOURCE_MEM,  	}, @@ -85,7 +106,8 @@ static struct mfd_cell_acpi_match intel_quark_acpi_match_i2c = {  	.adr = MFD_ACPI_MATCH_I2C,  }; -static const struct resource intel_quark_gpio_res[] = { +/* This is used as a place holder and will be modified at run-time */ +static struct resource intel_quark_gpio_res[] = {  	[INTEL_QUARK_IORES_MEM] = {  		.flags = IORESOURCE_MEM,  	}, @@ -96,15 +118,7 @@ static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {  };  static struct mfd_cell intel_quark_mfd_cells[] = { -	{ -		.id = MFD_GPIO_BAR, -		.name = "gpio-dwapb", -		.acpi_match = &intel_quark_acpi_match_gpio, -		.num_resources = ARRAY_SIZE(intel_quark_gpio_res), -		.resources = intel_quark_gpio_res, -		.ignore_resource_conflicts = true, -	}, -	{ +	[MFD_I2C_BAR] = {  		.id = MFD_I2C_BAR,  		.name = "i2c_designware",  		.acpi_match = &intel_quark_acpi_match_i2c, @@ -112,6 +126,14 @@ static struct mfd_cell intel_quark_mfd_cells[] = {  		.resources = intel_quark_i2c_res,  		.ignore_resource_conflicts = true,  	}, +	[MFD_GPIO_BAR] = { +		.id = MFD_GPIO_BAR, +		.name = "gpio-dwapb", +		.acpi_match = &intel_quark_acpi_match_gpio, +		.num_resources = ARRAY_SIZE(intel_quark_gpio_res), +		.resources = intel_quark_gpio_res, +		.ignore_resource_conflicts = true, +	},  };  static const struct pci_device_id intel_quark_mfd_ids[] = { @@ -155,48 +177,37 @@ static void intel_quark_unregister_i2c_clk(struct device *dev)  	clk_unregister(quark_mfd->i2c_clk);  } -static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell) +static int intel_quark_i2c_setup(struct pci_dev *pdev)  { +	struct mfd_cell *cell = &intel_quark_mfd_cells[MFD_I2C_BAR]; +	struct resource *res = intel_quark_i2c_res;  	const struct dmi_system_id *dmi_id; -	struct dw_i2c_platform_data *pdata; -	struct resource *res = (struct resource *)cell->resources; -	struct device *dev = &pdev->dev; -	res[INTEL_QUARK_IORES_MEM].start = -		pci_resource_start(pdev, MFD_I2C_BAR); -	res[INTEL_QUARK_IORES_MEM].end = -		pci_resource_end(pdev, MFD_I2C_BAR); +	res[INTEL_QUARK_IORES_MEM].start = pci_resource_start(pdev, MFD_I2C_BAR); +	res[INTEL_QUARK_IORES_MEM].end = pci_resource_end(pdev, MFD_I2C_BAR); -	res[INTEL_QUARK_IORES_IRQ].start = pdev->irq; -	res[INTEL_QUARK_IORES_IRQ].end = pdev->irq; - -	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); -	if (!pdata) -		return -ENOMEM; +	res[INTEL_QUARK_IORES_IRQ].start = pci_irq_vector(pdev, 0); +	res[INTEL_QUARK_IORES_IRQ].end = pci_irq_vector(pdev, 0);  	/* Normal mode by default */ -	pdata->i2c_scl_freq = 100000; +	cell->swnode = &intel_quark_i2c_controller_standard_node;  	dmi_id = dmi_first_match(dmi_platform_info);  	if (dmi_id) -		pdata->i2c_scl_freq = (uintptr_t)dmi_id->driver_data; - -	cell->platform_data = pdata; -	cell->pdata_size = sizeof(*pdata); +		cell->swnode = (struct software_node *)dmi_id->driver_data;  	return 0;  } -static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell) +static int intel_quark_gpio_setup(struct pci_dev *pdev)  { +	struct mfd_cell *cell = &intel_quark_mfd_cells[MFD_GPIO_BAR]; +	struct resource *res = intel_quark_gpio_res;  	struct dwapb_platform_data *pdata; -	struct resource *res = (struct resource *)cell->resources;  	struct device *dev = &pdev->dev; -	res[INTEL_QUARK_IORES_MEM].start = -		pci_resource_start(pdev, MFD_GPIO_BAR); -	res[INTEL_QUARK_IORES_MEM].end = -		pci_resource_end(pdev, MFD_GPIO_BAR); +	res[INTEL_QUARK_IORES_MEM].start = pci_resource_start(pdev, MFD_GPIO_BAR); +	res[INTEL_QUARK_IORES_MEM].end = pci_resource_end(pdev, MFD_GPIO_BAR);  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);  	if (!pdata) @@ -215,7 +226,7 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell)  	pdata->properties->idx		= 0;  	pdata->properties->ngpio	= INTEL_QUARK_MFD_NGPIO;  	pdata->properties->gpio_base	= INTEL_QUARK_MFD_GPIO_BASE; -	pdata->properties->irq[0]	= pdev->irq; +	pdata->properties->irq[0]	= pci_irq_vector(pdev, 0);  	pdata->properties->irq_shared	= true;  	cell->platform_data = pdata; @@ -238,29 +249,37 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,  	if (!quark_mfd)  		return -ENOMEM; -	quark_mfd->dev = &pdev->dev;  	dev_set_drvdata(&pdev->dev, quark_mfd);  	ret = intel_quark_register_i2c_clk(&pdev->dev);  	if (ret)  		return ret; -	ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); -	if (ret) +	pci_set_master(pdev); + +	/* This driver only requires 1 IRQ vector */ +	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); +	if (ret < 0)  		goto err_unregister_i2c_clk; -	ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); +	ret = intel_quark_i2c_setup(pdev);  	if (ret) -		goto err_unregister_i2c_clk; +		goto err_free_irq_vectors; + +	ret = intel_quark_gpio_setup(pdev); +	if (ret) +		goto err_free_irq_vectors;  	ret = mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,  			      ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,  			      NULL);  	if (ret) -		goto err_unregister_i2c_clk; +		goto err_free_irq_vectors;  	return 0; +err_free_irq_vectors: +	pci_free_irq_vectors(pdev);  err_unregister_i2c_clk:  	intel_quark_unregister_i2c_clk(&pdev->dev);  	return ret; @@ -268,8 +287,9 @@ err_unregister_i2c_clk:  static void intel_quark_mfd_remove(struct pci_dev *pdev)  { -	intel_quark_unregister_i2c_clk(&pdev->dev);  	mfd_remove_devices(&pdev->dev); +	pci_free_irq_vectors(pdev); +	intel_quark_unregister_i2c_clk(&pdev->dev);  }  static struct pci_driver intel_quark_mfd_driver = { | 
