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
Kirill Smelkov
linux
Commits
38b0a526
Commit
38b0a526
authored
Feb 10, 2017
by
Thierry Reding
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.11/drivers' into for-next
parents
776906ff
326ed314
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
411 additions
and
230 deletions
+411
-230
Documentation/devicetree/bindings/pwm/imx-pwm.txt
Documentation/devicetree/bindings/pwm/imx-pwm.txt
+3
-3
drivers/pwm/Kconfig
drivers/pwm/Kconfig
+3
-1
drivers/pwm/pwm-bfin.c
drivers/pwm/pwm-bfin.c
+1
-1
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-imx.c
+129
-142
drivers/pwm/pwm-lpss-pci.c
drivers/pwm/pwm-lpss-pci.c
+22
-0
drivers/pwm/pwm-lpss-platform.c
drivers/pwm/pwm-lpss-platform.c
+21
-0
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-lpss.c
+67
-65
drivers/pwm/pwm-lpss.h
drivers/pwm/pwm-lpss.h
+0
-4
drivers/pwm/pwm-pca9685.c
drivers/pwm/pwm-pca9685.c
+163
-12
drivers/pwm/pwm-pxa.c
drivers/pwm/pwm-pxa.c
+1
-1
drivers/pwm/pwm-vt8500.c
drivers/pwm/pwm-vt8500.c
+1
-1
No files found.
Documentation/devicetree/bindings/pwm/imx-pwm.txt
View file @
38b0a526
...
...
@@ -6,8 +6,8 @@ Required properties:
- "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1
- "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27
- reg: physical base address and length of the controller's registers
- #pwm-cells:
should be 2. See pwm.txt in this directory for a description of
the cells format.
- #pwm-cells:
2 for i.MX1 and 3 for i.MX27 and newer SoCs. See pwm.txt
in this directory for a description of
the cells format.
- clocks : Clock specifiers for both ipg and per clocks.
- clock-names : Clock names should include both "ipg" and "per"
See the clock consumer binding,
...
...
@@ -17,7 +17,7 @@ See the clock consumer binding,
Example:
pwm1: pwm@53fb4000 {
#pwm-cells = <
2
>;
#pwm-cells = <
3
>;
compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
reg = <0x53fb4000 0x4000>;
clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
...
...
drivers/pwm/Kconfig
View file @
38b0a526
...
...
@@ -76,7 +76,9 @@ config PWM_ATMEL_TCB
config PWM_BCM_IPROC
tristate "iProc PWM support"
depends on ARCH_BCM_IPROC
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on COMMON_CLK
default ARCH_BCM_IPROC
help
Generic PWM framework driver for Broadcom iProc PWM block. This
block is used in Broadcom iProc SoC's.
...
...
drivers/pwm/pwm-bfin.c
View file @
38b0a526
...
...
@@ -103,7 +103,7 @@ static void bfin_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
disable_gptimer
(
priv
->
pin
);
}
static
struct
pwm_ops
bfin_pwm_ops
=
{
static
const
struct
pwm_ops
bfin_pwm_ops
=
{
.
request
=
bfin_pwm_request
,
.
free
=
bfin_pwm_free
,
.
config
=
bfin_pwm_config
,
...
...
drivers/pwm/pwm-imx.c
View file @
38b0a526
...
...
@@ -38,6 +38,7 @@
#define MX3_PWMCR_DOZEEN (1 << 24)
#define MX3_PWMCR_WAITEN (1 << 23)
#define MX3_PWMCR_DBGEN (1 << 22)
#define MX3_PWMCR_POUTC (1 << 18)
#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
#define MX3_PWMCR_CLKSRC_IPG (1 << 16)
#define MX3_PWMCR_SWR (1 << 3)
...
...
@@ -49,15 +50,10 @@
struct
imx_chip
{
struct
clk
*
clk_per
;
struct
clk
*
clk_ipg
;
void
__iomem
*
mmio_base
;
struct
pwm_chip
chip
;
int
(
*
config
)(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
);
void
(
*
set_enable
)(
struct
pwm_chip
*
chip
,
bool
enable
);
};
#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip)
...
...
@@ -91,176 +87,170 @@ static int imx_pwm_config_v1(struct pwm_chip *chip,
return
0
;
}
static
void
imx_pwm_set_enable_v1
(
struct
pwm_chip
*
chip
,
bool
enable
)
static
int
imx_pwm_enable_v1
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
u32
val
;
int
ret
;
val
=
readl
(
imx
->
mmio_base
+
MX1_PWMC
);
if
(
enable
)
val
|=
MX1_PWMC_EN
;
else
val
&=
~
MX1_PWMC_EN
;
ret
=
clk_prepare_enable
(
imx
->
clk_per
);
if
(
ret
<
0
)
return
ret
;
val
=
readl
(
imx
->
mmio_base
+
MX1_PWMC
);
val
|=
MX1_PWMC_EN
;
writel
(
val
,
imx
->
mmio_base
+
MX1_PWMC
);
}
static
int
imx_pwm_config_v2
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
{
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
struct
device
*
dev
=
chip
->
dev
;
unsigned
long
long
c
;
unsigned
long
period_cycles
,
duty_cycles
,
prescale
;
unsigned
int
period_ms
;
bool
enable
=
pwm_is_enabled
(
pwm
);
int
wait_count
=
0
,
fifoav
;
u32
cr
,
sr
;
/*
* i.MX PWMv2 has a 4-word sample FIFO.
* In order to avoid FIFO overflow issue, we do software reset
* to clear all sample FIFO if the controller is disabled or
* wait for a full PWM cycle to get a relinquished FIFO slot
* when the controller is enabled and the FIFO is fully loaded.
*/
if
(
enable
)
{
sr
=
readl
(
imx
->
mmio_base
+
MX3_PWMSR
);
fifoav
=
sr
&
MX3_PWMSR_FIFOAV_MASK
;
if
(
fifoav
==
MX3_PWMSR_FIFOAV_4WORDS
)
{
period_ms
=
DIV_ROUND_UP
(
pwm_get_period
(
pwm
),
NSEC_PER_MSEC
);
msleep
(
period_ms
);
sr
=
readl
(
imx
->
mmio_base
+
MX3_PWMSR
);
if
(
fifoav
==
(
sr
&
MX3_PWMSR_FIFOAV_MASK
))
dev_warn
(
dev
,
"there is no free FIFO slot
\n
"
);
}
}
else
{
writel
(
MX3_PWMCR_SWR
,
imx
->
mmio_base
+
MX3_PWMCR
);
do
{
usleep_range
(
200
,
1000
);
cr
=
readl
(
imx
->
mmio_base
+
MX3_PWMCR
);
}
while
((
cr
&
MX3_PWMCR_SWR
)
&&
(
wait_count
++
<
MX3_PWM_SWR_LOOP
));
if
(
cr
&
MX3_PWMCR_SWR
)
dev_warn
(
dev
,
"software reset timeout
\n
"
);
}
c
=
clk_get_rate
(
imx
->
clk_per
);
c
=
c
*
period_ns
;
do_div
(
c
,
1000000000
);
period_cycles
=
c
;
prescale
=
period_cycles
/
0x10000
+
1
;
period_cycles
/=
prescale
;
c
=
(
unsigned
long
long
)
period_cycles
*
duty_ns
;
do_div
(
c
,
period_ns
);
duty_cycles
=
c
;
/*
* according to imx pwm RM, the real period value should be
* PERIOD value in PWMPR plus 2.
*/
if
(
period_cycles
>
2
)
period_cycles
-=
2
;
else
period_cycles
=
0
;
writel
(
duty_cycles
,
imx
->
mmio_base
+
MX3_PWMSAR
);
writel
(
period_cycles
,
imx
->
mmio_base
+
MX3_PWMPR
);
cr
=
MX3_PWMCR_PRESCALER
(
prescale
)
|
MX3_PWMCR_DOZEEN
|
MX3_PWMCR_WAITEN
|
MX3_PWMCR_DBGEN
|
MX3_PWMCR_CLKSRC_IPG_HIGH
;
if
(
enable
)
cr
|=
MX3_PWMCR_EN
;
writel
(
cr
,
imx
->
mmio_base
+
MX3_PWMCR
);
return
0
;
}
static
void
imx_pwm_
set_enable_v2
(
struct
pwm_chip
*
chip
,
bool
enable
)
static
void
imx_pwm_
disable_v1
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
u32
val
;
val
=
readl
(
imx
->
mmio_base
+
MX3_PWMCR
);
if
(
enable
)
val
|=
MX3_PWMCR_EN
;
else
val
&=
~
MX3_PWMCR_EN
;
val
=
readl
(
imx
->
mmio_base
+
MX1_PWMC
);
val
&=
~
MX1_PWMC_EN
;
writel
(
val
,
imx
->
mmio_base
+
MX1_PWMC
);
writel
(
val
,
imx
->
mmio_base
+
MX3_PWMCR
);
clk_disable_unprepare
(
imx
->
clk_per
);
}
static
int
imx_pwm_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
static
void
imx_pwm_sw_reset
(
struct
pwm_chip
*
chip
)
{
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
int
ret
;
ret
=
clk_prepare_enable
(
imx
->
clk_ipg
);
if
(
ret
)
return
ret
;
struct
device
*
dev
=
chip
->
dev
;
int
wait_count
=
0
;
u32
cr
;
writel
(
MX3_PWMCR_SWR
,
imx
->
mmio_base
+
MX3_PWMCR
);
do
{
usleep_range
(
200
,
1000
);
cr
=
readl
(
imx
->
mmio_base
+
MX3_PWMCR
);
}
while
((
cr
&
MX3_PWMCR_SWR
)
&&
(
wait_count
++
<
MX3_PWM_SWR_LOOP
));
if
(
cr
&
MX3_PWMCR_SWR
)
dev_warn
(
dev
,
"software reset timeout
\n
"
);
}
ret
=
imx
->
config
(
chip
,
pwm
,
duty_ns
,
period_ns
);
static
void
imx_pwm_wait_fifo_slot
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
struct
device
*
dev
=
chip
->
dev
;
unsigned
int
period_ms
;
int
fifoav
;
u32
sr
;
clk_disable_unprepare
(
imx
->
clk_ipg
);
sr
=
readl
(
imx
->
mmio_base
+
MX3_PWMSR
);
fifoav
=
sr
&
MX3_PWMSR_FIFOAV_MASK
;
if
(
fifoav
==
MX3_PWMSR_FIFOAV_4WORDS
)
{
period_ms
=
DIV_ROUND_UP
(
pwm_get_period
(
pwm
),
NSEC_PER_MSEC
);
msleep
(
period_ms
);
return
ret
;
sr
=
readl
(
imx
->
mmio_base
+
MX3_PWMSR
);
if
(
fifoav
==
(
sr
&
MX3_PWMSR_FIFOAV_MASK
))
dev_warn
(
dev
,
"there is no free FIFO slot
\n
"
);
}
}
static
int
imx_pwm_enable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
static
int
imx_pwm_apply_v2
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
struct
pwm_state
*
state
)
{
unsigned
long
period_cycles
,
duty_cycles
,
prescale
;
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
struct
pwm_state
cstate
;
unsigned
long
long
c
;
int
ret
;
u32
cr
;
pwm_get_state
(
pwm
,
&
cstate
);
if
(
state
->
enabled
)
{
c
=
clk_get_rate
(
imx
->
clk_per
);
c
*=
state
->
period
;
do_div
(
c
,
1000000000
);
period_cycles
=
c
;
prescale
=
period_cycles
/
0x10000
+
1
;
period_cycles
/=
prescale
;
c
=
(
unsigned
long
long
)
period_cycles
*
state
->
duty_cycle
;
do_div
(
c
,
state
->
period
);
duty_cycles
=
c
;
/*
* according to imx pwm RM, the real period value should be
* PERIOD value in PWMPR plus 2.
*/
if
(
period_cycles
>
2
)
period_cycles
-=
2
;
else
period_cycles
=
0
;
/*
* Wait for a free FIFO slot if the PWM is already enabled, and
* flush the FIFO if the PWM was disabled and is about to be
* enabled.
*/
if
(
cstate
.
enabled
)
{
imx_pwm_wait_fifo_slot
(
chip
,
pwm
);
}
else
{
ret
=
clk_prepare_enable
(
imx
->
clk_per
);
if
(
ret
)
return
ret
;
imx_pwm_sw_reset
(
chip
);
}
ret
=
clk_prepare_enable
(
imx
->
clk_per
);
if
(
ret
)
return
ret
;
writel
(
duty_cycles
,
imx
->
mmio_base
+
MX3_PWMSAR
);
writel
(
period_cycles
,
imx
->
mmio_base
+
MX3_PWMPR
);
imx
->
set_enable
(
chip
,
true
);
cr
=
MX3_PWMCR_PRESCALER
(
prescale
)
|
MX3_PWMCR_DOZEEN
|
MX3_PWMCR_WAITEN
|
MX3_PWMCR_DBGEN
|
MX3_PWMCR_CLKSRC_IPG_HIGH
|
MX3_PWMCR_EN
;
return
0
;
}
if
(
state
->
polarity
==
PWM_POLARITY_INVERSED
)
cr
|=
MX3_PWMCR_POUTC
;
static
void
imx_pwm_disable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
struct
imx_chip
*
imx
=
to_imx_chip
(
chip
);
writel
(
cr
,
imx
->
mmio_base
+
MX3_PWMCR
);
}
else
if
(
cstate
.
enabled
)
{
writel
(
0
,
imx
->
mmio_base
+
MX3_PWMCR
);
imx
->
set_enable
(
chip
,
false
);
clk_disable_unprepare
(
imx
->
clk_per
);
}
clk_disable_unprepare
(
imx
->
clk_per
)
;
return
0
;
}
static
struct
pwm_ops
imx_pwm_ops
=
{
.
enable
=
imx_pwm_enable
,
.
disable
=
imx_pwm_disable
,
.
config
=
imx_pwm_config
,
static
const
struct
pwm_ops
imx_pwm_ops_v1
=
{
.
enable
=
imx_pwm_enable_v1
,
.
disable
=
imx_pwm_disable_v1
,
.
config
=
imx_pwm_config_v1
,
.
owner
=
THIS_MODULE
,
};
static
const
struct
pwm_ops
imx_pwm_ops_v2
=
{
.
apply
=
imx_pwm_apply_v2
,
.
owner
=
THIS_MODULE
,
};
struct
imx_pwm_data
{
int
(
*
config
)(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
);
void
(
*
set_enable
)(
struct
pwm_chip
*
chip
,
bool
enable
);
bool
polarity_supported
;
const
struct
pwm_ops
*
ops
;
};
static
struct
imx_pwm_data
imx_pwm_data_v1
=
{
.
config
=
imx_pwm_config_v1
,
.
set_enable
=
imx_pwm_set_enable_v1
,
.
ops
=
&
imx_pwm_ops_v1
,
};
static
struct
imx_pwm_data
imx_pwm_data_v2
=
{
.
config
=
imx_pwm_config_v2
,
.
set_enable
=
imx_pwm_set_enable
_v2
,
.
polarity_supported
=
true
,
.
ops
=
&
imx_pwm_ops
_v2
,
};
static
const
struct
of_device_id
imx_pwm_dt_ids
[]
=
{
...
...
@@ -282,6 +272,8 @@ static int imx_pwm_probe(struct platform_device *pdev)
if
(
!
of_id
)
return
-
ENODEV
;
data
=
of_id
->
data
;
imx
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
imx
),
GFP_KERNEL
);
if
(
imx
==
NULL
)
return
-
ENOMEM
;
...
...
@@ -293,27 +285,22 @@ static int imx_pwm_probe(struct platform_device *pdev)
return
PTR_ERR
(
imx
->
clk_per
);
}
imx
->
clk_ipg
=
devm_clk_get
(
&
pdev
->
dev
,
"ipg"
);
if
(
IS_ERR
(
imx
->
clk_ipg
))
{
dev_err
(
&
pdev
->
dev
,
"getting ipg clock failed with %ld
\n
"
,
PTR_ERR
(
imx
->
clk_ipg
));
return
PTR_ERR
(
imx
->
clk_ipg
);
}
imx
->
chip
.
ops
=
&
imx_pwm_ops
;
imx
->
chip
.
ops
=
data
->
ops
;
imx
->
chip
.
dev
=
&
pdev
->
dev
;
imx
->
chip
.
base
=
-
1
;
imx
->
chip
.
npwm
=
1
;
if
(
data
->
polarity_supported
)
{
dev_dbg
(
&
pdev
->
dev
,
"PWM supports output inversion
\n
"
);
imx
->
chip
.
of_xlate
=
of_pwm_xlate_with_flags
;
imx
->
chip
.
of_pwm_n_cells
=
3
;
}
r
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
imx
->
mmio_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
r
);
if
(
IS_ERR
(
imx
->
mmio_base
))
return
PTR_ERR
(
imx
->
mmio_base
);
data
=
of_id
->
data
;
imx
->
config
=
data
->
config
;
imx
->
set_enable
=
data
->
set_enable
;
ret
=
pwmchip_add
(
&
imx
->
chip
);
if
(
ret
<
0
)
return
ret
;
...
...
drivers/pwm/pwm-lpss-pci.c
View file @
38b0a526
...
...
@@ -17,6 +17,27 @@
#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
,
};
static
int
pwm_lpss_probe_pci
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
{
...
...
@@ -80,6 +101,7 @@ static const struct pci_device_id pwm_lpss_pci_ids[] = {
{
PCI_VDEVICE
(
INTEL
,
0x1ac8
),
(
unsigned
long
)
&
pwm_lpss_bxt_info
},
{
PCI_VDEVICE
(
INTEL
,
0x2288
),
(
unsigned
long
)
&
pwm_lpss_bsw_info
},
{
PCI_VDEVICE
(
INTEL
,
0x2289
),
(
unsigned
long
)
&
pwm_lpss_bsw_info
},
{
PCI_VDEVICE
(
INTEL
,
0x31c8
),
(
unsigned
long
)
&
pwm_lpss_bxt_info
},
{
PCI_VDEVICE
(
INTEL
,
0x5ac8
),
(
unsigned
long
)
&
pwm_lpss_bxt_info
},
{
},
};
...
...
drivers/pwm/pwm-lpss-platform.c
View file @
38b0a526
...
...
@@ -18,6 +18,27 @@
#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
,
};
static
int
pwm_lpss_probe_platform
(
struct
platform_device
*
pdev
)
{
const
struct
pwm_lpss_boardinfo
*
info
;
...
...
drivers/pwm/pwm-lpss.c
View file @
38b0a526
...
...
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
...
...
@@ -37,30 +38,6 @@ struct pwm_lpss_chip {
const
struct
pwm_lpss_boardinfo
*
info
;
};
/* 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
,
};
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
,
};
EXPORT_SYMBOL_GPL
(
pwm_lpss_bxt_info
);
static
inline
struct
pwm_lpss_chip
*
to_lpwm
(
struct
pwm_chip
*
chip
)
{
return
container_of
(
chip
,
struct
pwm_lpss_chip
,
chip
);
...
...
@@ -80,17 +57,42 @@ static inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value)
writel
(
value
,
lpwm
->
regs
+
pwm
->
hwpwm
*
PWM_SIZE
+
PWM
);
}
static
void
pwm_lpss_update
(
struct
pwm_device
*
pwm
)
static
int
pwm_lpss_update
(
struct
pwm_device
*
pwm
)
{
struct
pwm_lpss_chip
*
lpwm
=
to_lpwm
(
pwm
->
chip
);
const
void
__iomem
*
addr
=
lpwm
->
regs
+
pwm
->
hwpwm
*
PWM_SIZE
+
PWM
;
const
unsigned
int
ms
=
500
*
USEC_PER_MSEC
;
u32
val
;
int
err
;
pwm_lpss_write
(
pwm
,
pwm_lpss_read
(
pwm
)
|
PWM_SW_UPDATE
);
/* Give it some time to propagate */
usleep_range
(
10
,
50
);
/*
* PWM Configuration register has SW_UPDATE bit that is set when a new
* configuration is written to the register. The bit is automatically
* cleared at the start of the next output cycle by the IP block.
*
* If one writes a new configuration to the register while it still has
* the bit enabled, PWM may freeze. That is, while one can still write
* to the register, it won't have an effect. Thus, we try to sleep long
* enough that the bit gets cleared and make sure the bit is not
* enabled while we update the configuration.
*/
err
=
readl_poll_timeout
(
addr
,
val
,
!
(
val
&
PWM_SW_UPDATE
),
40
,
ms
);
if
(
err
)
dev_err
(
pwm
->
chip
->
dev
,
"PWM_SW_UPDATE was not cleared
\n
"
);
return
err
;
}
static
int
pwm_lpss_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
static
inline
int
pwm_lpss_is_updating
(
struct
pwm_device
*
pwm
)
{
return
(
pwm_lpss_read
(
pwm
)
&
PWM_SW_UPDATE
)
?
-
EBUSY
:
0
;
}
static
void
pwm_lpss_prepare
(
struct
pwm_lpss_chip
*
lpwm
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
{
struct
pwm_lpss_chip
*
lpwm
=
to_lpwm
(
chip
);
unsigned
long
long
on_time_div
;
unsigned
long
c
=
lpwm
->
info
->
clk_rate
,
base_unit_range
;
unsigned
long
long
base_unit
,
freq
=
NSEC_PER_SEC
;
...
...
@@ -102,62 +104,62 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
* The equation is:
* base_unit = round(base_unit_range * freq / c)
*/
base_unit_range
=
BIT
(
lpwm
->
info
->
base_unit_bits
);
base_unit_range
=
BIT
(
lpwm
->
info
->
base_unit_bits
)
-
1
;
freq
*=
base_unit_range
;
base_unit
=
DIV_ROUND_CLOSEST_ULL
(
freq
,
c
);
if
(
duty_ns
<=
0
)
duty_ns
=
1
;
on_time_div
=
255ULL
*
duty_ns
;
do_div
(
on_time_div
,
period_ns
);
on_time_div
=
255ULL
-
on_time_div
;
pm_runtime_get_sync
(
chip
->
dev
);
ctrl
=
pwm_lpss_read
(
pwm
);
ctrl
&=
~
PWM_ON_TIME_DIV_MASK
;
ctrl
&=
~
(
(
base_unit_range
-
1
)
<<
PWM_BASE_UNIT_SHIFT
);
base_unit
&=
(
base_unit_range
-
1
)
;
ctrl
&=
~
(
base_unit_range
<<
PWM_BASE_UNIT_SHIFT
);
base_unit
&=
base_unit_range
;
ctrl
|=
(
u32
)
base_unit
<<
PWM_BASE_UNIT_SHIFT
;
ctrl
|=
on_time_div
;
pwm_lpss_write
(
pwm
,
ctrl
);
/*
* If the PWM is already enabled we need to notify the hardware
* about the change by setting PWM_SW_UPDATE.
*/
if
(
pwm_is_enabled
(
pwm
))
pwm_lpss_update
(
pwm
);
pm_runtime_put
(
chip
->
dev
);
return
0
;
}
static
int
pwm_lpss_enable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
static
int
pwm_lpss_apply
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
struct
pwm_state
*
state
)
{
pm_runtime_get_sync
(
chip
->
dev
);
struct
pwm_lpss_chip
*
lpwm
=
to_lpwm
(
chip
);
int
ret
;
/*
* Hardware must first see PWM_SW_UPDATE before the PWM can be
* enabled.
*/
pwm_lpss_update
(
pwm
);
pwm_lpss_write
(
pwm
,
pwm_lpss_read
(
pwm
)
|
PWM_ENABLE
);
return
0
;
}
if
(
state
->
enabled
)
{
if
(
!
pwm_is_enabled
(
pwm
))
{
pm_runtime_get_sync
(
chip
->
dev
);
ret
=
pwm_lpss_is_updating
(
pwm
);
if
(
ret
)
{
pm_runtime_put
(
chip
->
dev
);
return
ret
;
}
pwm_lpss_prepare
(
lpwm
,
pwm
,
state
->
duty_cycle
,
state
->
period
);
ret
=
pwm_lpss_update
(
pwm
);
if
(
ret
)
{
pm_runtime_put
(
chip
->
dev
);
return
ret
;
}
pwm_lpss_write
(
pwm
,
pwm_lpss_read
(
pwm
)
|
PWM_ENABLE
);
}
else
{
ret
=
pwm_lpss_is_updating
(
pwm
);
if
(
ret
)
return
ret
;
pwm_lpss_prepare
(
lpwm
,
pwm
,
state
->
duty_cycle
,
state
->
period
);
return
pwm_lpss_update
(
pwm
);
}
}
else
if
(
pwm_is_enabled
(
pwm
))
{
pwm_lpss_write
(
pwm
,
pwm_lpss_read
(
pwm
)
&
~
PWM_ENABLE
);
pm_runtime_put
(
chip
->
dev
);
}
static
void
pwm_lpss_disable
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
)
{
pwm_lpss_write
(
pwm
,
pwm_lpss_read
(
pwm
)
&
~
PWM_ENABLE
);
pm_runtime_put
(
chip
->
dev
);
return
0
;
}
static
const
struct
pwm_ops
pwm_lpss_ops
=
{
.
config
=
pwm_lpss_config
,
.
enable
=
pwm_lpss_enable
,
.
disable
=
pwm_lpss_disable
,
.
apply
=
pwm_lpss_apply
,
.
owner
=
THIS_MODULE
,
};
...
...
drivers/pwm/pwm-lpss.h
View file @
38b0a526
...
...
@@ -24,10 +24,6 @@ struct pwm_lpss_boardinfo {
unsigned
long
base_unit_bits
;
};
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
;
struct
pwm_lpss_chip
*
pwm_lpss_probe
(
struct
device
*
dev
,
struct
resource
*
r
,
const
struct
pwm_lpss_boardinfo
*
info
);
int
pwm_lpss_remove
(
struct
pwm_lpss_chip
*
lpwm
);
...
...
drivers/pwm/pwm-pca9685.c
View file @
38b0a526
...
...
@@ -20,8 +20,10 @@
*/
#include <linux/acpi.h>
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/pwm.h>
...
...
@@ -65,7 +67,6 @@
#define PCA9685_MAXCHAN 0x10
#define LED_FULL (1 << 4)
#define MODE1_RESTART (1 << 7)
#define MODE1_SLEEP (1 << 4)
#define MODE2_INVRT (1 << 4)
#define MODE2_OUTDRV (1 << 2)
...
...
@@ -81,6 +82,10 @@ struct pca9685 {
int
active_cnt
;
int
duty_ns
;
int
period_ns
;
#if IS_ENABLED(CONFIG_GPIOLIB)
struct
mutex
lock
;
struct
gpio_chip
gpio
;
#endif
};
static
inline
struct
pca9685
*
to_pca
(
struct
pwm_chip
*
chip
)
...
...
@@ -88,6 +93,151 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip)
return
container_of
(
chip
,
struct
pca9685
,
chip
);
}
#if IS_ENABLED(CONFIG_GPIOLIB)
static
int
pca9685_pwm_gpio_request
(
struct
gpio_chip
*
gpio
,
unsigned
int
offset
)
{
struct
pca9685
*
pca
=
gpiochip_get_data
(
gpio
);
struct
pwm_device
*
pwm
;
mutex_lock
(
&
pca
->
lock
);
pwm
=
&
pca
->
chip
.
pwms
[
offset
];
if
(
pwm
->
flags
&
(
PWMF_REQUESTED
|
PWMF_EXPORTED
))
{
mutex_unlock
(
&
pca
->
lock
);
return
-
EBUSY
;
}
pwm_set_chip_data
(
pwm
,
(
void
*
)
1
);
mutex_unlock
(
&
pca
->
lock
);
return
0
;
}
static
void
pca9685_pwm_gpio_free
(
struct
gpio_chip
*
gpio
,
unsigned
int
offset
)
{
struct
pca9685
*
pca
=
gpiochip_get_data
(
gpio
);
struct
pwm_device
*
pwm
;
mutex_lock
(
&
pca
->
lock
);
pwm
=
&
pca
->
chip
.
pwms
[
offset
];
pwm_set_chip_data
(
pwm
,
NULL
);
mutex_unlock
(
&
pca
->
lock
);
}
static
bool
pca9685_pwm_is_gpio
(
struct
pca9685
*
pca
,
struct
pwm_device
*
pwm
)
{
bool
is_gpio
=
false
;
mutex_lock
(
&
pca
->
lock
);
if
(
pwm
->
hwpwm
>=
PCA9685_MAXCHAN
)
{
unsigned
int
i
;
/*
* Check if any of the GPIOs are requested and in that case
* prevent using the "all LEDs" channel.
*/
for
(
i
=
0
;
i
<
pca
->
gpio
.
ngpio
;
i
++
)
if
(
gpiochip_is_requested
(
&
pca
->
gpio
,
i
))
{
is_gpio
=
true
;
break
;
}
}
else
if
(
pwm_get_chip_data
(
pwm
))
{
is_gpio
=
true
;
}
mutex_unlock
(
&
pca
->
lock
);
return
is_gpio
;
}
static
int
pca9685_pwm_gpio_get
(
struct
gpio_chip
*
gpio
,
unsigned
int
offset
)
{
struct
pca9685
*
pca
=
gpiochip_get_data
(
gpio
);
struct
pwm_device
*
pwm
=
&
pca
->
chip
.
pwms
[
offset
];
unsigned
int
value
;
regmap_read
(
pca
->
regmap
,
LED_N_ON_H
(
pwm
->
hwpwm
),
&
value
);
return
value
&
LED_FULL
;
}
static
void
pca9685_pwm_gpio_set
(
struct
gpio_chip
*
gpio
,
unsigned
int
offset
,
int
value
)
{
struct
pca9685
*
pca
=
gpiochip_get_data
(
gpio
);
struct
pwm_device
*
pwm
=
&
pca
->
chip
.
pwms
[
offset
];
unsigned
int
on
=
value
?
LED_FULL
:
0
;
/* Clear both OFF registers */
regmap_write
(
pca
->
regmap
,
LED_N_OFF_L
(
pwm
->
hwpwm
),
0
);
regmap_write
(
pca
->
regmap
,
LED_N_OFF_H
(
pwm
->
hwpwm
),
0
);
/* Set the full ON bit */
regmap_write
(
pca
->
regmap
,
LED_N_ON_H
(
pwm
->
hwpwm
),
on
);
}
static
int
pca9685_pwm_gpio_get_direction
(
struct
gpio_chip
*
chip
,
unsigned
int
offset
)
{
/* Always out */
return
0
;
}
static
int
pca9685_pwm_gpio_direction_input
(
struct
gpio_chip
*
gpio
,
unsigned
int
offset
)
{
return
-
EINVAL
;
}
static
int
pca9685_pwm_gpio_direction_output
(
struct
gpio_chip
*
gpio
,
unsigned
int
offset
,
int
value
)
{
pca9685_pwm_gpio_set
(
gpio
,
offset
,
value
);
return
0
;
}
/*
* The PCA9685 has a bit for turning the PWM output full off or on. Some
* boards like Intel Galileo actually uses these as normal GPIOs so we
* expose a GPIO chip here which can exclusively take over the underlying
* PWM channel.
*/
static
int
pca9685_pwm_gpio_probe
(
struct
pca9685
*
pca
)
{
struct
device
*
dev
=
pca
->
chip
.
dev
;
mutex_init
(
&
pca
->
lock
);
pca
->
gpio
.
label
=
dev_name
(
dev
);
pca
->
gpio
.
parent
=
dev
;
pca
->
gpio
.
request
=
pca9685_pwm_gpio_request
;
pca
->
gpio
.
free
=
pca9685_pwm_gpio_free
;
pca
->
gpio
.
get_direction
=
pca9685_pwm_gpio_get_direction
;
pca
->
gpio
.
direction_input
=
pca9685_pwm_gpio_direction_input
;
pca
->
gpio
.
direction_output
=
pca9685_pwm_gpio_direction_output
;
pca
->
gpio
.
get
=
pca9685_pwm_gpio_get
;
pca
->
gpio
.
set
=
pca9685_pwm_gpio_set
;
pca
->
gpio
.
base
=
-
1
;
pca
->
gpio
.
ngpio
=
PCA9685_MAXCHAN
;
pca
->
gpio
.
can_sleep
=
true
;
return
devm_gpiochip_add_data
(
dev
,
&
pca
->
gpio
,
pca
);
}
#else
static
inline
bool
pca9685_pwm_is_gpio
(
struct
pca9685
*
pca
,
struct
pwm_device
*
pwm
)
{
return
false
;
}
static
inline
int
pca9685_pwm_gpio_probe
(
struct
pca9685
*
pca
)
{
return
0
;
}
#endif
static
int
pca9685_pwm_config
(
struct
pwm_chip
*
chip
,
struct
pwm_device
*
pwm
,
int
duty_ns
,
int
period_ns
)
{
...
...
@@ -117,16 +267,6 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
udelay
(
500
);
pca
->
period_ns
=
period_ns
;
/*
* If the duty cycle did not change, restart PWM with
* the same duty cycle to period ratio and return.
*/
if
(
duty_ns
==
pca
->
duty_ns
)
{
regmap_update_bits
(
pca
->
regmap
,
PCA9685_MODE1
,
MODE1_RESTART
,
0x1
);
return
0
;
}
}
else
{
dev_err
(
chip
->
dev
,
"prescaler not set: period out of bounds!
\n
"
);
...
...
@@ -264,6 +404,9 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct
pca9685
*
pca
=
to_pca
(
chip
);
if
(
pca9685_pwm_is_gpio
(
pca
,
pwm
))
return
-
EBUSY
;
if
(
pca
->
active_cnt
++
==
0
)
return
regmap_update_bits
(
pca
->
regmap
,
PCA9685_MODE1
,
MODE1_SLEEP
,
0x0
);
...
...
@@ -344,7 +487,15 @@ static int pca9685_pwm_probe(struct i2c_client *client,
pca
->
chip
.
dev
=
&
client
->
dev
;
pca
->
chip
.
base
=
-
1
;
return
pwmchip_add
(
&
pca
->
chip
);
ret
=
pwmchip_add
(
&
pca
->
chip
);
if
(
ret
<
0
)
return
ret
;
ret
=
pca9685_pwm_gpio_probe
(
pca
);
if
(
ret
<
0
)
pwmchip_remove
(
&
pca
->
chip
);
return
ret
;
}
static
int
pca9685_pwm_remove
(
struct
i2c_client
*
client
)
...
...
drivers/pwm/pwm-pxa.c
View file @
38b0a526
...
...
@@ -118,7 +118,7 @@ static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
clk_disable_unprepare
(
pc
->
clk
);
}
static
struct
pwm_ops
pxa_pwm_ops
=
{
static
const
struct
pwm_ops
pxa_pwm_ops
=
{
.
config
=
pxa_pwm_config
,
.
enable
=
pxa_pwm_enable
,
.
disable
=
pxa_pwm_disable
,
...
...
drivers/pwm/pwm-vt8500.c
View file @
38b0a526
...
...
@@ -184,7 +184,7 @@ static int vt8500_pwm_set_polarity(struct pwm_chip *chip,
return
0
;
}
static
struct
pwm_ops
vt8500_pwm_ops
=
{
static
const
struct
pwm_ops
vt8500_pwm_ops
=
{
.
enable
=
vt8500_pwm_enable
,
.
disable
=
vt8500_pwm_disable
,
.
config
=
vt8500_pwm_config
,
...
...
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