diff options
Diffstat (limited to 'drivers/platform/x86/intel_pmc_ipc.c')
| -rw-r--r-- | drivers/platform/x86/intel_pmc_ipc.c | 115 | 
1 files changed, 41 insertions, 74 deletions
| diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index bb792a52248b..e03fa31446ca 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -33,6 +33,7 @@  #include <linux/suspend.h>  #include <linux/acpi.h>  #include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/spinlock.h>  #include <asm/intel_pmc_ipc.h> @@ -131,6 +132,7 @@ static struct intel_pmc_ipc_dev {  	/* gcr */  	void __iomem *gcr_mem_base;  	bool has_gcr_regs; +	spinlock_t gcr_lock;  	/* punit */  	struct platform_device *punit_dev; @@ -225,17 +227,17 @@ int intel_pmc_gcr_read(u32 offset, u32 *data)  {  	int ret; -	mutex_lock(&ipclock); +	spin_lock(&ipcdev.gcr_lock);  	ret = is_gcr_valid(offset);  	if (ret < 0) { -		mutex_unlock(&ipclock); +		spin_unlock(&ipcdev.gcr_lock);  		return ret;  	}  	*data = readl(ipcdev.gcr_mem_base + offset); -	mutex_unlock(&ipclock); +	spin_unlock(&ipcdev.gcr_lock);  	return 0;  } @@ -255,17 +257,17 @@ int intel_pmc_gcr_write(u32 offset, u32 data)  {  	int ret; -	mutex_lock(&ipclock); +	spin_lock(&ipcdev.gcr_lock);  	ret = is_gcr_valid(offset);  	if (ret < 0) { -		mutex_unlock(&ipclock); +		spin_unlock(&ipcdev.gcr_lock);  		return ret;  	}  	writel(data, ipcdev.gcr_mem_base + offset); -	mutex_unlock(&ipclock); +	spin_unlock(&ipcdev.gcr_lock);  	return 0;  } @@ -287,7 +289,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)  	u32 new_val;  	int ret = 0; -	mutex_lock(&ipclock); +	spin_lock(&ipcdev.gcr_lock);  	ret = is_gcr_valid(offset);  	if (ret < 0) @@ -309,7 +311,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)  	}  gcr_ipc_unlock: -	mutex_unlock(&ipclock); +	spin_unlock(&ipcdev.gcr_lock);  	return ret;  }  EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); @@ -480,52 +482,41 @@ static irqreturn_t ioc(int irq, void *dev_id)  static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)  { -	resource_size_t pci_resource; +	struct intel_pmc_ipc_dev *pmc = &ipcdev;  	int ret; -	int len; -	ipcdev.dev = &pci_dev_get(pdev)->dev; -	ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; +	/* Only one PMC is supported */ +	if (pmc->dev) +		return -EBUSY; -	ret = pci_enable_device(pdev); +	pmc->irq_mode = IPC_TRIGGER_MODE_IRQ; + +	spin_lock_init(&ipcdev.gcr_lock); + +	ret = pcim_enable_device(pdev);  	if (ret)  		return ret; -	ret = pci_request_regions(pdev, "intel_pmc_ipc"); +	ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));  	if (ret)  		return ret; -	pci_resource = pci_resource_start(pdev, 0); -	len = pci_resource_len(pdev, 0); -	if (!pci_resource || !len) { -		dev_err(&pdev->dev, "Failed to get resource\n"); -		return -ENOMEM; -	} +	init_completion(&pmc->cmd_complete); -	init_completion(&ipcdev.cmd_complete); +	pmc->ipc_base = pcim_iomap_table(pdev)[0]; -	if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) { +	ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", +				pmc); +	if (ret) {  		dev_err(&pdev->dev, "Failed to request irq\n"); -		return -EBUSY; +		return ret;  	} -	ipcdev.ipc_base = ioremap_nocache(pci_resource, len); -	if (!ipcdev.ipc_base) { -		dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); -		free_irq(pdev->irq, &ipcdev); -		ret = -ENOMEM; -	} +	pmc->dev = &pdev->dev; -	return ret; -} +	pci_set_drvdata(pdev, pmc); -static void ipc_pci_remove(struct pci_dev *pdev) -{ -	free_irq(pdev->irq, &ipcdev); -	pci_release_regions(pdev); -	pci_dev_put(pdev); -	iounmap(ipcdev.ipc_base); -	ipcdev.dev = NULL; +	return 0;  }  static const struct pci_device_id ipc_pci_ids[] = { @@ -540,7 +531,6 @@ static struct pci_driver ipc_pci_driver = {  	.name = "intel_pmc_ipc",  	.id_table = ipc_pci_ids,  	.probe = ipc_pci_probe, -	.remove = ipc_pci_remove,  };  static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, @@ -850,17 +840,12 @@ static int ipc_plat_get_res(struct platform_device *pdev)  		return -ENXIO;  	}  	size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; +	res->end = res->start + size - 1; + +	addr = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(addr)) +		return PTR_ERR(addr); -	if (!request_mem_region(res->start, size, pdev->name)) { -		dev_err(&pdev->dev, "Failed to request ipc resource\n"); -		return -EBUSY; -	} -	addr = ioremap_nocache(res->start, size); -	if (!addr) { -		dev_err(&pdev->dev, "I/O memory remapping failed\n"); -		release_mem_region(res->start, size); -		return -ENOMEM; -	}  	ipcdev.ipc_base = addr;  	ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; @@ -917,12 +902,12 @@ MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids);  static int ipc_plat_probe(struct platform_device *pdev)  { -	struct resource *res;  	int ret;  	ipcdev.dev = &pdev->dev;  	ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;  	init_completion(&ipcdev.cmd_complete); +	spin_lock_init(&ipcdev.gcr_lock);  	ipcdev.irq = platform_get_irq(pdev, 0);  	if (ipcdev.irq < 0) { @@ -939,11 +924,11 @@ static int ipc_plat_probe(struct platform_device *pdev)  	ret = ipc_create_pmc_devices();  	if (ret) {  		dev_err(&pdev->dev, "Failed to create pmc devices\n"); -		goto err_device; +		return ret;  	} -	if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND, -			"intel_pmc_ipc", &ipcdev)) { +	if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, +			     "intel_pmc_ipc", &ipcdev)) {  		dev_err(&pdev->dev, "Failed to request irq\n");  		ret = -EBUSY;  		goto err_irq; @@ -960,40 +945,22 @@ static int ipc_plat_probe(struct platform_device *pdev)  	return 0;  err_sys: -	free_irq(ipcdev.irq, &ipcdev); +	devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);  err_irq:  	platform_device_unregister(ipcdev.tco_dev);  	platform_device_unregister(ipcdev.punit_dev);  	platform_device_unregister(ipcdev.telemetry_dev); -err_device: -	iounmap(ipcdev.ipc_base); -	res = platform_get_resource(pdev, IORESOURCE_MEM, -				    PLAT_RESOURCE_IPC_INDEX); -	if (res) { -		release_mem_region(res->start, -				   PLAT_RESOURCE_IPC_SIZE + -				   PLAT_RESOURCE_GCR_SIZE); -	} +  	return ret;  }  static int ipc_plat_remove(struct platform_device *pdev)  { -	struct resource *res; -  	sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); -	free_irq(ipcdev.irq, &ipcdev); +	devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);  	platform_device_unregister(ipcdev.tco_dev);  	platform_device_unregister(ipcdev.punit_dev);  	platform_device_unregister(ipcdev.telemetry_dev); -	iounmap(ipcdev.ipc_base); -	res = platform_get_resource(pdev, IORESOURCE_MEM, -				    PLAT_RESOURCE_IPC_INDEX); -	if (res) { -		release_mem_region(res->start, -				   PLAT_RESOURCE_IPC_SIZE + -				   PLAT_RESOURCE_GCR_SIZE); -	}  	ipcdev.dev = NULL;  	return 0;  } |