Commit dc8e6e1e authored by Thierry Reding's avatar Thierry Reding

Merge branch 'for-4.9/drivers' into for-next

parents 51f01e4c 2fbc487d
Amlogic Meson PWM Controller
============================
Required properties:
- compatible: Shall contain "amlogic,meson8b-pwm" or "amlogic,meson-gxbb-pwm".
- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
the cells format.
Optional properties:
- clocks: Could contain one or two parents clocks phandle for each of the two
PWM channels.
- clock-names: Could contain at least the "clkin0" and/or "clkin1" names.
Example:
pwm_ab: pwm@8550 {
compatible = "amlogic,meson-gxbb-pwm";
reg = <0x0 0x08550 0x0 0x10>;
#pwm-cells = <3>;
status = "disabled";
clocks = <&xtal>, <&xtal>;
clock-names = "clkin0", "clkin1";
}
...@@ -2,8 +2,9 @@ MediaTek display PWM controller ...@@ -2,8 +2,9 @@ MediaTek display PWM controller
Required properties: Required properties:
- compatible: should be "mediatek,<name>-disp-pwm": - compatible: should be "mediatek,<name>-disp-pwm":
- "mediatek,mt8173-disp-pwm": found on mt8173 SoC. - "mediatek,mt2701-disp-pwm": found on mt2701 SoC.
- "mediatek,mt6595-disp-pwm": found on mt6595 SoC. - "mediatek,mt6595-disp-pwm": found on mt6595 SoC.
- "mediatek,mt8173-disp-pwm": found on mt8173 SoC.
- reg: physical base address and length of the controller's registers. - reg: physical base address and length of the controller's registers.
- #pwm-cells: must be 2. See pwm.txt in this directory for a description of - #pwm-cells: must be 2. See pwm.txt in this directory for a description of
the cell format. the cell format.
......
...@@ -13,13 +13,14 @@ Required parameters: ...@@ -13,13 +13,14 @@ Required parameters:
- pinctrl-0: List of phandles pointing to pin configuration nodes - pinctrl-0: List of phandles pointing to pin configuration nodes
for PWM module. for PWM module.
For Pinctrl properties, please refer to [1]. For Pinctrl properties, please refer to [1].
- clock-names: Set to "pwm". - clock-names: Valid entries are "pwm" and/or "capture".
- clocks: phandle of the clock used by the PWM module. - clocks: phandle of the clock used by the PWM module.
For Clk properties, please refer to [2]. For Clk properties, please refer to [2].
- interrupts: IRQ for the Capture device
Optional properties: Optional properties:
- st,pwm-num-chan: Number of available channels. If not passed, the driver - st,pwm-num-chan: Number of available PWM channels. Default is 0.
will consider single channel by default. - st,capture-num-chan: Number of available Capture channels. Default is 0.
[1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt [1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
[2] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/clock/clock-bindings.txt
...@@ -38,4 +39,5 @@ pwm1: pwm@fe510000 { ...@@ -38,4 +39,5 @@ pwm1: pwm@fe510000 {
clocks = <&clk_sysin>; clocks = <&clk_sysin>;
clock-names = "pwm"; clock-names = "pwm";
st,pwm-num-chan = <4>; st,pwm-num-chan = <4>;
st,capture-num-chan = <2>;
}; };
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
- "allwinner,sun5i-a10s-pwm" - "allwinner,sun5i-a10s-pwm"
- "allwinner,sun5i-a13-pwm" - "allwinner,sun5i-a13-pwm"
- "allwinner,sun7i-a20-pwm" - "allwinner,sun7i-a20-pwm"
- "allwinner,sun8i-h3-pwm"
- reg: physical base address and length of the controller's registers - reg: physical base address and length of the controller's registers
- #pwm-cells: should be 3. See pwm.txt in this directory for a description of - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
the cells format. the cells format.
......
...@@ -262,6 +262,15 @@ config PWM_LPSS_PLATFORM ...@@ -262,6 +262,15 @@ config PWM_LPSS_PLATFORM
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called pwm-lpss-platform. will be called pwm-lpss-platform.
config PWM_MESON
tristate "Amlogic Meson PWM driver"
depends on ARCH_MESON
help
The platform driver for Amlogic Meson PWM controller.
To compile this driver as a module, choose M here: the module
will be called pwm-meson.
config PWM_MTK_DISP config PWM_MTK_DISP
tristate "MediaTek display PWM driver" tristate "MediaTek display PWM driver"
depends on ARCH_MEDIATEK || COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST
......
...@@ -24,6 +24,7 @@ obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o ...@@ -24,6 +24,7 @@ obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o
obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o
obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
obj-$(CONFIG_PWM_MESON) += pwm-meson.o
obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pwm.h> #include <linux/pwm.h>
#include <linux/slab.h>
#define BERLIN_PWM_EN 0x0 #define BERLIN_PWM_EN 0x0
#define BERLIN_PWM_ENABLE BIT(0) #define BERLIN_PWM_ENABLE BIT(0)
...@@ -27,6 +28,13 @@ ...@@ -27,6 +28,13 @@
#define BERLIN_PWM_TCNT 0xc #define BERLIN_PWM_TCNT 0xc
#define BERLIN_PWM_MAX_TCNT 65535 #define BERLIN_PWM_MAX_TCNT 65535
struct berlin_pwm_channel {
u32 enable;
u32 ctrl;
u32 duty;
u32 tcnt;
};
struct berlin_pwm_chip { struct berlin_pwm_chip {
struct pwm_chip chip; struct pwm_chip chip;
struct clk *clk; struct clk *clk;
...@@ -55,6 +63,25 @@ static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip, ...@@ -55,6 +63,25 @@ static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip,
writel_relaxed(value, chip->base + channel * 0x10 + offset); writel_relaxed(value, chip->base + channel * 0x10 + offset);
} }
static int berlin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct berlin_pwm_channel *channel;
channel = kzalloc(sizeof(*channel), GFP_KERNEL);
if (!channel)
return -ENOMEM;
return pwm_set_chip_data(pwm, channel);
}
static void berlin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct berlin_pwm_channel *channel = pwm_get_chip_data(pwm);
pwm_set_chip_data(pwm, NULL);
kfree(channel);
}
static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
int duty_ns, int period_ns) int duty_ns, int period_ns)
{ {
...@@ -137,6 +164,8 @@ static void berlin_pwm_disable(struct pwm_chip *chip, ...@@ -137,6 +164,8 @@ static void berlin_pwm_disable(struct pwm_chip *chip,
} }
static const struct pwm_ops berlin_pwm_ops = { static const struct pwm_ops berlin_pwm_ops = {
.request = berlin_pwm_request,
.free = berlin_pwm_free,
.config = berlin_pwm_config, .config = berlin_pwm_config,
.set_polarity = berlin_pwm_set_polarity, .set_polarity = berlin_pwm_set_polarity,
.enable = berlin_pwm_enable, .enable = berlin_pwm_enable,
...@@ -204,12 +233,67 @@ static int berlin_pwm_remove(struct platform_device *pdev) ...@@ -204,12 +233,67 @@ static int berlin_pwm_remove(struct platform_device *pdev)
return ret; return ret;
} }
#ifdef CONFIG_PM_SLEEP
static int berlin_pwm_suspend(struct device *dev)
{
struct berlin_pwm_chip *pwm = dev_get_drvdata(dev);
unsigned int i;
for (i = 0; i < pwm->chip.npwm; i++) {
struct berlin_pwm_channel *channel;
channel = pwm_get_chip_data(&pwm->chip.pwms[i]);
if (!channel)
continue;
channel->enable = berlin_pwm_readl(pwm, i, BERLIN_PWM_ENABLE);
channel->ctrl = berlin_pwm_readl(pwm, i, BERLIN_PWM_CONTROL);
channel->duty = berlin_pwm_readl(pwm, i, BERLIN_PWM_DUTY);
channel->tcnt = berlin_pwm_readl(pwm, i, BERLIN_PWM_TCNT);
}
clk_disable_unprepare(pwm->clk);
return 0;
}
static int berlin_pwm_resume(struct device *dev)
{
struct berlin_pwm_chip *pwm = dev_get_drvdata(dev);
unsigned int i;
int ret;
ret = clk_prepare_enable(pwm->clk);
if (ret)
return ret;
for (i = 0; i < pwm->chip.npwm; i++) {
struct berlin_pwm_channel *channel;
channel = pwm_get_chip_data(&pwm->chip.pwms[i]);
if (!channel)
continue;
berlin_pwm_writel(pwm, i, channel->ctrl, BERLIN_PWM_CONTROL);
berlin_pwm_writel(pwm, i, channel->duty, BERLIN_PWM_DUTY);
berlin_pwm_writel(pwm, i, channel->tcnt, BERLIN_PWM_TCNT);
berlin_pwm_writel(pwm, i, channel->enable, BERLIN_PWM_ENABLE);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(berlin_pwm_pm_ops, berlin_pwm_suspend,
berlin_pwm_resume);
static struct platform_driver berlin_pwm_driver = { static struct platform_driver berlin_pwm_driver = {
.probe = berlin_pwm_probe, .probe = berlin_pwm_probe,
.remove = berlin_pwm_remove, .remove = berlin_pwm_remove,
.driver = { .driver = {
.name = "berlin-pwm", .name = "berlin-pwm",
.of_match_table = berlin_pwm_match, .of_match_table = berlin_pwm_match,
.pm = &berlin_pwm_pm_ops,
}, },
}; };
module_platform_driver(berlin_pwm_driver); module_platform_driver(berlin_pwm_driver);
......
...@@ -38,7 +38,7 @@ static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty) ...@@ -38,7 +38,7 @@ static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty)
struct { struct {
struct cros_ec_command msg; struct cros_ec_command msg;
struct ec_params_pwm_set_duty params; struct ec_params_pwm_set_duty params;
} buf; } __packed buf;
struct ec_params_pwm_set_duty *params = &buf.params; struct ec_params_pwm_set_duty *params = &buf.params;
struct cros_ec_command *msg = &buf.msg; struct cros_ec_command *msg = &buf.msg;
...@@ -65,7 +65,7 @@ static int __cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index, ...@@ -65,7 +65,7 @@ static int __cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index,
struct ec_params_pwm_get_duty params; struct ec_params_pwm_get_duty params;
struct ec_response_pwm_get_duty resp; struct ec_response_pwm_get_duty resp;
}; };
} buf; } __packed buf;
struct ec_params_pwm_get_duty *params = &buf.params; struct ec_params_pwm_get_duty *params = &buf.params;
struct ec_response_pwm_get_duty *resp = &buf.resp; struct ec_response_pwm_get_duty *resp = &buf.resp;
struct cros_ec_command *msg = &buf.msg; struct cros_ec_command *msg = &buf.msg;
......
...@@ -413,14 +413,18 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) ...@@ -413,14 +413,18 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
} }
for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) { for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) {
struct lpc18xx_pwm_data *data;
pwm = &lpc18xx_pwm->chip.pwms[i]; pwm = &lpc18xx_pwm->chip.pwms[i];
pwm->chip_data = devm_kzalloc(lpc18xx_pwm->dev,
sizeof(struct lpc18xx_pwm_data), data = devm_kzalloc(lpc18xx_pwm->dev, sizeof(*data),
GFP_KERNEL); GFP_KERNEL);
if (!pwm->chip_data) { if (!data) {
ret = -ENOMEM; ret = -ENOMEM;
goto remove_pwmchip; goto remove_pwmchip;
} }
pwm_set_chip_data(pwm, data);
} }
platform_set_drvdata(pdev, lpc18xx_pwm); platform_set_drvdata(pdev, lpc18xx_pwm);
......
This diff is collapsed.
...@@ -18,30 +18,40 @@ ...@@ -18,30 +18,40 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pwm.h> #include <linux/pwm.h>
#include <linux/slab.h> #include <linux/slab.h>
#define DISP_PWM_EN 0x00 #define DISP_PWM_EN 0x00
#define PWM_ENABLE_MASK BIT(0)
#define DISP_PWM_COMMIT 0x08
#define PWM_COMMIT_MASK BIT(0)
#define DISP_PWM_CON_0 0x10
#define PWM_CLKDIV_SHIFT 16 #define PWM_CLKDIV_SHIFT 16
#define PWM_CLKDIV_MAX 0x3ff #define PWM_CLKDIV_MAX 0x3ff
#define PWM_CLKDIV_MASK (PWM_CLKDIV_MAX << PWM_CLKDIV_SHIFT) #define PWM_CLKDIV_MASK (PWM_CLKDIV_MAX << PWM_CLKDIV_SHIFT)
#define DISP_PWM_CON_1 0x14
#define PWM_PERIOD_BIT_WIDTH 12 #define PWM_PERIOD_BIT_WIDTH 12
#define PWM_PERIOD_MASK ((1 << PWM_PERIOD_BIT_WIDTH) - 1) #define PWM_PERIOD_MASK ((1 << PWM_PERIOD_BIT_WIDTH) - 1)
#define PWM_HIGH_WIDTH_SHIFT 16 #define PWM_HIGH_WIDTH_SHIFT 16
#define PWM_HIGH_WIDTH_MASK (0x1fff << PWM_HIGH_WIDTH_SHIFT) #define PWM_HIGH_WIDTH_MASK (0x1fff << PWM_HIGH_WIDTH_SHIFT)
struct mtk_pwm_data {
u32 enable_mask;
unsigned int con0;
u32 con0_sel;
unsigned int con1;
bool has_commit;
unsigned int commit;
unsigned int commit_mask;
unsigned int bls_debug;
u32 bls_debug_mask;
};
struct mtk_disp_pwm { struct mtk_disp_pwm {
struct pwm_chip chip; struct pwm_chip chip;
const struct mtk_pwm_data *data;
struct clk *clk_main; struct clk *clk_main;
struct clk *clk_mm; struct clk *clk_mm;
void __iomem *base; void __iomem *base;
...@@ -106,12 +116,21 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -106,12 +116,21 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
return err; return err;
} }
mtk_disp_pwm_update_bits(mdp, DISP_PWM_CON_0, PWM_CLKDIV_MASK, mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
PWM_CLKDIV_MASK,
clk_div << PWM_CLKDIV_SHIFT); clk_div << PWM_CLKDIV_SHIFT);
mtk_disp_pwm_update_bits(mdp, DISP_PWM_CON_1, mtk_disp_pwm_update_bits(mdp, mdp->data->con1,
PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK, value); PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK,
mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT, PWM_COMMIT_MASK, 1); value);
mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT, PWM_COMMIT_MASK, 0);
if (mdp->data->has_commit) {
mtk_disp_pwm_update_bits(mdp, mdp->data->commit,
mdp->data->commit_mask,
mdp->data->commit_mask);
mtk_disp_pwm_update_bits(mdp, mdp->data->commit,
mdp->data->commit_mask,
0x0);
}
clk_disable(mdp->clk_mm); clk_disable(mdp->clk_mm);
clk_disable(mdp->clk_main); clk_disable(mdp->clk_main);
...@@ -134,7 +153,8 @@ static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -134,7 +153,8 @@ static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
return err; return err;
} }
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, PWM_ENABLE_MASK, 1); mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
mdp->data->enable_mask);
return 0; return 0;
} }
...@@ -143,7 +163,8 @@ static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -143,7 +163,8 @@ static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{ {
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, PWM_ENABLE_MASK, 0); mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
0x0);
clk_disable(mdp->clk_mm); clk_disable(mdp->clk_mm);
clk_disable(mdp->clk_main); clk_disable(mdp->clk_main);
...@@ -166,6 +187,8 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) ...@@ -166,6 +187,8 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
if (!mdp) if (!mdp)
return -ENOMEM; return -ENOMEM;
mdp->data = of_device_get_match_data(&pdev->dev);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mdp->base = devm_ioremap_resource(&pdev->dev, r); mdp->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(mdp->base)) if (IS_ERR(mdp->base))
...@@ -200,6 +223,19 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) ...@@ -200,6 +223,19 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mdp); platform_set_drvdata(pdev, mdp);
/*
* For MT2701, disable double buffer before writing register
* and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH.
*/
if (!mdp->data->has_commit) {
mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug,
mdp->data->bls_debug_mask,
mdp->data->bls_debug_mask);
mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
mdp->data->con0_sel,
mdp->data->con0_sel);
}
return 0; return 0;
disable_clk_mm: disable_clk_mm:
...@@ -221,9 +257,30 @@ static int mtk_disp_pwm_remove(struct platform_device *pdev) ...@@ -221,9 +257,30 @@ static int mtk_disp_pwm_remove(struct platform_device *pdev)
return ret; return ret;
} }
static const struct mtk_pwm_data mt2701_pwm_data = {
.enable_mask = BIT(16),
.con0 = 0xa8,
.con0_sel = 0x2,
.con1 = 0xac,
.has_commit = false,
.bls_debug = 0xb0,
.bls_debug_mask = 0x3,
};
static const struct mtk_pwm_data mt8173_pwm_data = {
.enable_mask = BIT(0),
.con0 = 0x10,
.con0_sel = 0x0,
.con1 = 0x14,
.has_commit = true,
.commit = 0x8,
.commit_mask = 0x1,
};
static const struct of_device_id mtk_disp_pwm_of_match[] = { static const struct of_device_id mtk_disp_pwm_of_match[] = {
{ .compatible = "mediatek,mt8173-disp-pwm" }, { .compatible = "mediatek,mt2701-disp-pwm", .data = &mt2701_pwm_data},
{ .compatible = "mediatek,mt6595-disp-pwm" }, { .compatible = "mediatek,mt6595-disp-pwm", .data = &mt8173_pwm_data},
{ .compatible = "mediatek,mt8173-disp-pwm", .data = &mt8173_pwm_data},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match); MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match);
......
...@@ -193,9 +193,18 @@ static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *chip, ...@@ -193,9 +193,18 @@ static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *chip,
* divider settings and choose the lowest divisor that can generate * divider settings and choose the lowest divisor that can generate
* frequencies lower than requested. * frequencies lower than requested.
*/ */
for (div = variant->div_base; div < 4; ++div) if (variant->bits < 32) {
if ((rate >> (variant->bits + div)) < freq) /* Only for s3c24xx */
break; for (div = variant->div_base; div < 4; ++div)
if ((rate >> (variant->bits + div)) < freq)
break;
} else {
/*
* Other variants have enough counter bits to generate any
* requested rate, so no need to check higher divisors.
*/
div = variant->div_base;
}
pwm_samsung_set_divisor(chip, chan, BIT(div)); pwm_samsung_set_divisor(chip, chan, BIT(div));
......
This diff is collapsed.
...@@ -284,6 +284,12 @@ static const struct sun4i_pwm_data sun4i_pwm_data_a20 = { ...@@ -284,6 +284,12 @@ static const struct sun4i_pwm_data sun4i_pwm_data_a20 = {
.npwm = 2, .npwm = 2,
}; };
static const struct sun4i_pwm_data sun4i_pwm_data_h3 = {
.has_prescaler_bypass = true,
.has_rdy = true,
.npwm = 1,
};
static const struct of_device_id sun4i_pwm_dt_ids[] = { static const struct of_device_id sun4i_pwm_dt_ids[] = {
{ {
.compatible = "allwinner,sun4i-a10-pwm", .compatible = "allwinner,sun4i-a10-pwm",
...@@ -297,6 +303,9 @@ static const struct of_device_id sun4i_pwm_dt_ids[] = { ...@@ -297,6 +303,9 @@ static const struct of_device_id sun4i_pwm_dt_ids[] = {
}, { }, {
.compatible = "allwinner,sun7i-a20-pwm", .compatible = "allwinner,sun7i-a20-pwm",
.data = &sun4i_pwm_data_a20, .data = &sun4i_pwm_data_a20,
}, {
.compatible = "allwinner,sun8i-h3-pwm",
.data = &sun4i_pwm_data_h3,
}, { }, {
/* sentinel */ /* sentinel */
}, },
......
...@@ -34,7 +34,6 @@ static int pwmss_probe(struct platform_device *pdev) ...@@ -34,7 +34,6 @@ static int pwmss_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
/* Populate all the child nodes here... */ /* Populate all the child nodes here... */
ret = of_platform_populate(node, NULL, NULL, &pdev->dev); ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
...@@ -46,31 +45,13 @@ static int pwmss_probe(struct platform_device *pdev) ...@@ -46,31 +45,13 @@ static int pwmss_probe(struct platform_device *pdev)
static int pwmss_remove(struct platform_device *pdev) static int pwmss_remove(struct platform_device *pdev)
{ {
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int pwmss_suspend(struct device *dev)
{
pm_runtime_put_sync(dev);
return 0;
}
static int pwmss_resume(struct device *dev)
{
pm_runtime_get_sync(dev);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pwmss_pm_ops, pwmss_suspend, pwmss_resume);
static struct platform_driver pwmss_driver = { static struct platform_driver pwmss_driver = {
.driver = { .driver = {
.name = "pwmss", .name = "pwmss",
.pm = &pwmss_pm_ops,
.of_match_table = pwmss_of_match, .of_match_table = pwmss_of_match,
}, },
.probe = pwmss_probe, .probe = pwmss_probe,
......
...@@ -269,6 +269,22 @@ static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ...@@ -269,6 +269,22 @@ static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
goto out; goto out;
} }
val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXEN);
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
if (ret < 0) {
dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
goto out;
}
val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXEN);
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
if (ret < 0) {
dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
goto out;
}
twl->twl6030_toggle3 = val; twl->twl6030_toggle3 = val;
out: out:
mutex_unlock(&twl->mutex); mutex_unlock(&twl->mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment