mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
pwm: add pwm driver
PD#138714: initial add pwm driver Change-Id: Ief5a3432642b8f2de8fecffaf51b5c055c696078 Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
This commit is contained in:
@@ -13503,3 +13503,10 @@ AMLOGIC CPU hotplug for dvfs and IPA
|
||||
M: Jianxin Pan <jianxin.pan@amlogic.com>
|
||||
F: drivers/amlogic/cpu_hotplug/*
|
||||
|
||||
AMLOGIC PWM DRIVER
|
||||
M: Jian Hu <jian.hu@amlogic.com>
|
||||
F: drivers/amlogic/pwm/*
|
||||
F: include/linux/amlogic/pwm_meson.h
|
||||
F: include/dt-bindings/pwm/meosn.h
|
||||
F: arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts
|
||||
F: arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include "mesongxl.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/gpio/gxl.h>
|
||||
@@ -184,6 +183,36 @@
|
||||
"usb1",
|
||||
"usb1_to_ddr";
|
||||
};
|
||||
|
||||
pwm {
|
||||
compatible = "amlogic, meson-pwm";
|
||||
status = "okay";
|
||||
pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
|
||||
<PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
|
||||
pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
|
||||
<PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
|
||||
<PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
|
||||
<PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
|
||||
reg = <0x0 0xc1108550 0x0 0x30>,
|
||||
<0x0 0xc8100550 0x0 0x10>;
|
||||
clocks = <&xtal>,
|
||||
<&clkc CLKID_VID_PLL>,
|
||||
/*the clock source is not supported now*/
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
clock-names = "xtal",
|
||||
"vid_pll_clk",
|
||||
"fclk_div4",
|
||||
"fclk_div3";
|
||||
clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
|
||||
clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
|
||||
/*all channels use the default clock source XTAL_CLK*/
|
||||
/*and you can shoose it in file dt-bindings/pwm/meson.h*/
|
||||
};
|
||||
};
|
||||
|
||||
&efuse {
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/gpio/gxl.h>
|
||||
#include "mesongxl.dtsi"
|
||||
/ {
|
||||
model = "Amlogic";
|
||||
@@ -183,6 +181,36 @@
|
||||
"usb1",
|
||||
"usb1_to_ddr";
|
||||
};
|
||||
|
||||
pwm {
|
||||
compatible = "amlogic, meson-pwm";
|
||||
status = "okay";
|
||||
pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
|
||||
<PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
|
||||
pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
|
||||
<PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
|
||||
<PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
|
||||
<PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
|
||||
reg = <0x0 0xc1108550 0x0 0x30>,
|
||||
<0x0 0xc8100550 0x0 0x10>;
|
||||
clocks = <&xtal>,
|
||||
<&clkc CLKID_VID_PLL>,
|
||||
/*the clock source is not supported now*/
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
clock-names = "xtal",
|
||||
"vid_pll_clk",
|
||||
"fclk_div4",
|
||||
"fclk_div3";
|
||||
clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
|
||||
clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
|
||||
/*all channels use the default clock source XTAL_CLK*/
|
||||
/*and you can shoose it in file dt-bindings/pwm/meson.h*/
|
||||
};
|
||||
};
|
||||
|
||||
&efuse {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include "mesongxm.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/gpio/gxl.h>
|
||||
@@ -180,6 +179,35 @@
|
||||
"usb1_to_ddr";
|
||||
};
|
||||
|
||||
pwm {
|
||||
compatible = "amlogic, meson-pwm";
|
||||
status = "okay";
|
||||
pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
|
||||
<PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
|
||||
pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
|
||||
<PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
|
||||
<PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
|
||||
<PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
|
||||
reg = <0x0 0xc1108550 0x0 0x30>,
|
||||
<0x0 0xc8100550 0x0 0x10>;
|
||||
clocks = <&xtal>,
|
||||
<&clkc CLKID_VID_PLL>,
|
||||
/*the clock source is not supported now*/
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
clock-names = "xtal",
|
||||
"vid_pll_clk",
|
||||
"fclk_div4",
|
||||
"fclk_div3";
|
||||
clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
|
||||
clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
|
||||
<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
|
||||
/*all channels use the default clock source XTAL_CLK*/
|
||||
/*and you can shoose it in file dt-bindings/pwm/meson.h*/
|
||||
};
|
||||
};
|
||||
|
||||
&efuse {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/reset/amlogic,gxl-reset.h>
|
||||
#include <dt-bindings/clock/amlogic,gxl-clkc.h>
|
||||
#include <dt-bindings/gpio/gxl.h>
|
||||
#include <dt-bindings/pwm/meson.h>
|
||||
/ {
|
||||
cpus:cpus {
|
||||
#address-cells = <2>;
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/reset/amlogic,gxl-reset.h>
|
||||
#include <dt-bindings/clock/amlogic,gxl-clkc.h>
|
||||
#include <dt-bindings/gpio/gxl.h>
|
||||
#include <dt-bindings/pwm/meson.h>
|
||||
|
||||
/ {
|
||||
cpus:cpus {
|
||||
#address-cells = <2>;
|
||||
|
||||
@@ -186,6 +186,7 @@ CONFIG_AMLOGIC_EFUSE=y
|
||||
CONFIG_AMLOGIC_REBOOT=y
|
||||
CONFIG_AMLOGIC_INTERNAL_PHY=y
|
||||
CONFIG_AMLOGIC_CPU_HOTPLUG=y
|
||||
CONFIG_AMLOGIC_PWM=y
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
@@ -278,6 +279,7 @@ CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
|
||||
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_DEVFREQ_GOV_POWERSAVE=y
|
||||
CONFIG_DEVFREQ_GOV_USERSPACE=y
|
||||
CONFIG_PWM=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
|
||||
@@ -47,5 +47,7 @@ source "drivers/amlogic/ethernet/phy/Kconfig"
|
||||
|
||||
source "drivers/amlogic/cpu_hotplug/Kconfig"
|
||||
|
||||
source "drivers/amlogic/pwm/Kconfig"
|
||||
|
||||
endmenu
|
||||
endif
|
||||
|
||||
@@ -42,3 +42,6 @@ obj-$(CONFIG_AMLOGIC_REBOOT) += reboot/
|
||||
obj-$(CONFIG_AMLOGIC_INTERNAL_PHY) += ethernet/phy/
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_CPU_HOTPLUG) += cpu_hotplug/
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_PWM) += pwm/
|
||||
|
||||
|
||||
12
drivers/amlogic/pwm/Kconfig
Normal file
12
drivers/amlogic/pwm/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# PWM configuration
|
||||
#
|
||||
|
||||
|
||||
menuconfig AMLOGIC_PWM
|
||||
bool "Amlogic PWM driver"
|
||||
depends on PWM_SYSFS
|
||||
depends on PWM
|
||||
default n
|
||||
help
|
||||
say y to enable Amlogic PWM driver.
|
||||
5
drivers/amlogic/pwm/Makefile
Normal file
5
drivers/amlogic/pwm/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
#
|
||||
# Makefile for PWM
|
||||
#
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_PWM) += pwm_meson.o pwm_meson_sysfs.o
|
||||
1018
drivers/amlogic/pwm/pwm_meson.c
Normal file
1018
drivers/amlogic/pwm/pwm_meson.c
Normal file
File diff suppressed because it is too large
Load Diff
697
drivers/amlogic/pwm/pwm_meson_sysfs.c
Normal file
697
drivers/amlogic/pwm/pwm_meson_sysfs.c
Normal file
@@ -0,0 +1,697 @@
|
||||
/*
|
||||
* drivers/amlogic/pwm/pwm_meson_sysfs.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "pwm: " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/amlogic/pwm_meson.h>
|
||||
|
||||
|
||||
/**
|
||||
* pwm_constant_enable()
|
||||
* - start a constant PWM output toggling
|
||||
* txl only support 8 channel constant output
|
||||
* @chip: aml_pwm_chip struct
|
||||
* @index: pwm channel to choose,like PWM_A or PWM_B
|
||||
*/
|
||||
int pwm_constant_enable(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
struct aml_pwm_chip *aml_chip = chip;
|
||||
int id = index;
|
||||
void __iomem *reg;
|
||||
unsigned int mask = 0;
|
||||
unsigned int val;
|
||||
|
||||
if ((id < 0) && (id > 7)) {
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"constant,index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case PWM_A:
|
||||
reg = aml_chip->base + REG_MISC_AB;
|
||||
val = 1 << 28;
|
||||
break;
|
||||
case PWM_B:
|
||||
reg = aml_chip->base + REG_MISC_AB;
|
||||
val = 1 << 29;
|
||||
break;
|
||||
case PWM_C:
|
||||
reg = aml_chip->base + REG_MISC_CD;
|
||||
val = 1 << 28;
|
||||
break;
|
||||
case PWM_D:
|
||||
reg = aml_chip->base + REG_MISC_CD;
|
||||
val = 1 << 29;
|
||||
break;
|
||||
case PWM_E:
|
||||
reg = aml_chip->base + REG_MISC_EF;
|
||||
val = 1 << 28;
|
||||
break;
|
||||
case PWM_F:
|
||||
reg = aml_chip->base + REG_MISC_EF;
|
||||
val = 1 << 29;
|
||||
break;
|
||||
case PWM_AO_A:
|
||||
reg = aml_chip->ao_base + REG_MISC_AO_AB;
|
||||
val = 1 << 28;
|
||||
break;
|
||||
case PWM_AO_B:
|
||||
reg = aml_chip->ao_base + REG_MISC_AO_AB;
|
||||
val = 1 << 29;
|
||||
break;
|
||||
default:
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"constant,index is not legal\n");
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
pwm_set_reg_bits(reg, mask, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_constant_enable);
|
||||
|
||||
|
||||
/**
|
||||
* pwm_constant_disable() - stop a constant PWM output toggling
|
||||
* @chip: aml_pwm_chip struct
|
||||
* @index: pwm channel to choose,like PWM_A or PWM_B
|
||||
*/
|
||||
|
||||
int pwm_constant_disable(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
struct aml_pwm_chip *aml_chip = chip;
|
||||
int id = index;
|
||||
void __iomem *reg;
|
||||
unsigned int mask;
|
||||
unsigned int val;
|
||||
|
||||
if ((id < 0) && (id > 7)) {
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"constant,index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case PWM_A:
|
||||
reg = aml_chip->base + REG_MISC_AB;
|
||||
mask = 1 << 28;
|
||||
val = 0 << 28;
|
||||
break;
|
||||
case PWM_B:
|
||||
reg = aml_chip->base + REG_MISC_AB;
|
||||
mask = 1 << 29;
|
||||
val = 0 << 29;
|
||||
break;
|
||||
case PWM_C:
|
||||
reg = aml_chip->base + REG_MISC_CD;
|
||||
mask = 1 << 28;
|
||||
val = 0 << 28;
|
||||
break;
|
||||
case PWM_D:
|
||||
reg = aml_chip->base + REG_MISC_CD;
|
||||
mask = 1 << 29;
|
||||
val = 0 << 29;
|
||||
break;
|
||||
case PWM_E:
|
||||
reg = aml_chip->base + REG_MISC_EF;
|
||||
mask = 1 << 28;
|
||||
val = 0 << 28;
|
||||
break;
|
||||
case PWM_F:
|
||||
reg = aml_chip->base + REG_MISC_EF;
|
||||
mask = 1 << 29;
|
||||
val = 0 << 29;
|
||||
break;
|
||||
case PWM_AO_A:
|
||||
reg = aml_chip->ao_base + REG_MISC_AO_AB;
|
||||
mask = 1 << 28;
|
||||
val = 0 << 28;
|
||||
break;
|
||||
case PWM_AO_B:
|
||||
reg = aml_chip->ao_base + REG_MISC_AO_AB;
|
||||
mask = 1 << 29;
|
||||
val = 0 << 29;
|
||||
break;
|
||||
default:
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"constant,index is not legal\n");
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
}
|
||||
pwm_set_reg_bits(reg, mask, val);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_constant_disable);
|
||||
|
||||
|
||||
static ssize_t pwm_constant_show(struct device *child,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
return sprintf(buf, "%d\n", chip->variant.constant);
|
||||
}
|
||||
|
||||
static ssize_t pwm_constant_store(struct device *child,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
int val, ret, id, res;
|
||||
|
||||
res = sscanf(buf, "%d %d", &val, &id);
|
||||
if (res != 2) {
|
||||
dev_err(child, "Can't parse pwm id,usage:[value index]\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((id < 0) && (id > 7)) {
|
||||
dev_err(chip->chip.dev,
|
||||
"constant,index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
ret = pwm_constant_disable(chip, id);
|
||||
chip->variant.constant = 0;
|
||||
break;
|
||||
case 1:
|
||||
ret = pwm_constant_enable(chip, id);
|
||||
chip->variant.constant = 1;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret ? : size;
|
||||
}
|
||||
|
||||
/**
|
||||
* pwm_set_times() - set PWM times output toggling
|
||||
* set pwm a1 and pwm a2 timer together
|
||||
* and pwm a1 should be set first
|
||||
* @chip: aml_pwm_chip struct
|
||||
* @index: pwm channel to choose,like PWM_A or PWM_B,range from 1 to 15
|
||||
* @value: blink times to set,range from 1 to 255
|
||||
*/
|
||||
|
||||
int pwm_set_times(struct aml_pwm_chip *chip,
|
||||
int index, int value)
|
||||
{
|
||||
struct aml_pwm_chip *aml_chip = chip;
|
||||
int id = index;
|
||||
int val = value;
|
||||
void __iomem *reg;
|
||||
unsigned int clear_val;
|
||||
unsigned int set_val;
|
||||
|
||||
if (((val <= 0) && (val > 255)) || ((id < 0) && (id > 15))) {
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"index or value is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case PWM_A:
|
||||
reg = aml_chip->base + REG_TIME_AB;
|
||||
clear_val = 0xff << 24;
|
||||
set_val = val << 24;
|
||||
break;
|
||||
case PWM_B:
|
||||
reg = aml_chip->base + REG_TIME_AB;
|
||||
clear_val = 0xff << 8;
|
||||
set_val = val << 8;
|
||||
break;
|
||||
case PWM_C:
|
||||
reg = aml_chip->base + REG_TIME_CD;
|
||||
clear_val = 0xff << 24;
|
||||
set_val = val << 24;
|
||||
break;
|
||||
case PWM_D:
|
||||
reg = aml_chip->base + REG_TIME_CD;
|
||||
clear_val = 0xff << 8;
|
||||
set_val = val << 8;
|
||||
break;
|
||||
case PWM_E:
|
||||
reg = aml_chip->base + REG_TIME_EF;
|
||||
clear_val = 0xff << 24;
|
||||
set_val = val << 24;
|
||||
break;
|
||||
case PWM_F:
|
||||
reg = aml_chip->base + REG_TIME_EF;
|
||||
clear_val = 0xff << 8;
|
||||
set_val = val << 8;
|
||||
break;
|
||||
case PWM_AO_A:
|
||||
reg = aml_chip->ao_base + REG_TIME_AO_AB;
|
||||
clear_val = 0xff << 24;
|
||||
set_val = val << 24;
|
||||
break;
|
||||
case PWM_AO_B:
|
||||
reg = aml_chip->ao_base + REG_TIME_AO_AB;
|
||||
clear_val = 0xff << 8;
|
||||
set_val = val << 8;
|
||||
break;
|
||||
case PWM_A2:
|
||||
reg = aml_chip->base + REG_TIME_AB;
|
||||
clear_val = 0xff << 16;
|
||||
set_val = val << 16;
|
||||
break;
|
||||
case PWM_B2:
|
||||
reg = aml_chip->base + REG_TIME_AB;
|
||||
clear_val = 0xff;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_C2:
|
||||
reg = aml_chip->base + REG_TIME_CD;
|
||||
clear_val = 0xff << 16;
|
||||
set_val = val << 16;
|
||||
break;
|
||||
case PWM_D2:
|
||||
reg = aml_chip->base + REG_TIME_CD;
|
||||
clear_val = 0xff;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_E2:
|
||||
reg = aml_chip->base + REG_TIME_EF;
|
||||
clear_val = 0xff << 16;
|
||||
set_val = val << 16;
|
||||
break;
|
||||
case PWM_F2:
|
||||
reg = aml_chip->base + REG_TIME_EF;
|
||||
clear_val = 0xff;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_AO_A2:
|
||||
reg = aml_chip->ao_base + REG_TIME_AO_AB;
|
||||
clear_val = 0xff << 16;
|
||||
set_val = val << 16;
|
||||
break;
|
||||
case PWM_AO_B2:
|
||||
reg = aml_chip->ao_base + REG_TIME_AO_AB;
|
||||
clear_val = 0xff;
|
||||
set_val = val;
|
||||
break;
|
||||
default:
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"times,index is not legal\n");
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
}
|
||||
pwm_clear_reg_bits(reg, clear_val);
|
||||
pwm_write_reg1(reg, set_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_set_times);
|
||||
|
||||
static ssize_t pwm_times_show(struct device *child,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
return sprintf(buf, "%d\n", chip->variant.times);
|
||||
}
|
||||
|
||||
static ssize_t pwm_times_store(struct device *child,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
int val, ret, id, res;
|
||||
|
||||
res = sscanf(buf, "%d %d", &val, &id);
|
||||
if (res != 2) {
|
||||
dev_err(child,
|
||||
"Can't parse pwm id and value,usage:[value index]\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (((val <= 0) && (val > 255)) || ((id < 0) && (id > 15))) {
|
||||
dev_err(chip->chip.dev,
|
||||
"index or value is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pwm_set_times(chip, id, val);
|
||||
chip->variant.times = val;
|
||||
|
||||
return ret ? : size;
|
||||
}
|
||||
|
||||
/**
|
||||
* pwm_blink_enable()
|
||||
* - start a blink PWM output toggling
|
||||
* txl only support 8 channel blink output
|
||||
* @chip: aml_pwm_chip struct
|
||||
* @index: pwm channel to choose,like PWM_A or PWM_B
|
||||
*/
|
||||
int pwm_blink_enable(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
struct aml_pwm_chip *aml_chip = chip;
|
||||
int id = index;
|
||||
void __iomem *reg;
|
||||
unsigned int mask = 0;
|
||||
unsigned int val;
|
||||
|
||||
if ((id < 0) && (id > 7)) {
|
||||
dev_err(aml_chip->chip.dev, "index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case PWM_A:
|
||||
reg = aml_chip->base + REG_BLINK_AB;
|
||||
val = 1 << 8;
|
||||
break;
|
||||
case PWM_B:
|
||||
reg = aml_chip->base + REG_BLINK_AB;
|
||||
val = 1 << 9;
|
||||
break;
|
||||
case PWM_C:
|
||||
reg = aml_chip->base + REG_BLINK_CD;
|
||||
val = 1 << 8;
|
||||
break;
|
||||
case PWM_D:
|
||||
reg = aml_chip->base + REG_BLINK_CD;
|
||||
val = 1 << 9;
|
||||
break;
|
||||
case PWM_E:
|
||||
reg = aml_chip->base + REG_BLINK_EF;
|
||||
val = 1 << 8;
|
||||
break;
|
||||
case PWM_F:
|
||||
reg = aml_chip->base + REG_BLINK_EF;
|
||||
val = 1 << 9;
|
||||
break;
|
||||
case PWM_AO_A:
|
||||
reg = aml_chip->ao_base + REG_BLINK_AO_AB;
|
||||
val = 1 << 8;
|
||||
break;
|
||||
case PWM_AO_B:
|
||||
reg = aml_chip->ao_base + REG_BLINK_AO_AB;
|
||||
val = 1 << 9;
|
||||
break;
|
||||
default:
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"blink,index is not legal\n");
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
}
|
||||
pwm_set_reg_bits(reg, mask, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_blink_enable);
|
||||
|
||||
/**
|
||||
* pwm_blink_disable() - stop a constant PWM output toggling
|
||||
* @chip: aml_pwm_chip struct
|
||||
* @index: pwm channel to choose,like PWM_A or PWM_B
|
||||
*/
|
||||
int pwm_blink_disable(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
struct aml_pwm_chip *aml_chip = chip;
|
||||
int id = index;
|
||||
void __iomem *reg;
|
||||
unsigned int mask;
|
||||
unsigned int val;
|
||||
|
||||
if ((id < 1) && (id > 7)) {
|
||||
dev_err(aml_chip->chip.dev, "index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case PWM_A:
|
||||
reg = aml_chip->base + REG_BLINK_AB;
|
||||
mask = 1 << 8;
|
||||
val = 0 << 8;
|
||||
break;
|
||||
case PWM_B:
|
||||
reg = aml_chip->base + REG_BLINK_AB;
|
||||
mask = 1 << 9;
|
||||
val = 0 << 9;
|
||||
break;
|
||||
case PWM_C:
|
||||
reg = aml_chip->base + REG_BLINK_CD;
|
||||
mask = 1 << 8;
|
||||
val = 0 << 8;
|
||||
break;
|
||||
case PWM_D:
|
||||
reg = aml_chip->base + REG_BLINK_CD;
|
||||
mask = 1 << 9;
|
||||
val = 0 << 9;
|
||||
break;
|
||||
case PWM_E:
|
||||
reg = aml_chip->base + REG_BLINK_EF;
|
||||
mask = 1 << 8;
|
||||
val = 0 << 8;
|
||||
break;
|
||||
case PWM_F:
|
||||
reg = aml_chip->base + REG_BLINK_EF;
|
||||
mask = 1 << 9;
|
||||
val = 0 << 9;
|
||||
break;
|
||||
case PWM_AO_A:
|
||||
reg = aml_chip->ao_base + REG_BLINK_AO_AB;
|
||||
mask = 1 << 8;
|
||||
val = 0 << 8;
|
||||
break;
|
||||
case PWM_AO_B:
|
||||
reg = aml_chip->ao_base + REG_BLINK_AO_AB;
|
||||
mask = 1 << 9;
|
||||
val = 0 << 9;
|
||||
break;
|
||||
default:
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"blink,index is not legal\n");
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
}
|
||||
pwm_set_reg_bits(reg, mask, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_blink_disable);
|
||||
|
||||
static ssize_t pwm_blink_enable_show(struct device *child,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
return sprintf(buf, "%d\n", chip->variant.blink_enable);
|
||||
}
|
||||
|
||||
static ssize_t pwm_blink_enable_store(struct device *child,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
int val, ret, id, res;
|
||||
|
||||
res = sscanf(buf, "%d %d", &val, &id);
|
||||
if (res != 2) {
|
||||
dev_err(child,
|
||||
"blink enable,Can't parse pwm id,usage:[value index]\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((id < 1) && (id > 7)) {
|
||||
dev_err(chip->chip.dev, "index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
ret = pwm_blink_disable(chip, id);
|
||||
chip->variant.blink_enable = 0;
|
||||
break;
|
||||
case 1:
|
||||
ret = pwm_blink_enable(chip, id);
|
||||
chip->variant.blink_enable = 1;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret ? : size;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* pwm_set_blink_times() - set PWM blink times output toggling
|
||||
* @chip: aml_pwm_chip struct
|
||||
* @index: pwm channel to choose,like PWM_A or PWM_B
|
||||
* @value: blink times to set,range from 1 to 15
|
||||
*/
|
||||
int pwm_set_blink_times(struct aml_pwm_chip *chip,
|
||||
int index,
|
||||
int value)
|
||||
{
|
||||
struct aml_pwm_chip *aml_chip = chip;
|
||||
int id = index;
|
||||
int val = value;
|
||||
void __iomem *reg;
|
||||
unsigned int clear_val;
|
||||
unsigned int set_val;
|
||||
|
||||
|
||||
if (((val <= 0) && (val > 15)) || ((id < 1) && (id > 7))) {
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"value or index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case PWM_A:
|
||||
reg = aml_chip->base + REG_BLINK_AB;
|
||||
clear_val = 0xf;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_B:
|
||||
reg = aml_chip->base + REG_BLINK_AB;
|
||||
clear_val = 0xf << 4;
|
||||
set_val = val << 4;
|
||||
break;
|
||||
case PWM_C:
|
||||
reg = aml_chip->base + REG_BLINK_CD;
|
||||
clear_val = 0xf;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_D:
|
||||
reg = aml_chip->base + REG_BLINK_CD;
|
||||
clear_val = 0xf << 4;
|
||||
set_val = val << 4;
|
||||
break;
|
||||
case PWM_E:
|
||||
reg = aml_chip->base + REG_BLINK_EF;
|
||||
clear_val = 0xf;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_F:
|
||||
reg = aml_chip->base + REG_BLINK_EF;
|
||||
clear_val = 0xf << 4;
|
||||
set_val = val << 4;
|
||||
break;
|
||||
case PWM_AO_A:
|
||||
reg = aml_chip->ao_base + REG_BLINK_AO_AB;
|
||||
clear_val = 0xf;
|
||||
set_val = val;
|
||||
break;
|
||||
case PWM_AO_B:
|
||||
reg = aml_chip->ao_base + REG_BLINK_AO_AB;
|
||||
clear_val = 0xf << 4;
|
||||
set_val = val << 4;
|
||||
break;
|
||||
default:
|
||||
dev_err(aml_chip->chip.dev,
|
||||
"bink times,index is not legal\n");
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
}
|
||||
pwm_clear_reg_bits(reg, clear_val);
|
||||
pwm_write_reg(reg, set_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_set_blink_times);
|
||||
|
||||
static ssize_t pwm_blink_times_show(struct device *child,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
return sprintf(buf, "%d\n", chip->variant.blink_times);
|
||||
}
|
||||
|
||||
static ssize_t pwm_blink_times_store(struct device *child,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct aml_pwm_chip *chip =
|
||||
(struct aml_pwm_chip *)dev_get_drvdata(child);
|
||||
int val, ret, id, res;
|
||||
|
||||
res = sscanf(buf, "%d %d", &val, &id);
|
||||
if (res != 2) {
|
||||
dev_err(child,
|
||||
"Can't parse pwm id and value,usage:[value index]\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (((val <= 0) && (val > 15)) || ((id < 0) && (id > 7))) {
|
||||
dev_err(chip->chip.dev,
|
||||
"value or index is not within the scope!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pwm_set_blink_times(chip, id, val);
|
||||
chip->variant.blink_times = val;
|
||||
|
||||
return ret ? : size;
|
||||
}
|
||||
|
||||
|
||||
static DEVICE_ATTR(constant, 0644,
|
||||
pwm_constant_show,
|
||||
pwm_constant_store);
|
||||
static DEVICE_ATTR(times, 0644,
|
||||
pwm_times_show,
|
||||
pwm_times_store);
|
||||
static DEVICE_ATTR(blink_enable, 0644,
|
||||
pwm_blink_enable_show,
|
||||
pwm_blink_enable_store);
|
||||
static DEVICE_ATTR(blink_times, 0644,
|
||||
pwm_blink_times_show,
|
||||
pwm_blink_times_store);
|
||||
|
||||
static struct attribute *pwm_attrs[] = {
|
||||
&dev_attr_constant.attr,
|
||||
&dev_attr_times.attr,
|
||||
&dev_attr_blink_enable.attr,
|
||||
&dev_attr_blink_times.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group pwm_attr_group = {
|
||||
.attrs = pwm_attrs,
|
||||
};
|
||||
|
||||
int meson_pwm_sysfs_init(struct device *dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = sysfs_create_group(&dev->kobj, &pwm_attr_group);
|
||||
return retval;
|
||||
}
|
||||
66
include/dt-bindings/pwm/meson.h
Normal file
66
include/dt-bindings/pwm/meson.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* include/dt-bindings/pwm/meson.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_PWM_MESON_H
|
||||
#define _DT_BINDINGS_PWM_MESON_H
|
||||
|
||||
|
||||
#define PWM_A 0
|
||||
#define PWM_B 1
|
||||
#define PWM_C 2
|
||||
#define PWM_D 3
|
||||
#define PWM_E 4
|
||||
#define PWM_F 5
|
||||
#define PWM_AO_A 6
|
||||
#define PWM_AO_B 7
|
||||
|
||||
/*
|
||||
* Addtional 8 channels for txl
|
||||
*/
|
||||
#define PWM_A2 8
|
||||
#define PWM_B2 9
|
||||
#define PWM_C2 10
|
||||
#define PWM_D2 11
|
||||
#define PWM_E2 12
|
||||
#define PWM_F2 13
|
||||
#define PWM_AO_A2 14
|
||||
#define PWM_AO_B2 15
|
||||
|
||||
/* fclk_div3
|
||||
*--------------|\
|
||||
* fclk_div3 | \
|
||||
*--------------| \ get clock source
|
||||
* vid_pll_clk | |---------------------
|
||||
*--------------| |
|
||||
* XTAL | /
|
||||
*--------------|/
|
||||
* vid_pll_clk is not defined and described now,
|
||||
*waiting for CLKID_VID_PLL is suportted in the future,
|
||||
* the macro is used for compiling passed.
|
||||
*/
|
||||
#define CLKID_VID_PLL
|
||||
|
||||
/*
|
||||
* 4 clock sources to choose
|
||||
* keep the same order with pwm_aml_clk function in pwm driver
|
||||
*/
|
||||
#define XTAL_CLK 0
|
||||
#define VID_PLL_CLK 1
|
||||
#define FCLK_DIV4_CLK 2
|
||||
#define FCLK_DIV3_CLK 3
|
||||
|
||||
#endif
|
||||
205
include/linux/amlogic/pwm_meson.h
Normal file
205
include/linux/amlogic/pwm_meson.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* include/linux/amlogic/pwm_meson.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PWM_MESON_H
|
||||
#define _PWM_MESON_H
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
|
||||
|
||||
#define REG_PWM_A 0x0
|
||||
#define REG_PWM_B 0x4
|
||||
#define REG_MISC_AB 0x8
|
||||
#define REG_DS_A_B 0xc
|
||||
#define REG_TIME_AB 0x10
|
||||
#define REG_PWM_A2 0x14
|
||||
#define REG_PWM_B2 0x18
|
||||
#define REG_BLINK_AB 0x1c
|
||||
|
||||
|
||||
#define REG_PWM_C 0xf0
|
||||
#define REG_PWM_D 0xf4
|
||||
#define REG_MISC_CD 0xf8
|
||||
#define REG_DS_C_D 0xfc
|
||||
#define REG_TIME_CD 0x100
|
||||
#define REG_PWM_C2 0x104
|
||||
#define REG_PWM_D2 0x108
|
||||
#define REG_BLINK_CD 0x10c
|
||||
|
||||
|
||||
|
||||
#define REG_PWM_E 0x170
|
||||
#define REG_PWM_F 0x174
|
||||
#define REG_MISC_EF 0x178
|
||||
#define REG_DS_E_F 0x17c
|
||||
#define REG_TIME_EF 0x180
|
||||
#define REG_PWM_E2 0x184
|
||||
#define REG_PWM_F2 0x188
|
||||
#define REG_BLINK_EF 0x18c
|
||||
|
||||
|
||||
#define REG_PWM_AO_A 0x0
|
||||
#define REG_PWM_AO_B 0x4
|
||||
#define REG_MISC_AO_AB 0x8
|
||||
#define REG_DS_AO_A_B 0xc
|
||||
#define REG_TIME_AO_AB 0x10
|
||||
#define REG_PWM_AO_A2 0x14
|
||||
#define REG_PWM_AO_B2 0x18
|
||||
#define REG_BLINK_AO_AB 0x1c
|
||||
|
||||
|
||||
#define FIN_FREQ (24 * 1000)
|
||||
#define DUTY_MAX 1024
|
||||
|
||||
#define AML_PWM_NUM 8
|
||||
#define AML_PWM_NUM_NEW 16
|
||||
|
||||
|
||||
enum pwm_channel {
|
||||
PWM_A = 0,
|
||||
PWM_B,
|
||||
PWM_C,
|
||||
PWM_D,
|
||||
PWM_E,
|
||||
PWM_F,
|
||||
PWM_AO_A,
|
||||
PWM_AO_B,
|
||||
|
||||
PWM_A2,
|
||||
PWM_B2,
|
||||
PWM_C2,
|
||||
PWM_D2,
|
||||
PWM_E2,
|
||||
PWM_F2,
|
||||
PWM_AO_A2,
|
||||
PWM_AO_B2,
|
||||
};
|
||||
|
||||
/*pwm att*/
|
||||
struct aml_pwm_channel {
|
||||
unsigned int pwm_hi;
|
||||
unsigned int pwm_lo;
|
||||
unsigned int pwm_pre_div;
|
||||
|
||||
unsigned int period_ns;
|
||||
unsigned int duty_ns;
|
||||
unsigned int pwm_freq;
|
||||
};
|
||||
|
||||
/*pwm regiset att*/
|
||||
struct aml_pwm_variant {
|
||||
u8 output_mask;
|
||||
u16 output_mask_new;
|
||||
/*
|
||||
*add for gxtvbb , gxl , gxm
|
||||
*/
|
||||
|
||||
unsigned int times;
|
||||
/*
|
||||
*include above and add for txl
|
||||
*/
|
||||
unsigned int constant;
|
||||
unsigned int blink_enable;
|
||||
unsigned int blink_times;
|
||||
};
|
||||
|
||||
struct aml_pwm_chip {
|
||||
struct pwm_chip chip;
|
||||
void __iomem *base;
|
||||
void __iomem *ao_base;
|
||||
struct aml_pwm_variant variant;
|
||||
u8 inverter_mask;
|
||||
|
||||
unsigned int clk_mask;
|
||||
struct clk *xtal_clk;
|
||||
struct clk *vid_pll_clk;
|
||||
struct clk *fclk_div4_clk;
|
||||
struct clk *fclk_div3_clk;
|
||||
|
||||
};
|
||||
|
||||
struct aml_pwm_chip *to_aml_pwm_chip(struct pwm_chip *chip);
|
||||
void pwm_set_reg_bits(void __iomem *reg,
|
||||
unsigned int mask,
|
||||
const unsigned int val);
|
||||
|
||||
void pwm_write_reg(void __iomem *reg,
|
||||
const unsigned int val);
|
||||
|
||||
void pwm_clear_reg_bits(void __iomem *reg, const unsigned int val);
|
||||
|
||||
void pwm_write_reg1(void __iomem *reg, const unsigned int val);
|
||||
|
||||
|
||||
int meson_pwm_sysfs_init(struct device *dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_AMLOGIC_PWM)
|
||||
int pwm_constant_enable(struct aml_pwm_chip *chip, int index);
|
||||
int pwm_constant_disable(struct aml_pwm_chip *chip, int index);
|
||||
|
||||
int pwm_blink_enable(struct aml_pwm_chip *chip, int index);
|
||||
int pwm_blink_disable(struct aml_pwm_chip *chip, int index);
|
||||
|
||||
int pwm_set_times(struct aml_pwm_chip *chip,
|
||||
int index, int value);
|
||||
int pwm_set_blink_times(struct aml_pwm_chip *chip,
|
||||
int index,
|
||||
int value);
|
||||
|
||||
#else
|
||||
static inline int pwm_constant_enable
|
||||
(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int pwm_constant_disable
|
||||
(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int pwm_blink_enable
|
||||
(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int pwm_blink_disable
|
||||
(struct aml_pwm_chip *chip, int index)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int pwm_set_times(struct aml_pwm_chip *chip,
|
||||
int index, int value)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int pwm_set_blink_times(struct aml_pwm_chip *chip,
|
||||
int index,
|
||||
int value)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_PWM_MESON) */
|
||||
|
||||
#endif /* _PWM_MESON_H_ */
|
||||
|
||||
Reference in New Issue
Block a user