pwm: Changes for v6.1-rc1

The Rockchip and Mediatek drivers gain support for more chips and the
 LPSS driver undergoes some refactoring and receives some improvements.
 Other than that there are various cleanups of the core.
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmM+9MgZHHRoaWVycnku
 cmVkaW5nQGdtYWlsLmNvbQAKCRDdI6zXfz6zod9GD/4qFiwglyU81Aw56voXQPDS
 MJ9+DLBlfhnC8KtGmhPBOc4xjr+hf3QuCr6by/PbT3C3cUBFVjFWoaxCGKFzSoGP
 Vkt0ZuaRwBycp4z5dhOR8VhnJcLOcd155o13mv+J/Gzt1LJxq4ipwb2lNDqMBux2
 37VjpQUvAQmmt/mhNhR/YHs9UKcjMB/HEcTUAha77l2wTxmRydr9tHKkl/8AalPM
 N+9KEsurmpqmLJgWJUXZpBF3YDf+o1S4m0/4/LPN7GTfOvFSNmE8D2Rmc/5YzEQU
 oePdqxfXEgDwB/a5ZDOnuqWfPscNAxh2fELkG42sAqX/8LXn+tZ6LUbuWzwT2hQy
 CWBJbP79A+7bkHPuoXnrJsnIULSbXEd8g9j0JfTIT2CDN1Usjl5K+nNWS68a66qi
 iJMh16hYsjwSURuJG+t0AttWutZKFXGDV3vTompaoM92jhEyrsfnT1jrFc3aUzYW
 lwRKdP+ANTWEe/4x2LitmOavmbM5Q/2afFV3NXNV06xPAlqMM/GWRM614OV1d4AV
 mBr8eXKbKUR4SqOwPVSbG2eqOshMriuWmESjw3O2hO+dz5ZHzQQgwB5/3IUMAu1C
 /GWG9fzOZ/mtesggyfSh/ml5juzJDYhWqBJquXRFKNoX254xSqmhNusvq3KnECnO
 f2E5mNuj4n9ea+OmqRl/lQ==
 =zTfN
 -----END PGP SIGNATURE-----

Merge tag 'pwm/for-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm

Pull pwm updates from Thierry Reding:
 "The Rockchip and Mediatek drivers gain support for more chips and the
  LPSS driver undergoes some refactoring and receives some improvements.

  Other than that there are various cleanups of the core"

* tag 'pwm/for-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
  pwm: sysfs: Replace sprintf() with sysfs_emit()
  pwm: core: Replace custom implementation of device_match_fwnode()
  pwm: lpss: Add a comment to the bypass field
  pwm: lpss: Make use of bits.h macros for all masks
  pwm: lpss: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr() macros
  pwm: lpss: Use device_get_match_data() to get device data
  pwm: lpss: Move resource mapping to the glue drivers
  pwm: lpss: Move exported symbols to PWM_LPSS namespace
  pwm: lpss: Deduplicate board info data structures
  dt-bindings: pwm: Add compatible for Mediatek MT8188
  dt-bindings: pwm: rockchip: Add rockchip,rk3128-pwm
  dt-bindings: pwm: rockchip: Add description for rk3588
  pwm: sysfs: Switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
  pwm: rockchip: Convert to use dev_err_probe()
This commit is contained in:
Linus Torvalds 2022-10-07 11:32:10 -07:00
commit 3fb55dd140
9 changed files with 92 additions and 97 deletions

View File

@ -27,6 +27,7 @@ properties:
- items: - items:
- enum: - enum:
- mediatek,mt8186-disp-pwm - mediatek,mt8186-disp-pwm
- mediatek,mt8188-disp-pwm
- mediatek,mt8192-disp-pwm - mediatek,mt8192-disp-pwm
- mediatek,mt8195-disp-pwm - mediatek,mt8195-disp-pwm
- const: mediatek,mt8183-disp-pwm - const: mediatek,mt8183-disp-pwm

View File

@ -21,6 +21,7 @@ properties:
- const: rockchip,rk2928-pwm - const: rockchip,rk2928-pwm
- items: - items:
- enum: - enum:
- rockchip,rk3128-pwm
- rockchip,rk3368-pwm - rockchip,rk3368-pwm
- rockchip,rk3399-pwm - rockchip,rk3399-pwm
- rockchip,rv1108-pwm - rockchip,rv1108-pwm
@ -30,6 +31,7 @@ properties:
- rockchip,px30-pwm - rockchip,px30-pwm
- rockchip,rk3308-pwm - rockchip,rk3308-pwm
- rockchip,rk3568-pwm - rockchip,rk3568-pwm
- rockchip,rk3588-pwm
- const: rockchip,rk3328-pwm - const: rockchip,rk3328-pwm
reg: reg:

View File

@ -678,7 +678,7 @@ static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
mutex_lock(&pwm_lock); mutex_lock(&pwm_lock);
list_for_each_entry(chip, &pwm_chips, list) list_for_each_entry(chip, &pwm_chips, list)
if (chip->dev && dev_fwnode(chip->dev) == fwnode) { if (chip->dev && device_match_fwnode(chip->dev, fwnode)) {
mutex_unlock(&pwm_lock); mutex_unlock(&pwm_lock);
return chip; return chip;
} }

View File

@ -14,35 +14,6 @@
#include "pwm-lpss.h" #include "pwm-lpss.h"
/* BayTrail */
static const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
.clk_rate = 25000000,
.npwm = 1,
.base_unit_bits = 16,
};
/* Braswell */
static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
.clk_rate = 19200000,
.npwm = 1,
.base_unit_bits = 16,
};
/* Broxton */
static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
.clk_rate = 19200000,
.npwm = 4,
.base_unit_bits = 22,
.bypass = true,
};
/* Tangier */
static const struct pwm_lpss_boardinfo pwm_lpss_tng_info = {
.clk_rate = 19200000,
.npwm = 4,
.base_unit_bits = 22,
};
static int pwm_lpss_probe_pci(struct pci_dev *pdev, static int pwm_lpss_probe_pci(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
@ -54,8 +25,12 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev,
if (err < 0) if (err < 0)
return err; return err;
err = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
if (err)
return err;
info = (struct pwm_lpss_boardinfo *)id->driver_data; info = (struct pwm_lpss_boardinfo *)id->driver_data;
lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info); lpwm = pwm_lpss_probe(&pdev->dev, pcim_iomap_table(pdev)[0], info);
if (IS_ERR(lpwm)) if (IS_ERR(lpwm))
return PTR_ERR(lpwm); return PTR_ERR(lpwm);
@ -73,7 +48,6 @@ static void pwm_lpss_remove_pci(struct pci_dev *pdev)
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
} }
#ifdef CONFIG_PM
static int pwm_lpss_runtime_suspend_pci(struct device *dev) static int pwm_lpss_runtime_suspend_pci(struct device *dev)
{ {
/* /*
@ -87,12 +61,11 @@ static int pwm_lpss_runtime_resume_pci(struct device *dev)
{ {
return 0; return 0;
} }
#endif
static const struct dev_pm_ops pwm_lpss_pci_pm = { static DEFINE_RUNTIME_DEV_PM_OPS(pwm_lpss_pci_pm,
SET_RUNTIME_PM_OPS(pwm_lpss_runtime_suspend_pci, pwm_lpss_runtime_suspend_pci,
pwm_lpss_runtime_resume_pci, NULL) pwm_lpss_runtime_resume_pci,
}; NULL);
static const struct pci_device_id pwm_lpss_pci_ids[] = { static const struct pci_device_id pwm_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info}, { PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info},
@ -114,10 +87,11 @@ static struct pci_driver pwm_lpss_driver_pci = {
.probe = pwm_lpss_probe_pci, .probe = pwm_lpss_probe_pci,
.remove = pwm_lpss_remove_pci, .remove = pwm_lpss_remove_pci,
.driver = { .driver = {
.pm = &pwm_lpss_pci_pm, .pm = pm_ptr(&pwm_lpss_pci_pm),
}, },
}; };
module_pci_driver(pwm_lpss_driver_pci); module_pci_driver(pwm_lpss_driver_pci);
MODULE_DESCRIPTION("PWM PCI driver for Intel LPSS"); MODULE_DESCRIPTION("PWM PCI driver for Intel LPSS");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PWM_LPSS);

View File

@ -7,52 +7,31 @@
* Derived from the original pwm-lpss.c * Derived from the original pwm-lpss.c
*/ */
#include <linux/acpi.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/property.h>
#include "pwm-lpss.h" #include "pwm-lpss.h"
/* BayTrail */
static const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
.clk_rate = 25000000,
.npwm = 1,
.base_unit_bits = 16,
};
/* Braswell */
static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
.clk_rate = 19200000,
.npwm = 1,
.base_unit_bits = 16,
.other_devices_aml_touches_pwm_regs = true,
};
/* Broxton */
static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
.clk_rate = 19200000,
.npwm = 4,
.base_unit_bits = 22,
.bypass = true,
};
static int pwm_lpss_probe_platform(struct platform_device *pdev) static int pwm_lpss_probe_platform(struct platform_device *pdev)
{ {
const struct pwm_lpss_boardinfo *info; const struct pwm_lpss_boardinfo *info;
const struct acpi_device_id *id;
struct pwm_lpss_chip *lpwm; struct pwm_lpss_chip *lpwm;
struct resource *r; void __iomem *base;
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); info = device_get_match_data(&pdev->dev);
if (!id) if (!info)
return -ENODEV; return -ENODEV;
info = (const struct pwm_lpss_boardinfo *)id->driver_data; base = devm_platform_ioremap_resource(pdev, 0);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (IS_ERR(base))
return PTR_ERR(base);
lpwm = pwm_lpss_probe(&pdev->dev, r, info); lpwm = pwm_lpss_probe(&pdev->dev, base, info);
if (IS_ERR(lpwm)) if (IS_ERR(lpwm))
return PTR_ERR(lpwm); return PTR_ERR(lpwm);
@ -110,4 +89,5 @@ module_platform_driver(pwm_lpss_driver_platform);
MODULE_DESCRIPTION("PWM platform driver for Intel LPSS"); MODULE_DESCRIPTION("PWM platform driver for Intel LPSS");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PWM_LPSS);
MODULE_ALIAS("platform:pwm-lpss"); MODULE_ALIAS("platform:pwm-lpss");

View File

@ -10,6 +10,7 @@
* Author: Alan Cox <alan@linux.intel.com> * Author: Alan Cox <alan@linux.intel.com>
*/ */
#include <linux/bits.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
@ -18,17 +19,53 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/time.h> #include <linux/time.h>
#define DEFAULT_SYMBOL_NAMESPACE PWM_LPSS
#include "pwm-lpss.h" #include "pwm-lpss.h"
#define PWM 0x00000000 #define PWM 0x00000000
#define PWM_ENABLE BIT(31) #define PWM_ENABLE BIT(31)
#define PWM_SW_UPDATE BIT(30) #define PWM_SW_UPDATE BIT(30)
#define PWM_BASE_UNIT_SHIFT 8 #define PWM_BASE_UNIT_SHIFT 8
#define PWM_ON_TIME_DIV_MASK 0x000000ff #define PWM_ON_TIME_DIV_MASK GENMASK(7, 0)
/* Size of each PWM register space if multiple */ /* Size of each PWM register space if multiple */
#define PWM_SIZE 0x400 #define PWM_SIZE 0x400
/* BayTrail */
const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
.clk_rate = 25000000,
.npwm = 1,
.base_unit_bits = 16,
};
EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
/* Braswell */
const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
.clk_rate = 19200000,
.npwm = 1,
.base_unit_bits = 16,
.other_devices_aml_touches_pwm_regs = true,
};
EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
/* Broxton */
const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
.clk_rate = 19200000,
.npwm = 4,
.base_unit_bits = 22,
.bypass = true,
};
EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);
/* Tangier */
const struct pwm_lpss_boardinfo pwm_lpss_tng_info = {
.clk_rate = 19200000,
.npwm = 4,
.base_unit_bits = 22,
};
EXPORT_SYMBOL_GPL(pwm_lpss_tng_info);
static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
{ {
return container_of(chip, struct pwm_lpss_chip, chip); return container_of(chip, struct pwm_lpss_chip, chip);
@ -207,7 +244,7 @@ static const struct pwm_ops pwm_lpss_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, void __iomem *base,
const struct pwm_lpss_boardinfo *info) const struct pwm_lpss_boardinfo *info)
{ {
struct pwm_lpss_chip *lpwm; struct pwm_lpss_chip *lpwm;
@ -222,10 +259,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
if (!lpwm) if (!lpwm)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
lpwm->regs = devm_ioremap_resource(dev, r); lpwm->regs = base;
if (IS_ERR(lpwm->regs))
return ERR_CAST(lpwm->regs);
lpwm->info = info; lpwm->info = info;
c = lpwm->info->clk_rate; c = lpwm->info->clk_rate;

View File

@ -25,6 +25,11 @@ struct pwm_lpss_boardinfo {
unsigned long clk_rate; unsigned long clk_rate;
unsigned int npwm; unsigned int npwm;
unsigned long base_unit_bits; unsigned long base_unit_bits;
/*
* Some versions of the IP may stuck in the state machine if enable
* bit is not set, and hence update bit will show busy status till
* the reset. For the rest it may be otherwise.
*/
bool bypass; bool bypass;
/* /*
* On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device * On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device
@ -33,7 +38,12 @@ struct pwm_lpss_boardinfo {
bool other_devices_aml_touches_pwm_regs; bool other_devices_aml_touches_pwm_regs;
}; };
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
extern const struct pwm_lpss_boardinfo pwm_lpss_bsw_info;
extern const struct pwm_lpss_boardinfo pwm_lpss_bxt_info;
extern const struct pwm_lpss_boardinfo pwm_lpss_tng_info;
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, void __iomem *base,
const struct pwm_lpss_boardinfo *info); const struct pwm_lpss_boardinfo *info);
#endif /* __PWM_LPSS_H */ #endif /* __PWM_LPSS_H */

View File

@ -328,22 +328,16 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
else else
pc->pclk = pc->clk; pc->pclk = pc->clk;
if (IS_ERR(pc->pclk)) { if (IS_ERR(pc->pclk))
ret = PTR_ERR(pc->pclk); return dev_err_probe(&pdev->dev, PTR_ERR(pc->pclk), "Can't get APB clk\n");
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "Can't get APB clk: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(pc->clk); ret = clk_prepare_enable(pc->clk);
if (ret) { if (ret)
dev_err(&pdev->dev, "Can't prepare enable PWM clk: %d\n", ret); return dev_err_probe(&pdev->dev, ret, "Can't prepare enable PWM clk\n");
return ret;
}
ret = clk_prepare_enable(pc->pclk); ret = clk_prepare_enable(pc->pclk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); dev_err_probe(&pdev->dev, ret, "Can't prepare enable APB clk\n");
goto err_clk; goto err_clk;
} }
@ -360,7 +354,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
ret = pwmchip_add(&pc->chip); ret = pwmchip_add(&pc->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
goto err_pclk; goto err_pclk;
} }

View File

@ -42,7 +42,7 @@ static ssize_t period_show(struct device *child,
pwm_get_state(pwm, &state); pwm_get_state(pwm, &state);
return sprintf(buf, "%llu\n", state.period); return sysfs_emit(buf, "%llu\n", state.period);
} }
static ssize_t period_store(struct device *child, static ssize_t period_store(struct device *child,
@ -77,7 +77,7 @@ static ssize_t duty_cycle_show(struct device *child,
pwm_get_state(pwm, &state); pwm_get_state(pwm, &state);
return sprintf(buf, "%llu\n", state.duty_cycle); return sysfs_emit(buf, "%llu\n", state.duty_cycle);
} }
static ssize_t duty_cycle_store(struct device *child, static ssize_t duty_cycle_store(struct device *child,
@ -112,7 +112,7 @@ static ssize_t enable_show(struct device *child,
pwm_get_state(pwm, &state); pwm_get_state(pwm, &state);
return sprintf(buf, "%d\n", state.enabled); return sysfs_emit(buf, "%d\n", state.enabled);
} }
static ssize_t enable_store(struct device *child, static ssize_t enable_store(struct device *child,
@ -171,7 +171,7 @@ static ssize_t polarity_show(struct device *child,
break; break;
} }
return sprintf(buf, "%s\n", polarity); return sysfs_emit(buf, "%s\n", polarity);
} }
static ssize_t polarity_store(struct device *child, static ssize_t polarity_store(struct device *child,
@ -212,7 +212,7 @@ static ssize_t capture_show(struct device *child,
if (ret) if (ret)
return ret; return ret;
return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); return sysfs_emit(buf, "%u %u\n", result.period, result.duty_cycle);
} }
static DEVICE_ATTR_RW(period); static DEVICE_ATTR_RW(period);
@ -361,7 +361,7 @@ static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
{ {
const struct pwm_chip *chip = dev_get_drvdata(parent); const struct pwm_chip *chip = dev_get_drvdata(parent);
return sprintf(buf, "%u\n", chip->npwm); return sysfs_emit(buf, "%u\n", chip->npwm);
} }
static DEVICE_ATTR_RO(npwm); static DEVICE_ATTR_RO(npwm);
@ -433,7 +433,7 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm)
return ret; return ret;
} }
static int __maybe_unused pwm_class_suspend(struct device *parent) static int pwm_class_suspend(struct device *parent)
{ {
struct pwm_chip *chip = dev_get_drvdata(parent); struct pwm_chip *chip = dev_get_drvdata(parent);
unsigned int i; unsigned int i;
@ -464,20 +464,20 @@ static int __maybe_unused pwm_class_suspend(struct device *parent)
return ret; return ret;
} }
static int __maybe_unused pwm_class_resume(struct device *parent) static int pwm_class_resume(struct device *parent)
{ {
struct pwm_chip *chip = dev_get_drvdata(parent); struct pwm_chip *chip = dev_get_drvdata(parent);
return pwm_class_resume_npwm(parent, chip->npwm); return pwm_class_resume_npwm(parent, chip->npwm);
} }
static SIMPLE_DEV_PM_OPS(pwm_class_pm_ops, pwm_class_suspend, pwm_class_resume); static DEFINE_SIMPLE_DEV_PM_OPS(pwm_class_pm_ops, pwm_class_suspend, pwm_class_resume);
static struct class pwm_class = { static struct class pwm_class = {
.name = "pwm", .name = "pwm",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.dev_groups = pwm_chip_groups, .dev_groups = pwm_chip_groups,
.pm = &pwm_class_pm_ops, .pm = pm_sleep_ptr(&pwm_class_pm_ops),
}; };
static int pwmchip_sysfs_match(struct device *parent, const void *data) static int pwmchip_sysfs_match(struct device *parent, const void *data)