Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
7755daf5
Commit
7755daf5
authored
Aug 21, 2017
by
Thierry Reding
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.14/drivers' into for-next
parents
5771a8c0
08a4d8ec
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
699 additions
and
307 deletions
+699
-307
Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
+2
-2
Documentation/devicetree/bindings/pwm/pwm-mediatek.txt
Documentation/devicetree/bindings/pwm/pwm-mediatek.txt
+5
-1
Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
+9
-2
Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+1
-0
Documentation/devicetree/bindings/pwm/pwm-zx.txt
Documentation/devicetree/bindings/pwm/pwm-zx.txt
+22
-0
Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt
Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt
+0
-1
drivers/pwm/Kconfig
drivers/pwm/Kconfig
+11
-2
drivers/pwm/Makefile
drivers/pwm/Makefile
+1
-0
drivers/pwm/pwm-bcm2835.c
drivers/pwm/pwm-bcm2835.c
+2
-0
drivers/pwm/pwm-hibvt.c
drivers/pwm/pwm-hibvt.c
+1
-1
drivers/pwm/pwm-mediatek.c
drivers/pwm/pwm-mediatek.c
+54
-24
drivers/pwm/pwm-meson.c
drivers/pwm/pwm-meson.c
+1
-1
drivers/pwm/pwm-pca9685.c
drivers/pwm/pwm-pca9685.c
+7
-7
drivers/pwm/pwm-renesas-tpu.c
drivers/pwm/pwm-renesas-tpu.c
+0
-1
drivers/pwm/pwm-rockchip.c
drivers/pwm/pwm-rockchip.c
+147
-134
drivers/pwm/pwm-samsung.c
drivers/pwm/pwm-samsung.c
+35
-35
drivers/pwm/pwm-tegra.c
drivers/pwm/pwm-tegra.c
+1
-1
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiecap.c
+48
-42
drivers/pwm/pwm-tiehrpwm.c
drivers/pwm/pwm-tiehrpwm.c
+69
-53
drivers/pwm/pwm-vt8500.c
drivers/pwm/pwm-vt8500.c
+1
-0
drivers/pwm/pwm-zx.c
drivers/pwm/pwm-zx.c
+282
-0
No files found.
Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
View file @
7755daf5
...
@@ -6,7 +6,7 @@ Required properties:
...
@@ -6,7 +6,7 @@ Required properties:
- clocks: This clock defines the base clock frequency of the PWM hardware
- clocks: This clock defines the base clock frequency of the PWM hardware
system, the period and the duty_cycle of the PWM signal is a multiple of
system, the period and the duty_cycle of the PWM signal is a multiple of
the base period.
the base period.
- #pwm-cells: Should be
2
. 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.
Examples:
Examples:
...
@@ -15,7 +15,7 @@ pwm@2020c000 {
...
@@ -15,7 +15,7 @@ pwm@2020c000 {
compatible = "brcm,bcm2835-pwm";
compatible = "brcm,bcm2835-pwm";
reg = <0x2020c000 0x28>;
reg = <0x2020c000 0x28>;
clocks = <&clk_pwm>;
clocks = <&clk_pwm>;
#pwm-cells = <
2
>;
#pwm-cells = <
3
>;
};
};
clocks {
clocks {
...
...
Documentation/devicetree/bindings/pwm/pwm-mediatek.txt
View file @
7755daf5
...
@@ -2,6 +2,8 @@ MediaTek PWM controller
...
@@ -2,6 +2,8 @@ MediaTek PWM controller
Required properties:
Required properties:
- compatible: should be "mediatek,<name>-pwm":
- compatible: should be "mediatek,<name>-pwm":
- "mediatek,mt2712-pwm": found on mt2712 SoC.
- "mediatek,mt7622-pwm": found on mt7622 SoC.
- "mediatek,mt7623-pwm": found on mt7623 SoC.
- "mediatek,mt7623-pwm": found on mt7623 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
...
@@ -10,7 +12,9 @@ Required properties:
...
@@ -10,7 +12,9 @@ Required properties:
- clock-names: must contain the following:
- clock-names: must contain the following:
- "top": the top clock generator
- "top": the top clock generator
- "main": clock used by the PWM core
- "main": clock used by the PWM core
- "pwm1-5": the five per PWM clocks
- "pwm1-8": the eight per PWM clocks for mt2712
- "pwm1-6": the six per PWM clocks for mt7622
- "pwm1-5": the five per PWM clocks for mt7623
- pinctrl-names: Must contain a "default" entry.
- pinctrl-names: Must contain a "default" entry.
- pinctrl-0: One property must exist for each entry in pinctrl-names.
- pinctrl-0: One property must exist for each entry in pinctrl-names.
See pinctrl/pinctrl-bindings.txt for details of the property values.
See pinctrl/pinctrl-bindings.txt for details of the property values.
...
...
Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
View file @
7755daf5
...
@@ -3,10 +3,17 @@ Rockchip PWM controller
...
@@ -3,10 +3,17 @@ Rockchip PWM controller
Required properties:
Required properties:
- compatible: should be "rockchip,<name>-pwm"
- compatible: should be "rockchip,<name>-pwm"
"rockchip,rk2928-pwm": found on RK29XX,RK3066 and RK3188 SoCs
"rockchip,rk2928-pwm": found on RK29XX,RK3066 and RK3188 SoCs
"rockchip,rk3288-pwm": found on RK3288 SoC
"rockchip,rk3288-pwm": found on RK3288 SOC
"rockchip,rv1108-pwm", "rockchip,rk3288-pwm": found on RV1108 SoC
"rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
"rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
- reg: physical base address and length of the controller's registers
- reg: physical base address and length of the controller's registers
- clocks: phandle and clock specifier of the PWM reference clock
- clocks: See ../clock/clock-bindings.txt
- For older hardware (rk2928, rk3066, rk3188, rk3228, rk3288, rk3399):
- There is one clock that's used both to derive the functional clock
for the device and as the bus clock.
- For newer hardware (rk3328 and future socs): specified by name
- "pwm": This is used to derive the functional clock.
- "pclk": This is the APB bus clock.
- #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
- #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
for a description of the cell format.
for a description of the cell format.
...
...
Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
View file @
7755daf5
...
@@ -6,6 +6,7 @@ Required properties:
...
@@ -6,6 +6,7 @@ Required properties:
for am4372 - compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
for am4372 - compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap";
for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap";
for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap";
- #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 PWM channel index ranges from 0 to 4. The only third
the cells format. The PWM channel index ranges from 0 to 4. The only third
cell flag supported by this binding is PWM_POLARITY_INVERTED.
cell flag supported by this binding is PWM_POLARITY_INVERTED.
...
...
Documentation/devicetree/bindings/pwm/pwm-zx.txt
0 → 100644
View file @
7755daf5
ZTE ZX PWM controller
Required properties:
- compatible: Should be "zte,zx296718-pwm".
- reg: Physical base address and length of the controller's registers.
- clocks : The phandle and specifier referencing the controller's clocks.
- clock-names: "pclk" for PCLK, "wclk" for WCLK to the PWM controller. The
PCLK is for register access, while WCLK is the reference clock for
calculating period and duty cycles.
- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
the cells format.
Example:
pwm: pwm@1439000 {
compatible = "zte,zx296718-pwm";
reg = <0x1439000 0x1000>;
clocks = <&lsp1crm LSP1_PWM_PCLK>,
<&lsp1crm LSP1_PWM_WCLK>;
clock-names = "pclk", "wclk";
#pwm-cells = <3>;
};
Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt
View file @
7755daf5
...
@@ -6,7 +6,6 @@ Required Properties:
...
@@ -6,7 +6,6 @@ Required Properties:
- "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller.
- "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller.
- "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller.
- "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller.
- "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller.
- "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller.
- "renesas,tpu-sh7372": for SH7372 (SH-Mobile AP4) compatible PWM controller.
- "renesas,tpu": for generic R-Car TPU PWM controller.
- "renesas,tpu": for generic R-Car TPU PWM controller.
- reg: Base address and length of each memory resource used by the PWM
- reg: Base address and length of each memory resource used by the PWM
...
...
drivers/pwm/Kconfig
View file @
7755daf5
...
@@ -300,7 +300,7 @@ config PWM_MEDIATEK
...
@@ -300,7 +300,7 @@ config PWM_MEDIATEK
Generic PWM framework driver for Mediatek ARM SoC.
Generic PWM framework driver for Mediatek ARM SoC.
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-m
xs
.
will be called pwm-m
ediatek
.
config PWM_MXS
config PWM_MXS
tristate "Freescale MXS PWM support"
tristate "Freescale MXS PWM support"
...
@@ -446,7 +446,7 @@ config PWM_TEGRA
...
@@ -446,7 +446,7 @@ config PWM_TEGRA
config PWM_TIECAP
config PWM_TIECAP
tristate "ECAP PWM support"
tristate "ECAP PWM support"
depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX
depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX
|| ARCH_KEYSTONE
help
help
PWM driver support for the ECAP APWM controller found on AM33XX
PWM driver support for the ECAP APWM controller found on AM33XX
TI SOC
TI SOC
...
@@ -500,4 +500,13 @@ config PWM_VT8500
...
@@ -500,4 +500,13 @@ config PWM_VT8500
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-vt8500.
will be called pwm-vt8500.
config PWM_ZX
tristate "ZTE ZX PWM support"
depends on ARCH_ZX
help
Generic PWM framework driver for ZTE ZX family SoCs.
To compile this driver as a module, choose M here: the module
will be called pwm-zx.
endif
endif
drivers/pwm/Makefile
View file @
7755daf5
...
@@ -49,3 +49,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o
...
@@ -49,3 +49,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o
obj-$(CONFIG_PWM_TWL)
+=
pwm-twl.o
obj-$(CONFIG_PWM_TWL)
+=
pwm-twl.o
obj-$(CONFIG_PWM_TWL_LED)
+=
pwm-twl-led.o
obj-$(CONFIG_PWM_TWL_LED)
+=
pwm-twl-led.o
obj-$(CONFIG_PWM_VT8500)
+=
pwm-vt8500.o
obj-$(CONFIG_PWM_VT8500)
+=
pwm-vt8500.o
obj-$(CONFIG_PWM_ZX)
+=
pwm-zx.o
drivers/pwm/pwm-bcm2835.c
View file @
7755daf5
...
@@ -167,6 +167,8 @@ static int bcm2835_pwm_probe(struct platform_device *pdev)
...
@@ -167,6 +167,8 @@ static int bcm2835_pwm_probe(struct platform_device *pdev)
pc
->
chip
.
dev
=
&
pdev
->
dev
;
pc
->
chip
.
dev
=
&
pdev
->
dev
;
pc
->
chip
.
ops
=
&
bcm2835_pwm_ops
;
pc
->
chip
.
ops
=
&
bcm2835_pwm_ops
;
pc
->
chip
.
npwm
=
2
;
pc
->
chip
.
npwm
=
2
;
pc
->
chip
.
of_xlate
=
of_pwm_xlate_with_flags
;
pc
->
chip
.
of_pwm_n_cells
=
3
;
platform_set_drvdata
(
pdev
,
pc
);
platform_set_drvdata
(
pdev
,
pc
);
...
...
drivers/pwm/pwm-hibvt.c
View file @
7755daf5
...
@@ -208,7 +208,7 @@ static int hibvt_pwm_probe(struct platform_device *pdev)
...
@@ -208,7 +208,7 @@ static int hibvt_pwm_probe(struct platform_device *pdev)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
pwm_chip
->
rstc
=
devm_reset_control_get
(
&
pdev
->
dev
,
NULL
);
pwm_chip
->
rstc
=
devm_reset_control_get
_exclusive
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
pwm_chip
->
rstc
))
{
if
(
IS_ERR
(
pwm_chip
->
rstc
))
{
clk_disable_unprepare
(
pwm_chip
->
clk
);
clk_disable_unprepare
(
pwm_chip
->
clk
);
return
PTR_ERR
(
pwm_chip
->
rstc
);
return
PTR_ERR
(
pwm_chip
->
rstc
);
...
...
drivers/pwm/pwm-mediatek.c
View file @
7755daf5
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
* Mediatek Pulse Width Modulator driver
* Mediatek Pulse Width Modulator driver
*
*
* Copyright (C) 2015 John Crispin <blogic@openwrt.org>
* Copyright (C) 2015 John Crispin <blogic@openwrt.org>
* Copyright (C) 2017 Zhi Mao <zhi.mao@mediatek.com>
*
*
* This file is licensed under the terms of the GNU General Public
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* License version 2. This program is licensed "as is" without any
...
@@ -29,6 +30,8 @@
...
@@ -29,6 +30,8 @@
#define PWMDWIDTH 0x2c
#define PWMDWIDTH 0x2c
#define PWMTHRES 0x30
#define PWMTHRES 0x30
#define PWM_CLK_DIV_MAX 7
enum
{
enum
{
MTK_CLK_MAIN
=
0
,
MTK_CLK_MAIN
=
0
,
MTK_CLK_TOP
,
MTK_CLK_TOP
,
...
@@ -61,6 +64,42 @@ static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip)
...
@@ -61,6 +64,42 @@ static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip)
return
container_of
(
chip
,
struct
mtk_pwm_chip
,
chip
);
return
container_of
(
chip
,
struct
mtk_pwm_chip
,
chip
);
}
}
static
int
mtk_pwm_clk_enable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
struct
mtk_pwm_chip
*
pc
=
to_mtk_pwm_chip
(
chip
);
int
ret
;
ret
=
clk_prepare_enable
(
pc
->
clks
[
MTK_CLK_TOP
]);
if
(
ret
<
0
)
return
ret
;
ret
=
clk_prepare_enable
(
pc
->
clks
[
MTK_CLK_MAIN
]);
if
(
ret
<
0
)
goto
disable_clk_top
;
ret
=
clk_prepare_enable
(
pc
->
clks
[
MTK_CLK_PWM1
+
pwm
->
hwpwm
]);
if
(
ret
<
0
)
goto
disable_clk_main
;
return
0
;
disable_clk_main:
clk_disable_unprepare
(
pc
->
clks
[
MTK_CLK_MAIN
]);
disable_clk_top:
clk_disable_unprepare
(
pc
->
clks
[
MTK_CLK_TOP
]);
return
ret
;
}
static
void
mtk_pwm_clk_disable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
struct
mtk_pwm_chip
*
pc
=
to_mtk_pwm_chip
(
chip
);
clk_disable_unprepare
(
pc
->
clks
[
MTK_CLK_PWM1
+
pwm
->
hwpwm
]);
clk_disable_unprepare
(
pc
->
clks
[
MTK_CLK_MAIN
]);
clk_disable_unprepare
(
pc
->
clks
[
MTK_CLK_TOP
]);
}
static
inline
u32
mtk_pwm_readl
(
struct
mtk_pwm_chip
*
chip
,
unsigned
int
num
,
static
inline
u32
mtk_pwm_readl
(
struct
mtk_pwm_chip
*
chip
,
unsigned
int
num
,
unsigned
int
offset
)
unsigned
int
offset
)
{
{
...
@@ -80,6 +119,11 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -80,6 +119,11 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
struct
mtk_pwm_chip
*
pc
=
to_mtk_pwm_chip
(
chip
);
struct
mtk_pwm_chip
*
pc
=
to_mtk_pwm_chip
(
chip
);
struct
clk
*
clk
=
pc
->
clks
[
MTK_CLK_PWM1
+
pwm
->
hwpwm
];
struct
clk
*
clk
=
pc
->
clks
[
MTK_CLK_PWM1
+
pwm
->
hwpwm
];
u32
resolution
,
clkdiv
=
0
;
u32
resolution
,
clkdiv
=
0
;
int
ret
;
ret
=
mtk_pwm_clk_enable
(
chip
,
pwm
);
if
(
ret
<
0
)
return
ret
;
resolution
=
NSEC_PER_SEC
/
clk_get_rate
(
clk
);
resolution
=
NSEC_PER_SEC
/
clk_get_rate
(
clk
);
...
@@ -88,13 +132,18 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -88,13 +132,18 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
clkdiv
++
;
clkdiv
++
;
}
}
if
(
clkdiv
>
7
)
if
(
clkdiv
>
PWM_CLK_DIV_MAX
)
{
mtk_pwm_clk_disable
(
chip
,
pwm
);
dev_err
(
chip
->
dev
,
"period %d not supported
\n
"
,
period_ns
);
return
-
EINVAL
;
return
-
EINVAL
;
}
mtk_pwm_writel
(
pc
,
pwm
->
hwpwm
,
PWMCON
,
BIT
(
15
)
|
BIT
(
3
)
|
clkdiv
);
mtk_pwm_writel
(
pc
,
pwm
->
hwpwm
,
PWMCON
,
BIT
(
15
)
|
clkdiv
);
mtk_pwm_writel
(
pc
,
pwm
->
hwpwm
,
PWMDWIDTH
,
period_ns
/
resolution
);
mtk_pwm_writel
(
pc
,
pwm
->
hwpwm
,
PWMDWIDTH
,
period_ns
/
resolution
);
mtk_pwm_writel
(
pc
,
pwm
->
hwpwm
,
PWMTHRES
,
duty_ns
/
resolution
);
mtk_pwm_writel
(
pc
,
pwm
->
hwpwm
,
PWMTHRES
,
duty_ns
/
resolution
);
mtk_pwm_clk_disable
(
chip
,
pwm
);
return
0
;
return
0
;
}
}
...
@@ -104,7 +153,7 @@ static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
...
@@ -104,7 +153,7 @@ static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
u32
value
;
u32
value
;
int
ret
;
int
ret
;
ret
=
clk_prepare
(
pc
->
clks
[
MTK_CLK_PWM1
+
pwm
->
hwpwm
]
);
ret
=
mtk_pwm_clk_enable
(
chip
,
pwm
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -124,7 +173,7 @@ static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
...
@@ -124,7 +173,7 @@ static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
value
&=
~
BIT
(
pwm
->
hwpwm
);
value
&=
~
BIT
(
pwm
->
hwpwm
);
writel
(
value
,
pc
->
regs
);
writel
(
value
,
pc
->
regs
);
clk_unprepare
(
pc
->
clks
[
MTK_CLK_PWM1
+
pwm
->
hwpwm
]
);
mtk_pwm_clk_disable
(
chip
,
pwm
);
}
}
static
const
struct
pwm_ops
mtk_pwm_ops
=
{
static
const
struct
pwm_ops
mtk_pwm_ops
=
{
...
@@ -156,14 +205,6 @@ static int mtk_pwm_probe(struct platform_device *pdev)
...
@@ -156,14 +205,6 @@ static int mtk_pwm_probe(struct platform_device *pdev)
return
PTR_ERR
(
pc
->
clks
[
i
]);
return
PTR_ERR
(
pc
->
clks
[
i
]);
}
}
ret
=
clk_prepare
(
pc
->
clks
[
MTK_CLK_TOP
]);
if
(
ret
<
0
)
return
ret
;
ret
=
clk_prepare
(
pc
->
clks
[
MTK_CLK_MAIN
]);
if
(
ret
<
0
)
goto
disable_clk_top
;
platform_set_drvdata
(
pdev
,
pc
);
platform_set_drvdata
(
pdev
,
pc
);
pc
->
chip
.
dev
=
&
pdev
->
dev
;
pc
->
chip
.
dev
=
&
pdev
->
dev
;
...
@@ -174,26 +215,15 @@ static int mtk_pwm_probe(struct platform_device *pdev)
...
@@ -174,26 +215,15 @@ static int mtk_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
(
&
pdev
->
dev
,
"pwmchip_add() failed: %d
\n
"
,
ret
);
goto
disable_clk_main
;
return
ret
;
}
}
return
0
;
return
0
;
disable_clk_main:
clk_unprepare
(
pc
->
clks
[
MTK_CLK_MAIN
]);
disable_clk_top:
clk_unprepare
(
pc
->
clks
[
MTK_CLK_TOP
]);
return
ret
;
}
}
static
int
mtk_pwm_remove
(
struct
platform_device
*
pdev
)
static
int
mtk_pwm_remove
(
struct
platform_device
*
pdev
)
{
{
struct
mtk_pwm_chip
*
pc
=
platform_get_drvdata
(
pdev
);
struct
mtk_pwm_chip
*
pc
=
platform_get_drvdata
(
pdev
);
unsigned
int
i
;
for
(
i
=
0
;
i
<
pc
->
chip
.
npwm
;
i
++
)
pwm_disable
(
&
pc
->
chip
.
pwms
[
i
]);
return
pwmchip_remove
(
&
pc
->
chip
);
return
pwmchip_remove
(
&
pc
->
chip
);
}
}
...
...
drivers/pwm/pwm-meson.c
View file @
7755daf5
...
@@ -441,7 +441,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
...
@@ -441,7 +441,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
for
(
i
=
0
;
i
<
meson
->
chip
.
npwm
;
i
++
)
{
for
(
i
=
0
;
i
<
meson
->
chip
.
npwm
;
i
++
)
{
struct
meson_pwm_channel
*
channel
=
&
channels
[
i
];
struct
meson_pwm_channel
*
channel
=
&
channels
[
i
];
snprintf
(
name
,
sizeof
(
name
),
"%
s#mux%u"
,
np
->
full_name
,
i
);
snprintf
(
name
,
sizeof
(
name
),
"%
pOF#mux%u"
,
np
,
i
);
init
.
name
=
name
;
init
.
name
=
name
;
init
.
ops
=
&
clk_mux_ops
;
init
.
ops
=
&
clk_mux_ops
;
...
...
drivers/pwm/pwm-pca9685.c
View file @
7755daf5
...
@@ -241,11 +241,11 @@ static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
...
@@ -241,11 +241,11 @@ static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
}
}
#endif
#endif
static
void
pca9685_set_sleep_mode
(
struct
pca9685
*
pca
,
int
sleep
)
static
void
pca9685_set_sleep_mode
(
struct
pca9685
*
pca
,
bool
enable
)
{
{
regmap_update_bits
(
pca
->
regmap
,
PCA9685_MODE1
,
regmap_update_bits
(
pca
->
regmap
,
PCA9685_MODE1
,
MODE1_SLEEP
,
sleep
?
MODE1_SLEEP
:
0
);
MODE1_SLEEP
,
enable
?
MODE1_SLEEP
:
0
);
if
(
!
sleep
)
{
if
(
!
enable
)
{
/* Wait 500us for the oscillator to be back up */
/* Wait 500us for the oscillator to be back up */
udelay
(
500
);
udelay
(
500
);
}
}
...
@@ -272,13 +272,13 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -272,13 +272,13 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* state is guaranteed active here.
* state is guaranteed active here.
*/
*/
/* Put chip into sleep mode */
/* Put chip into sleep mode */
pca9685_set_sleep_mode
(
pca
,
1
);
pca9685_set_sleep_mode
(
pca
,
true
);
/* Change the chip-wide output frequency */
/* Change the chip-wide output frequency */
regmap_write
(
pca
->
regmap
,
PCA9685_PRESCALE
,
prescale
);
regmap_write
(
pca
->
regmap
,
PCA9685_PRESCALE
,
prescale
);
/* Wake the chip up */
/* Wake the chip up */
pca9685_set_sleep_mode
(
pca
,
0
);
pca9685_set_sleep_mode
(
pca
,
false
);
pca
->
period_ns
=
period_ns
;
pca
->
period_ns
=
period_ns
;
}
else
{
}
else
{
...
@@ -534,7 +534,7 @@ static int pca9685_pwm_runtime_suspend(struct device *dev)
...
@@ -534,7 +534,7 @@ static int pca9685_pwm_runtime_suspend(struct device *dev)
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
pca9685
*
pca
=
i2c_get_clientdata
(
client
);
struct
pca9685
*
pca
=
i2c_get_clientdata
(
client
);
pca9685_set_sleep_mode
(
pca
,
1
);
pca9685_set_sleep_mode
(
pca
,
true
);
return
0
;
return
0
;
}
}
...
@@ -543,7 +543,7 @@ static int pca9685_pwm_runtime_resume(struct device *dev)
...
@@ -543,7 +543,7 @@ static int pca9685_pwm_runtime_resume(struct device *dev)
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
pca9685
*
pca
=
i2c_get_clientdata
(
client
);
struct
pca9685
*
pca
=
i2c_get_clientdata
(
client
);
pca9685_set_sleep_mode
(
pca
,
0
);
pca9685_set_sleep_mode
(
pca
,
false
);
return
0
;
return
0
;
}
}
#endif
#endif
...
...
drivers/pwm/pwm-renesas-tpu.c
View file @
7755daf5
...
@@ -455,7 +455,6 @@ static const struct of_device_id tpu_of_table[] = {
...
@@ -455,7 +455,6 @@ static const struct of_device_id tpu_of_table[] = {
{
.
compatible
=
"renesas,tpu-r8a73a4"
,
},
{
.
compatible
=
"renesas,tpu-r8a73a4"
,
},
{
.
compatible
=
"renesas,tpu-r8a7740"
,
},
{
.
compatible
=
"renesas,tpu-r8a7740"
,
},
{
.
compatible
=
"renesas,tpu-r8a7790"
,
},
{
.
compatible
=
"renesas,tpu-r8a7790"
,
},
{
.
compatible
=
"renesas,tpu-sh7372"
,
},
{
.
compatible
=
"renesas,tpu"
,
},
{
.
compatible
=
"renesas,tpu"
,
},
{
},
{
},
};
};
...
...
drivers/pwm/pwm-rockchip.c
View file @
7755daf5
This diff is collapsed.
Click to expand it.
drivers/pwm/pwm-samsung.c
View file @
7755daf5
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
* Copyright (c) 2008 Simtec Electronics
* Copyright (c) 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
* Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
* Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
* Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
*
* PWM driver for Samsung SoCs
* PWM driver for Samsung SoCs
*
*
...
@@ -74,6 +75,7 @@ struct samsung_pwm_channel {
...
@@ -74,6 +75,7 @@ struct samsung_pwm_channel {
* @chip: generic PWM chip
* @chip: generic PWM chip
* @variant: local copy of hardware variant data
* @variant: local copy of hardware variant data
* @inverter_mask: inverter status for all channels - one bit per channel
* @inverter_mask: inverter status for all channels - one bit per channel
* @disabled_mask: disabled status for all channels - one bit per channel
* @base: base address of mapped PWM registers
* @base: base address of mapped PWM registers
* @base_clk: base clock used to drive the timers
* @base_clk: base clock used to drive the timers
* @tclk0: external clock 0 (can be ERR_PTR if not present)
* @tclk0: external clock 0 (can be ERR_PTR if not present)
...
@@ -83,6 +85,7 @@ struct samsung_pwm_chip {
...
@@ -83,6 +85,7 @@ struct samsung_pwm_chip {
struct
pwm_chip
chip
;
struct
pwm_chip
chip
;
struct
samsung_pwm_variant
variant
;
struct
samsung_pwm_variant
variant
;
u8
inverter_mask
;
u8
inverter_mask
;
u8
disabled_mask
;
void
__iomem
*
base
;
void
__iomem
*
base
;
struct
clk
*
base_clk
;
struct
clk
*
base_clk
;
...
@@ -257,6 +260,8 @@ static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
...
@@ -257,6 +260,8 @@ static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
tcon
|=
TCON_START
(
tcon_chan
)
|
TCON_AUTORELOAD
(
tcon_chan
);
tcon
|=
TCON_START
(
tcon_chan
)
|
TCON_AUTORELOAD
(
tcon_chan
);
writel
(
tcon
,
our_chip
->
base
+
REG_TCON
);
writel
(
tcon
,
our_chip
->
base
+
REG_TCON
);
our_chip
->
disabled_mask
&=
~
BIT
(
pwm
->
hwpwm
);
spin_unlock_irqrestore
(
&
samsung_pwm_lock
,
flags
);
spin_unlock_irqrestore
(
&
samsung_pwm_lock
,
flags
);
return
0
;
return
0
;
...
@@ -275,6 +280,8 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
...
@@ -275,6 +280,8 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
tcon
&=
~
TCON_AUTORELOAD
(
tcon_chan
);
tcon
&=
~
TCON_AUTORELOAD
(
tcon_chan
);
writel
(
tcon
,
our_chip
->
base
+
REG_TCON
);
writel
(
tcon
,
our_chip
->
base
+
REG_TCON
);
our_chip
->
disabled_mask
|=
BIT
(
pwm
->
hwpwm
);
spin_unlock_irqrestore
(
&
samsung_pwm_lock
,
flags
);
spin_unlock_irqrestore
(
&
samsung_pwm_lock
,
flags
);
}
}
...
@@ -297,8 +304,8 @@ static void pwm_samsung_manual_update(struct samsung_pwm_chip *chip,
...
@@ -297,8 +304,8 @@ static void pwm_samsung_manual_update(struct samsung_pwm_chip *chip,
spin_unlock_irqrestore
(
&
samsung_pwm_lock
,
flags
);
spin_unlock_irqrestore
(
&
samsung_pwm_lock
,
flags
);
}
}
static
int
pwm_samsung_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
static
int
__
pwm_samsung_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
int
duty_ns
,
int
period_ns
,
bool
force_period
)
{
{
struct
samsung_pwm_chip
*
our_chip
=
to_samsung_pwm_chip
(
chip
);
struct
samsung_pwm_chip
*
our_chip
=
to_samsung_pwm_chip
(
chip
);
struct
samsung_pwm_channel
*
chan
=
pwm_get_chip_data
(
pwm
);
struct
samsung_pwm_channel
*
chan
=
pwm_get_chip_data
(
pwm
);
...
@@ -312,9 +319,6 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -312,9 +319,6 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
if
(
period_ns
>
NSEC_PER_SEC
)
if
(
period_ns
>
NSEC_PER_SEC
)
return
-
ERANGE
;
return
-
ERANGE
;
if
(
period_ns
==
chan
->
period_ns
&&
duty_ns
==
chan
->
duty_ns
)
return
0
;
tcnt
=
readl
(
our_chip
->
base
+
REG_TCNTB
(
pwm
->
hwpwm
));
tcnt
=
readl
(
our_chip
->
base
+
REG_TCNTB
(
pwm
->
hwpwm
));
oldtcmp
=
readl
(
our_chip
->
base
+
REG_TCMPB
(
pwm
->
hwpwm
));
oldtcmp
=
readl
(
our_chip
->
base
+
REG_TCMPB
(
pwm
->
hwpwm
));
...
@@ -322,7 +326,7 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -322,7 +326,7 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
++
tcnt
;
++
tcnt
;
/* Check to see if we are changing the clock rate of the PWM. */
/* Check to see if we are changing the clock rate of the PWM. */
if
(
chan
->
period_ns
!=
period_ns
)
{
if
(
chan
->
period_ns
!=
period_ns
||
force_period
)
{
unsigned
long
tin_rate
;
unsigned
long
tin_rate
;
u32
period
;
u32
period
;
...
@@ -381,6 +385,12 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -381,6 +385,12 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
return
0
;
return
0
;
}
}
static
int
pwm_samsung_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
{
return
__pwm_samsung_config
(
chip
,
pwm
,
duty_ns
,
period_ns
,
false
);
}
static
void
pwm_samsung_set_invert
(
struct
samsung_pwm_chip
*
chip
,
static
void
pwm_samsung_set_invert
(
struct
samsung_pwm_chip
*
chip
,
unsigned
int
channel
,
bool
invert
)
unsigned
int
channel
,
bool
invert
)
{
{
...
@@ -592,51 +602,41 @@ static int pwm_samsung_remove(struct platform_device *pdev)
...
@@ -592,51 +602,41 @@ static int pwm_samsung_remove(struct platform_device *pdev)
}
}
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
static
int
pwm_samsung_
suspend
(
struct
device
*
dev
)
static
int
pwm_samsung_
resume
(
struct
device
*
dev
)
{
{
struct
samsung_pwm_chip
*
chip
=
dev_get_drvdata
(
dev
);
struct
samsung_pwm_chip
*
our_chip
=
dev_get_drvdata
(
dev
);
struct
pwm_chip
*
chip
=
&
our_chip
->
chip
;
unsigned
int
i
;
unsigned
int
i
;
/*
for
(
i
=
0
;
i
<
SAMSUNG_PWM_NUM
;
i
++
)
{
* No one preserves these values during suspend so reset them.
struct
pwm_device
*
pwm
=
&
chip
->
pwms
[
i
];
* Otherwise driver leaves PWM unconfigured if same values are
* passed to pwm_config() next time.
*/
for
(
i
=
0
;
i
<
SAMSUNG_PWM_NUM
;
++
i
)
{
struct
pwm_device
*
pwm
=
&
chip
->
chip
.
pwms
[
i
];
struct
samsung_pwm_channel
*
chan
=
pwm_get_chip_data
(
pwm
);
struct
samsung_pwm_channel
*
chan
=
pwm_get_chip_data
(
pwm
);
if
(
!
chan
)
if
(
!
chan
)
continue
;
continue
;
chan
->
period_ns
=
0
;
if
(
our_chip
->
variant
.
output_mask
&
BIT
(
i
))
chan
->
duty_ns
=
0
;
pwm_samsung_set_invert
(
our_chip
,
i
,
}
our_chip
->
inverter_mask
&
BIT
(
i
));
return
0
;
}
static
int
pwm_samsung_resume
(
struct
device
*
dev
)
if
(
chan
->
period_ns
)
{
{
__pwm_samsung_config
(
chip
,
pwm
,
chan
->
duty_ns
,
struct
samsung_pwm_chip
*
chip
=
dev_get_drvdata
(
dev
);
chan
->
period_ns
,
true
);
unsigned
int
chan
;
/* needed to make PWM disable work on Odroid-XU3 */
pwm_samsung_manual_update
(
our_chip
,
pwm
);
}
/*
if
(
our_chip
->
disabled_mask
&
BIT
(
i
))
* Inverter setting must be preserved across suspend/resume
pwm_samsung_disable
(
chip
,
pwm
);
* as nobody really seems to configure it more than once.
else
*/
pwm_samsung_enable
(
chip
,
pwm
);
for
(
chan
=
0
;
chan
<
SAMSUNG_PWM_NUM
;
++
chan
)
{
if
(
chip
->
variant
.
output_mask
&
BIT
(
chan
))
pwm_samsung_set_invert
(
chip
,
chan
,
chip
->
inverter_mask
&
BIT
(
chan
));
}
}
return
0
;
return
0
;
}
}
#endif
#endif
static
SIMPLE_DEV_PM_OPS
(
pwm_samsung_pm_ops
,
pwm_samsung_suspend
,
static
SIMPLE_DEV_PM_OPS
(
pwm_samsung_pm_ops
,
NULL
,
pwm_samsung_resume
);
pwm_samsung_resume
);
static
struct
platform_driver
pwm_samsung_driver
=
{
static
struct
platform_driver
pwm_samsung_driver
=
{
.
driver
=
{
.
driver
=
{
...
...
drivers/pwm/pwm-tegra.c
View file @
7755daf5
...
@@ -218,7 +218,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
...
@@ -218,7 +218,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
*/
*/
pwm
->
clk_rate
=
clk_get_rate
(
pwm
->
clk
);
pwm
->
clk_rate
=
clk_get_rate
(
pwm
->
clk
);
pwm
->
rst
=
devm_reset_control_get
(
&
pdev
->
dev
,
"pwm"
);
pwm
->
rst
=
devm_reset_control_get
_exclusive
(
&
pdev
->
dev
,
"pwm"
);
if
(
IS_ERR
(
pwm
->
rst
))
{
if
(
IS_ERR
(
pwm
->
rst
))
{
ret
=
PTR_ERR
(
pwm
->
rst
);
ret
=
PTR_ERR
(
pwm
->
rst
);
dev_err
(
&
pdev
->
dev
,
"Reset control is not found: %d
\n
"
,
ret
);
dev_err
(
&
pdev
->
dev
,
"Reset control is not found: %d
\n
"
,
ret
);
...
...
drivers/pwm/pwm-tiecap.c
View file @
7755daf5
...
@@ -39,15 +39,15 @@
...
@@ -39,15 +39,15 @@
#define ECCTL2_TSCTR_FREERUN BIT(4)
#define ECCTL2_TSCTR_FREERUN BIT(4)
struct
ecap_context
{
struct
ecap_context
{
u32
cap3
;
u32
cap3
;
u32
cap4
;
u32
cap4
;
u16
ecctl2
;
u16
ecctl2
;
};
};
struct
ecap_pwm_chip
{
struct
ecap_pwm_chip
{
struct
pwm_chip
chip
;
struct
pwm_chip
chip
;
unsigned
int
clk_rate
;
unsigned
int
clk_rate
;
void
__iomem
*
mmio_base
;
void
__iomem
*
mmio_base
;
struct
ecap_context
ctx
;
struct
ecap_context
ctx
;
};
};
...
@@ -64,9 +64,9 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -64,9 +64,9 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int
duty_ns
,
int
period_ns
)
int
duty_ns
,
int
period_ns
)
{
{
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
u32
period_cycles
,
duty_cycles
;
unsigned
long
long
c
;
unsigned
long
long
c
;
unsigned
long
period_cycles
,
duty_cycles
;
u16
value
;
unsigned
int
reg_val
;
if
(
period_ns
>
NSEC_PER_SEC
)
if
(
period_ns
>
NSEC_PER_SEC
)
return
-
ERANGE
;
return
-
ERANGE
;
...
@@ -74,7 +74,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -74,7 +74,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
c
=
pc
->
clk_rate
;
c
=
pc
->
clk_rate
;
c
=
c
*
period_ns
;
c
=
c
*
period_ns
;
do_div
(
c
,
NSEC_PER_SEC
);
do_div
(
c
,
NSEC_PER_SEC
);
period_cycles
=
(
u
nsigned
long
)
c
;
period_cycles
=
(
u
32
)
c
;
if
(
period_cycles
<
1
)
{
if
(
period_cycles
<
1
)
{
period_cycles
=
1
;
period_cycles
=
1
;
...
@@ -83,17 +83,17 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -83,17 +83,17 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
c
=
pc
->
clk_rate
;
c
=
pc
->
clk_rate
;
c
=
c
*
duty_ns
;
c
=
c
*
duty_ns
;
do_div
(
c
,
NSEC_PER_SEC
);
do_div
(
c
,
NSEC_PER_SEC
);
duty_cycles
=
(
u
nsigned
long
)
c
;
duty_cycles
=
(
u
32
)
c
;
}
}
pm_runtime_get_sync
(
pc
->
chip
.
dev
);
pm_runtime_get_sync
(
pc
->
chip
.
dev
);
reg_val
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
value
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
/* Configure APWM mode & disable sync option */
/* Configure APWM mode & disable sync option */
reg_val
|=
ECCTL2_APWM_MODE
|
ECCTL2_SYNC_SEL_DISA
;
value
|=
ECCTL2_APWM_MODE
|
ECCTL2_SYNC_SEL_DISA
;
writew
(
reg_val
,
pc
->
mmio_base
+
ECCTL2
);
writew
(
value
,
pc
->
mmio_base
+
ECCTL2
);
if
(
!
pwm_is_enabled
(
pwm
))
{
if
(
!
pwm_is_enabled
(
pwm
))
{
/* Update active registers if not running */
/* Update active registers if not running */
...
@@ -110,40 +110,45 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
...
@@ -110,40 +110,45 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
}
}
if
(
!
pwm_is_enabled
(
pwm
))
{
if
(
!
pwm_is_enabled
(
pwm
))
{
reg_val
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
value
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
/* Disable APWM mode to put APWM output Low */
/* Disable APWM mode to put APWM output Low */
reg_val
&=
~
ECCTL2_APWM_MODE
;
value
&=
~
ECCTL2_APWM_MODE
;
writew
(
reg_val
,
pc
->
mmio_base
+
ECCTL2
);
writew
(
value
,
pc
->
mmio_base
+
ECCTL2
);
}
}
pm_runtime_put_sync
(
pc
->
chip
.
dev
);
pm_runtime_put_sync
(
pc
->
chip
.
dev
);
return
0
;
return
0
;
}
}
static
int
ecap_pwm_set_polarity
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
static
int
ecap_pwm_set_polarity
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
enum
pwm_polarity
polarity
)
enum
pwm_polarity
polarity
)
{
{
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
u
nsigned
short
reg_val
;
u
16
value
;
pm_runtime_get_sync
(
pc
->
chip
.
dev
);
pm_runtime_get_sync
(
pc
->
chip
.
dev
);
reg_val
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
value
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
if
(
polarity
==
PWM_POLARITY_INVERSED
)
if
(
polarity
==
PWM_POLARITY_INVERSED
)
/* Duty cycle defines LOW period of PWM */
/* Duty cycle defines LOW period of PWM */
reg_val
|=
ECCTL2_APWM_POL_LOW
;
value
|=
ECCTL2_APWM_POL_LOW
;
else
else
/* Duty cycle defines HIGH period of PWM */
/* Duty cycle defines HIGH period of PWM */
reg_val
&=
~
ECCTL2_APWM_POL_LOW
;
value
&=
~
ECCTL2_APWM_POL_LOW
;
writew
(
value
,
pc
->
mmio_base
+
ECCTL2
);
writew
(
reg_val
,
pc
->
mmio_base
+
ECCTL2
);
pm_runtime_put_sync
(
pc
->
chip
.
dev
);
pm_runtime_put_sync
(
pc
->
chip
.
dev
);
return
0
;
return
0
;
}
}
static
int
ecap_pwm_enable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
static
int
ecap_pwm_enable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
{
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
u
nsigned
int
reg_val
;
u
16
value
;
/* Leave clock enabled on enabling PWM */
/* Leave clock enabled on enabling PWM */
pm_runtime_get_sync
(
pc
->
chip
.
dev
);
pm_runtime_get_sync
(
pc
->
chip
.
dev
);
...
@@ -152,24 +157,25 @@ static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
...
@@ -152,24 +157,25 @@ static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
* Enable 'Free run Time stamp counter mode' to start counter
* Enable 'Free run Time stamp counter mode' to start counter
* and 'APWM mode' to enable APWM output
* and 'APWM mode' to enable APWM output
*/
*/
reg_val
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
value
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
reg_val
|=
ECCTL2_TSCTR_FREERUN
|
ECCTL2_APWM_MODE
;
value
|=
ECCTL2_TSCTR_FREERUN
|
ECCTL2_APWM_MODE
;
writew
(
reg_val
,
pc
->
mmio_base
+
ECCTL2
);
writew
(
value
,
pc
->
mmio_base
+
ECCTL2
);
return
0
;
return
0
;
}
}
static
void
ecap_pwm_disable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
static
void
ecap_pwm_disable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
{
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
struct
ecap_pwm_chip
*
pc
=
to_ecap_pwm_chip
(
chip
);
u
nsigned
int
reg_val
;
u
16
value
;
/*
/*
* Disable 'Free run Time stamp counter mode' to stop counter
* Disable 'Free run Time stamp counter mode' to stop counter
* and 'APWM mode' to put APWM output to low
* and 'APWM mode' to put APWM output to low
*/
*/
reg_val
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
value
=
readw
(
pc
->
mmio_base
+
ECCTL2
);
reg_val
&=
~
(
ECCTL2_TSCTR_FREERUN
|
ECCTL2_APWM_MODE
);
value
&=
~
(
ECCTL2_TSCTR_FREERUN
|
ECCTL2_APWM_MODE
);
writew
(
reg_val
,
pc
->
mmio_base
+
ECCTL2
);
writew
(
value
,
pc
->
mmio_base
+
ECCTL2
);
/* Disable clock on PWM disable */
/* Disable clock on PWM disable */
pm_runtime_put_sync
(
pc
->
chip
.
dev
);
pm_runtime_put_sync
(
pc
->
chip
.
dev
);
...
@@ -184,12 +190,12 @@ static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
...
@@ -184,12 +190,12 @@ static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
}
}
static
const
struct
pwm_ops
ecap_pwm_ops
=
{
static
const
struct
pwm_ops
ecap_pwm_ops
=
{
.
free
=
ecap_pwm_free
,
.
free
=
ecap_pwm_free
,
.
config
=
ecap_pwm_config
,
.
config
=
ecap_pwm_config
,
.
set_polarity
=
ecap_pwm_set_polarity
,
.
set_polarity
=
ecap_pwm_set_polarity
,
.
enable
=
ecap_pwm_enable
,
.
enable
=
ecap_pwm_enable
,
.
disable
=
ecap_pwm_disable
,
.
disable
=
ecap_pwm_disable
,
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
};
};
static
const
struct
of_device_id
ecap_of_match
[]
=
{
static
const
struct
of_device_id
ecap_of_match
[]
=
{
...
@@ -202,10 +208,10 @@ MODULE_DEVICE_TABLE(of, ecap_of_match);
...
@@ -202,10 +208,10 @@ MODULE_DEVICE_TABLE(of, ecap_of_match);
static
int
ecap_pwm_probe
(
struct
platform_device
*
pdev
)
static
int
ecap_pwm_probe
(
struct
platform_device
*
pdev
)
{
{
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
int
ret
;
struct
ecap_pwm_chip
*
pc
;
struct
resource
*
r
;
struct
resource
*
r
;
struct
clk
*
clk
;
struct
clk
*
clk
;
struct
ecap_pwm_chip
*
pc
;
int
ret
;
pc
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
pc
),
GFP_KERNEL
);
pc
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
pc
),
GFP_KERNEL
);
if
(
!
pc
)
if
(
!
pc
)
...
@@ -248,9 +254,9 @@ static int ecap_pwm_probe(struct platform_device *pdev)
...
@@ -248,9 +254,9 @@ static int ecap_pwm_probe(struct platform_device *pdev)
return
ret
;
return
ret
;
}
}
platform_set_drvdata
(
pdev
,
pc
);
pm_runtime_enable
(
&
pdev
->
dev
);
pm_runtime_enable
(
&
pdev
->
dev
);
platform_set_drvdata
(
pdev
,
pc
);
return
0
;
return
0
;
}
}
...
@@ -259,6 +265,7 @@ static int ecap_pwm_remove(struct platform_device *pdev)
...
@@ -259,6 +265,7 @@ static int ecap_pwm_remove(struct platform_device *pdev)
struct
ecap_pwm_chip
*
pc
=
platform_get_drvdata
(
pdev
);
struct
ecap_pwm_chip
*
pc
=
platform_get_drvdata
(
pdev
);
pm_runtime_disable
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
pwmchip_remove
(
&
pc
->
chip
);
return
pwmchip_remove
(
&
pc
->
chip
);
}
}
...
@@ -311,14 +318,13 @@ static SIMPLE_DEV_PM_OPS(ecap_pwm_pm_ops, ecap_pwm_suspend, ecap_pwm_resume);
...
@@ -311,14 +318,13 @@ static SIMPLE_DEV_PM_OPS(ecap_pwm_pm_ops, ecap_pwm_suspend, ecap_pwm_resume);
static
struct
platform_driver
ecap_pwm_driver
=
{
static
struct
platform_driver
ecap_pwm_driver
=
{
.
driver
=
{
.
driver
=
{
.
name
=
"ecap"
,
.
name
=
"ecap"
,
.
of_match_table
=
ecap_of_match
,
.
of_match_table
=
ecap_of_match
,
.
pm
=
&
ecap_pwm_pm_ops
,
.
pm
=
&
ecap_pwm_pm_ops
,
},
},
.
probe
=
ecap_pwm_probe
,
.
probe
=
ecap_pwm_probe
,
.
remove
=
ecap_pwm_remove
,
.
remove
=
ecap_pwm_remove
,
};
};
module_platform_driver
(
ecap_pwm_driver
);
module_platform_driver
(
ecap_pwm_driver
);
MODULE_DESCRIPTION
(
"ECAP PWM driver"
);
MODULE_DESCRIPTION
(
"ECAP PWM driver"
);
...
...
drivers/pwm/pwm-tiehrpwm.c
View file @
7755daf5
This diff is collapsed.
Click to expand it.
drivers/pwm/pwm-vt8500.c
View file @
7755daf5
...
@@ -241,6 +241,7 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
...
@@ -241,6 +241,7 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
ret
=
pwmchip_add
(
&
chip
->
chip
);
ret
=
pwmchip_add
(
&
chip
->
chip
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to add PWM chip
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to add PWM chip
\n
"
);
clk_unprepare
(
chip
->
clk
);
return
ret
;
return
ret
;
}
}
...
...
drivers/pwm/pwm-zx.c
0 → 100644
View file @
7755daf5
/*
* Copyright (C) 2017 Sanechips Technology Co., Ltd.
* Copyright 2017 Linaro Ltd.
*
* 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/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#define ZX_PWM_MODE 0x0
#define ZX_PWM_CLKDIV_SHIFT 2
#define ZX_PWM_CLKDIV_MASK GENMASK(11, 2)
#define ZX_PWM_CLKDIV(x) (((x) << ZX_PWM_CLKDIV_SHIFT) & \
ZX_PWM_CLKDIV_MASK)
#define ZX_PWM_POLAR BIT(1)
#define ZX_PWM_EN BIT(0)
#define ZX_PWM_PERIOD 0x4
#define ZX_PWM_DUTY 0x8
#define ZX_PWM_CLKDIV_MAX 1023
#define ZX_PWM_PERIOD_MAX 65535
struct
zx_pwm_chip
{
struct
pwm_chip
chip
;
struct
clk
*
pclk
;
struct
clk
*
wclk
;
void
__iomem
*
base
;
};
static
inline
struct
zx_pwm_chip
*
to_zx_pwm_chip
(
struct
pwm_chip
*
chip
)
{
return
container_of
(
chip
,
struct
zx_pwm_chip
,
chip
);
}
static
inline
u32
zx_pwm_readl
(
struct
zx_pwm_chip
*
zpc
,
unsigned
int
hwpwm
,
unsigned
int
offset
)
{
return
readl
(
zpc
->
base
+
(
hwpwm
+
1
)
*
0x10
+
offset
);
}
static
inline
void
zx_pwm_writel
(
struct
zx_pwm_chip
*
zpc
,
unsigned
int
hwpwm
,
unsigned
int
offset
,
u32
value
)
{
writel
(
value
,
zpc
->
base
+
(
hwpwm
+
1
)
*
0x10
+
offset
);
}
static
void
zx_pwm_set_mask
(
struct
zx_pwm_chip
*
zpc
,
unsigned
int
hwpwm
,
unsigned
int
offset
,
u32
mask
,
u32
value
)
{
u32
data
;
data
=
zx_pwm_readl
(
zpc
,
hwpwm
,
offset
);
data
&=
~
mask
;
data
|=
value
&
mask
;
zx_pwm_writel
(
zpc
,
hwpwm
,
offset
,
data
);
}
static
void
zx_pwm_get_state
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
struct
pwm_state
*
state
)
{
struct
zx_pwm_chip
*
zpc
=
to_zx_pwm_chip
(
chip
);
unsigned
long
rate
;
unsigned
int
div
;
u32
value
;
u64
tmp
;
value
=
zx_pwm_readl
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
);
if
(
value
&
ZX_PWM_POLAR
)
state
->
polarity
=
PWM_POLARITY_NORMAL
;
else
state
->
polarity
=
PWM_POLARITY_INVERSED
;
if
(
value
&
ZX_PWM_EN
)
state
->
enabled
=
true
;
else
state
->
enabled
=
false
;
div
=
(
value
&
ZX_PWM_CLKDIV_MASK
)
>>
ZX_PWM_CLKDIV_SHIFT
;
rate
=
clk_get_rate
(
zpc
->
wclk
);
tmp
=
zx_pwm_readl
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_PERIOD
);
tmp
*=
div
*
NSEC_PER_SEC
;
state
->
period
=
DIV_ROUND_CLOSEST_ULL
(
tmp
,
rate
);
tmp
=
zx_pwm_readl
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_DUTY
);
tmp
*=
div
*
NSEC_PER_SEC
;
state
->
duty_cycle
=
DIV_ROUND_CLOSEST_ULL
(
tmp
,
rate
);
}
static
int
zx_pwm_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
unsigned
int
duty_ns
,
unsigned
int
period_ns
)
{
struct
zx_pwm_chip
*
zpc
=
to_zx_pwm_chip
(
chip
);
unsigned
int
period_cycles
,
duty_cycles
;
unsigned
long
long
c
;
unsigned
int
div
=
1
;
unsigned
long
rate
;
/* Find out the best divider */
rate
=
clk_get_rate
(
zpc
->
wclk
);
while
(
1
)
{
c
=
rate
/
div
;
c
=
c
*
period_ns
;
do_div
(
c
,
NSEC_PER_SEC
);
if
(
c
<
ZX_PWM_PERIOD_MAX
)
break
;
div
++
;
if
(
div
>
ZX_PWM_CLKDIV_MAX
)
return
-
ERANGE
;
}
/* Calculate duty cycles */
period_cycles
=
c
;
c
*=
duty_ns
;
do_div
(
c
,
period_ns
);
duty_cycles
=
c
;
/*
* If the PWM is being enabled, we have to temporarily disable it
* before configuring the registers.
*/
if
(
pwm_is_enabled
(
pwm
))
zx_pwm_set_mask
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
,
ZX_PWM_EN
,
0
);
/* Set up registers */
zx_pwm_set_mask
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
,
ZX_PWM_CLKDIV_MASK
,
ZX_PWM_CLKDIV
(
div
));
zx_pwm_writel
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_PERIOD
,
period_cycles
);
zx_pwm_writel
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_DUTY
,
duty_cycles
);
/* Re-enable the PWM if needed */
if
(
pwm_is_enabled
(
pwm
))
zx_pwm_set_mask
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
,
ZX_PWM_EN
,
ZX_PWM_EN
);
return
0
;
}
static
int
zx_pwm_apply
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
struct
pwm_state
*
state
)
{
struct
zx_pwm_chip
*
zpc
=
to_zx_pwm_chip
(
chip
);
struct
pwm_state
cstate
;
int
ret
;
pwm_get_state
(
pwm
,
&
cstate
);
if
(
state
->
polarity
!=
cstate
.
polarity
)
zx_pwm_set_mask
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
,
ZX_PWM_POLAR
,
(
state
->
polarity
==
PWM_POLARITY_INVERSED
)
?
0
:
ZX_PWM_POLAR
);
if
(
state
->
period
!=
cstate
.
period
||
state
->
duty_cycle
!=
cstate
.
duty_cycle
)
{
ret
=
zx_pwm_config
(
chip
,
pwm
,
state
->
duty_cycle
,
state
->
period
);
if
(
ret
)
return
ret
;
}
if
(
state
->
enabled
!=
cstate
.
enabled
)
{
if
(
state
->
enabled
)
{
ret
=
clk_prepare_enable
(
zpc
->
wclk
);
if
(
ret
)
return
ret
;
zx_pwm_set_mask
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
,
ZX_PWM_EN
,
ZX_PWM_EN
);
}
else
{
zx_pwm_set_mask
(
zpc
,
pwm
->
hwpwm
,
ZX_PWM_MODE
,
ZX_PWM_EN
,
0
);
clk_disable_unprepare
(
zpc
->
wclk
);
}
}
return
0
;
}
static
const
struct
pwm_ops
zx_pwm_ops
=
{
.
apply
=
zx_pwm_apply
,
.
get_state
=
zx_pwm_get_state
,
.
owner
=
THIS_MODULE
,
};
static
int
zx_pwm_probe
(
struct
platform_device
*
pdev
)
{
struct
zx_pwm_chip
*
zpc
;
struct
resource
*
res
;
unsigned
int
i
;
int
ret
;
zpc
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
zpc
),
GFP_KERNEL
);
if
(
!
zpc
)
return
-
ENOMEM
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
zpc
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
zpc
->
base
))
return
PTR_ERR
(
zpc
->
base
);
zpc
->
pclk
=
devm_clk_get
(
&
pdev
->
dev
,
"pclk"
);
if
(
IS_ERR
(
zpc
->
pclk
))
return
PTR_ERR
(
zpc
->
pclk
);
zpc
->
wclk
=
devm_clk_get
(
&
pdev
->
dev
,
"wclk"
);
if
(
IS_ERR
(
zpc
->
wclk
))
return
PTR_ERR
(
zpc
->
wclk
);
ret
=
clk_prepare_enable
(
zpc
->
pclk
);
if
(
ret
)
return
ret
;
zpc
->
chip
.
dev
=
&
pdev
->
dev
;
zpc
->
chip
.
ops
=
&
zx_pwm_ops
;
zpc
->
chip
.
base
=
-
1
;
zpc
->
chip
.
npwm
=
4
;
zpc
->
chip
.
of_xlate
=
of_pwm_xlate_with_flags
;
zpc
->
chip
.
of_pwm_n_cells
=
3
;
/*
* PWM devices may be enabled by firmware, and let's disable all of
* them initially to save power.
*/
for
(
i
=
0
;
i
<
zpc
->
chip
.
npwm
;
i
++
)
zx_pwm_set_mask
(
zpc
,
i
,
ZX_PWM_MODE
,
ZX_PWM_EN
,
0
);
ret
=
pwmchip_add
(
&
zpc
->
chip
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to add PWM chip: %d
\n
"
,
ret
);
return
ret
;
}
platform_set_drvdata
(
pdev
,
zpc
);
return
0
;
}
static
int
zx_pwm_remove
(
struct
platform_device
*
pdev
)
{
struct
zx_pwm_chip
*
zpc
=
platform_get_drvdata
(
pdev
);
int
ret
;
ret
=
pwmchip_remove
(
&
zpc
->
chip
);
clk_disable_unprepare
(
zpc
->
pclk
);
return
ret
;
}
static
const
struct
of_device_id
zx_pwm_dt_ids
[]
=
{
{
.
compatible
=
"zte,zx296718-pwm"
,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
zx_pwm_dt_ids
);
static
struct
platform_driver
zx_pwm_driver
=
{
.
driver
=
{
.
name
=
"zx-pwm"
,
.
of_match_table
=
zx_pwm_dt_ids
,
},
.
probe
=
zx_pwm_probe
,
.
remove
=
zx_pwm_remove
,
};
module_platform_driver
(
zx_pwm_driver
);
MODULE_ALIAS
(
"platform:zx-pwm"
);
MODULE_AUTHOR
(
"Shawn Guo <shawn.guo@linaro.org>"
);
MODULE_DESCRIPTION
(
"ZTE ZX PWM Driver"
);
MODULE_LICENSE
(
"GPL v2"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment