From: "Chew, Chiau Ee" <[email protected]> This is to add support for BYT PCI mode PWM.
Signed-off-by: Chew, Chiau Ee <[email protected]> Signed-off-by: Chang, Rebecca Swee Fun <[email protected]> Signed-off-by: Maurice Petallo <[email protected]> --- drivers/pwm/Kconfig | 9 +++- drivers/pwm/Makefile | 1 + drivers/pwm/pwm-lpss-pci.c | 118 ++++++++++++++++++++++++++++++++++++++++++++ drivers/pwm/pwm-lpss.c | 92 ++++++++++++++++++---------------- drivers/pwm/pwm-lpss.h | 17 +++++++ 5 files changed, 194 insertions(+), 43 deletions(-) create mode 100644 drivers/pwm/pwm-lpss-pci.c create mode 100644 drivers/pwm/pwm-lpss.h diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index f2b0948..45df189 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -89,7 +89,7 @@ config PWM_LPC32XX config PWM_LPSS tristate "Intel LPSS PWM support" - depends on ACPI + depends on PCI || ACPI help Generic PWM framework driver for Intel Low Power Subsystem PWM controller. @@ -97,6 +97,13 @@ config PWM_LPSS To compile this driver as a module, choose M here: the module will be called pwm-lpio. +config PWM_LPSS_PCI + tristate "Intel LPSS PWM PCI support" + depends on PWM_LPSS && PCI + help + Generic PWM framework PCI driver for Intel Low Power Subsystem PWM + controller. + config PWM_MXS tristate "Freescale MXS PWM support" depends on ARCH_MXS && OF diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 6a5e723..7daf83c 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_IMX) += pwm-imx.o obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o +obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o obj-$(CONFIG_PWM_PXA) += pwm-pxa.o diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c new file mode 100644 index 0000000..90bde86 --- /dev/null +++ b/drivers/pwm/pwm-lpss-pci.c @@ -0,0 +1,118 @@ +/* + * Intel Low Power Subsystem PWM PCI controller driver + * + * Copyright (C) 2013, Intel Corporation + * Author: Chew, Chiau Ee <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/pci.h> +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pwm.h> +#include <linux/platform_device.h> +#include <linux/init.h> + +#include "pwm-lpss.h" + +enum { + BYT_PWM_PORT0, + BYT_PWM_PORT1, +}; + +struct pwm_lpss_pci_config { + int bus_id; +}; + +static struct pwm_lpss_pci_config pwm_pci_configs[] = { + [BYT_PWM_PORT0] = { + .bus_id = 0, + }, + [BYT_PWM_PORT1] = { + .bus_id = 1, + }, +}; + +static int pwm_lpss_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + struct pwm_lpss_chip *lpwm; + struct platform_device_info pwm; + int ret; + struct platform_device *pdev; + struct pwm_lpss_pci_config *c = &pwm_pci_configs[ent->driver_data]; + + ret = pcim_enable_device(dev); + if (ret) { + dev_err(&dev->dev, "failed to enable PWM chip: %d\n", ret); + return ret; + } + + ret = pcim_iomap_regions(dev, 1 << 0, "BYT PWM"); + if (ret) { + dev_err(&dev->dev, + "failed to map region for PWM chip: %d\n", ret); + return ret; + } + + lpwm = devm_kzalloc(&dev->dev, sizeof(*lpwm), GFP_KERNEL); + if (!lpwm) + return -ENOMEM; + + lpwm->regs = pcim_iomap_table(dev)[0]; + if (!lpwm->regs) + return -EIO; + + lpwm->clk = devm_clk_get(&dev->dev, NULL); + + lpwm->chip.base = c->bus_id; + + memset(&pwm, 0, sizeof(pwm)); + + pwm.parent = &dev->dev; + pwm.name = "pwm-lpss"; + pwm.id = c->bus_id; + pwm.data = lpwm; + pwm.size_data = sizeof(*lpwm); + + pdev = platform_device_register_full(&pwm); + if (!pdev) + return -ENOMEM; + + pci_set_drvdata(dev, pdev); + return 0; +} + +static void pwm_lpss_pci_remove(struct pci_dev *dev) +{ + struct platform_device *pdev = pci_get_drvdata(dev); + + platform_device_unregister(pdev); +} + +static DEFINE_PCI_DEVICE_TABLE(pwm_lpss_pci_devices) = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f08), + .driver_data = BYT_PWM_PORT0 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f09), + .driver_data = BYT_PWM_PORT1 }, + { }, +}; +MODULE_DEVICE_TABLE(pci, pwm_lpss_pci_devices); + +static struct pci_driver pwm_lpss_pci_driver = { + .name = "pwm-lpss-pci", + .id_table = pwm_lpss_pci_devices, + .probe = pwm_lpss_pci_probe, + .remove = pwm_lpss_pci_remove, +}; +module_pci_driver(pwm_lpss_pci_driver); + +MODULE_DESCRIPTION("PWM PCI driver for Intel LPSS"); +MODULE_AUTHOR("Chew, Chiau Ee <[email protected]>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("pci:pwm-lpss"); diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index fb3548c..eeed096 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -17,23 +17,7 @@ #include <linux/pwm.h> #include <linux/platform_device.h> -#define PWM 0x00000000 -#define PWM_ENABLE BIT(31) -#define PWM_SW_UPDATE BIT(30) -#define PWM_BASE_UNIT_SHIFT 8 -#define PWM_BASE_UNIT_MASK 0x00ffff00 -#define PWM_ON_TIME_DIV_MASK 0x000000ff - -struct pwm_lpss_chip { - struct pwm_chip chip; - void __iomem *regs; - struct clk *clk; -}; - -static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) -{ - return container_of(chip, struct pwm_lpss_chip, chip); -} +#include "pwm-lpss.h" static void pwm_lpss_set_state(struct pwm_lpss_chip *lpwm, bool enable) { @@ -109,36 +93,68 @@ static const struct pwm_ops pwm_lpss_ops = { .owner = THIS_MODULE, }; -static int pwm_lpss_probe(struct platform_device *pdev) +#ifdef CONFIG_ACPI +struct pwm_lpss_chip *pwm_lpss_acpi_get_pdata(struct platform_device *pdev) { struct pwm_lpss_chip *lpwm; struct resource *r; - int ret; lpwm = devm_kzalloc(&pdev->dev, sizeof(*lpwm), GFP_KERNEL); - if (!lpwm) - return -ENOMEM; + if (!lpwm) { + dev_err(&pdev->dev, "failed to allocate memory for platform data\n"); + return NULL; + } - lpwm->chip.dev = &pdev->dev; - lpwm->chip.ops = &pwm_lpss_ops; - lpwm->chip.base = -1; - lpwm->chip.npwm = 1; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "failed to get mmio base\n"); + return NULL; + } lpwm->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(lpwm->clk)) { dev_err(&pdev->dev, "failed to get pwm clk\n"); - return -ENODEV; + return NULL; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&pdev->dev, "failed to get mmio base\n"); - return -ENODEV; - } + lpwm->chip.base = -1; - lpwm->regs = devm_request_and_ioremap(lpwm->chip.dev, r); + lpwm->regs = devm_request_and_ioremap(&pdev->dev, r); if (!lpwm->regs) - return -EBUSY; + return NULL; + + return lpwm; +} + +static const struct acpi_device_id pwm_lpss_acpi_match[] = { + { "80860F08", 0 }, + { "80860F09", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match); +#else +struct pwm_lpss_chip *pwm_lpss_acpi_get_pdata(struct platform_device *pdev) +{ + return NULL; +} +#endif + +static int pwm_lpss_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pwm_lpss_chip *lpwm; + int ret; + + lpwm = dev_get_platdata(dev); + if (!lpwm) { + lpwm = pwm_lpss_acpi_get_pdata(pdev); + if (!lpwm) + return -ENODEV; + } + + lpwm->chip.dev = &pdev->dev; + lpwm->chip.ops = &pwm_lpss_ops; + lpwm->chip.npwm = 1; ret = pwmchip_add(&lpwm->chip); if (ret) { @@ -148,6 +164,7 @@ static int pwm_lpss_probe(struct platform_device *pdev) platform_set_drvdata(pdev, lpwm); return 0; + } static int pwm_lpss_remove(struct platform_device *pdev) @@ -158,15 +175,6 @@ static int pwm_lpss_remove(struct platform_device *pdev) return pwmchip_remove(&lpwm->chip); } -#ifdef CONFIG_ACPI -static const struct acpi_device_id pwm_lpss_acpi_match[] = { - { "80860F08", 0 }, - { "80860F09", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match); -#endif - static struct platform_driver pwm_lpss_driver = { .driver = { .name = "pwm-lpss", diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h new file mode 100644 index 0000000..d1705e5 --- /dev/null +++ b/drivers/pwm/pwm-lpss.h @@ -0,0 +1,17 @@ +#define PWM 0x00000000 +#define PWM_ENABLE BIT(31) +#define PWM_SW_UPDATE BIT(30) +#define PWM_BASE_UNIT_SHIFT 8 +#define PWM_BASE_UNIT_MASK 0x00ffff00 +#define PWM_ON_TIME_DIV_MASK 0x000000ff + +struct pwm_lpss_chip { + struct pwm_chip chip; + void __iomem *regs; + struct clk *clk; +}; + +static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) +{ + return container_of(chip, struct pwm_lpss_chip, chip); +} -- 1.7.10.4 -- _______________________________________________ linux-yocto mailing list [email protected] https://lists.yoctoproject.org/listinfo/linux-yocto
