From d0ce9bb877cf1ed431a9737e5017c3d0064ca225 Mon Sep 17 00:00:00 2001 From: Ruibin Chang Date: Mon, 7 Jun 2021 15:21:22 +0800 Subject: [PATCH] ITE drivers/pwm: add PWM for it8xxx2 Add pulse width modulator (PWM) for it8xxx2. Signed-off-by: Ruibin Chang --- CODEOWNERS | 2 + boards/riscv/it8xxx2_evb/it8xxx2_evb.dts | 33 +++ .../riscv/it8xxx2_evb/it8xxx2_evb_defconfig | 2 + drivers/pwm/CMakeLists.txt | 1 + drivers/pwm/Kconfig | 2 + drivers/pwm/Kconfig.it8xxx2 | 12 + drivers/pwm/pwm_ite_it8xxx2.c | 265 ++++++++++++++++++ dts/bindings/pwm/ite,it8xxx2-pwm.yaml | 58 ++++ dts/bindings/pwm/ite,it8xxx2-pwmprs.yaml | 18 ++ dts/riscv/it8xxx2-alts-map.dtsi | 25 ++ dts/riscv/it8xxx2.dtsi | 111 ++++++++ include/dt-bindings/pwm/it8xxx2_pwm.h | 24 ++ soc/riscv/riscv-ite/common/chip_chipregs.h | 93 +++--- 13 files changed, 601 insertions(+), 45 deletions(-) create mode 100644 drivers/pwm/Kconfig.it8xxx2 create mode 100644 drivers/pwm/pwm_ite_it8xxx2.c create mode 100644 dts/bindings/pwm/ite,it8xxx2-pwm.yaml create mode 100644 dts/bindings/pwm/ite,it8xxx2-pwmprs.yaml create mode 100644 include/dt-bindings/pwm/it8xxx2_pwm.h diff --git a/CODEOWNERS b/CODEOWNERS index 496a66ab3ee..bc74e19faf4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -275,6 +275,7 @@ /drivers/pwm/pwm_capture.c @henrikbrixandersen /drivers/pwm/pwm_shell.c @henrikbrixandersen /drivers/pwm/*gecko* @sun681 +/drivers/pwm/*it8xxx2* @RuibinChang /drivers/sensor/ @MaureenHelm /drivers/sensor/ams_iAQcore/ @alexanderwachter /drivers/sensor/ens210/ @alexanderwachter @@ -471,6 +472,7 @@ /include/dt-bindings/dma/stm32_dma.h @cybertale /include/dt-bindings/ethernet/xlnx_gem.h @ibirnbaum /include/dt-bindings/pcie/ @dcpleung +/include/dt-bindings/pwm/*it8xxx2* @RuibinChang /include/dt-bindings/usb/usb.h @galak /include/drivers/emul.h @sjg20 /include/fs/ @nashif @nvlsianpu @de-nordic diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts b/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts index 6cf7ae9e813..9f615a7790b 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts @@ -11,6 +11,12 @@ / { model = "IT8XXX2 EV-Board"; compatible = "riscv,it8xxx2-evb"; + + aliases { + pwm-led0 = &led0; + pwm-led1 = &led1; + }; + chosen { zephyr,console = &uart1; zephyr,shell-uart = &uart1; @@ -20,6 +26,19 @@ zephyr,flash-controller = &flashctrl; zephyr,code-partition = &slot0_partition; }; + + pwmleds { + compatible = "pwm-leds"; + /* NOTE: &pwm number needs same with channel number */ + led0: led_0 { + pwms = <&pwm7 PWM_CHANNEL_7 PWM_POLARITY_INVERTED>; + label = "LED0_GREEN"; + }; + led1: led_1 { + pwms = <&pwm0 PWM_CHANNEL_0 PWM_POLARITY_NORMAL>; + label = "LED1_BLUE"; + }; + }; }; &adc0 { status = "okay"; @@ -58,6 +77,20 @@ current-speed = <460800>; clock-frequency = <1804800>; }; +&pwm0 { + status = "okay"; + prescaler-cx = ; + /* + * If we need pwm output in ITE chip power saving mode, + * then we should set frequency <=324Hz. + */ + pwm-output-frequency = <324>; +}; +&pwm7 { + status = "okay"; + prescaler-cx = ; + pwm-output-frequency = <30000>; +}; &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig index 57ca792693b..4fde079cb4d 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig @@ -32,3 +32,5 @@ CONFIG_I2C=y CONFIG_I2C_ITE_IT8XXX2=y CONFIG_ADC_ITE_IT8XXX2=y CONFIG_SOC_FLASH_ITE_IT8XXX2=y +CONFIG_PWM=y +CONFIG_PWM_ITE_IT8XXX2=y diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index 00160a26bf8..7eb3be7b7a9 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_PWM_NRF5_SW pwm_nrf5_sw.c) zephyr_library_sources_ifdef(CONFIG_PWM_NRFX pwm_nrfx.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_FTM pwm_mcux_ftm.c) zephyr_library_sources_ifdef(CONFIG_PWM_IMX pwm_imx.c) +zephyr_library_sources_ifdef(CONFIG_PWM_ITE_IT8XXX2 pwm_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_PWM_LED_ESP32 pwm_led_esp32.c) zephyr_library_sources_ifdef(CONFIG_PWM_SAM pwm_sam.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX pwm_mcux.c) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 130cb1b0b53..eb7e43477e9 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -39,6 +39,8 @@ source "drivers/pwm/Kconfig.mcux_ftm" source "drivers/pwm/Kconfig.imx" +source "drivers/pwm/Kconfig.it8xxx2" + source "drivers/pwm/Kconfig.esp32" source "drivers/pwm/Kconfig.sam" diff --git a/drivers/pwm/Kconfig.it8xxx2 b/drivers/pwm/Kconfig.it8xxx2 new file mode 100644 index 00000000000..e02467b7740 --- /dev/null +++ b/drivers/pwm/Kconfig.it8xxx2 @@ -0,0 +1,12 @@ +# IT8XXX2 PWM configuration options + +# Copyright (c) 2021 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +config PWM_ITE_IT8XXX2 + bool "ITE IT8XXX2 embedded controller (EC) PWM driver" + depends on SOC_IT8XXX2 + help + Enable PWM driver for it8xxx2_evb. + Supports three 16-bit prescalers each with 8-bit cycle timer, and + eight PWM channels each with 8-bit duty cycle. diff --git a/drivers/pwm/pwm_ite_it8xxx2.c b/drivers/pwm/pwm_ite_it8xxx2.c new file mode 100644 index 00000000000..c8ded9d605e --- /dev/null +++ b/drivers/pwm/pwm_ite_it8xxx2.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2021 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_it8xxx2_pwm + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(pwm_ite_it8xxx2, CONFIG_PWM_LOG_LEVEL); + +#define PWM_CTRX_MIN 100 +#define PWM_EC_FREQ MHZ(8) +#define PCSSG_MASK 0x3 + +/* Device config */ +struct pwm_it8xxx2_cfg { + /* PWM channel duty cycle register */ + uintptr_t reg_dcr; + /* PWM channel clock source selection register */ + uintptr_t reg_pcssg; + /* PWM channel clock source gating register */ + uintptr_t reg_pcsgr; + /* PWM channel output polarity register */ + uintptr_t reg_pwmpol; + /* PWM channel */ + int channel; + /* PWM prescaler control register base */ + uintptr_t base; + /* Select PWM prescaler that output to PWM channel */ + int prs_sel; + /* Pinmux control device structure */ + const struct device *pinctrls; + /* GPIO pin */ + uint8_t pin; + /* Alternate function */ + uint8_t alt_fun; +}; + +/* Driver convenience defines */ +#define DRV_CONFIG(dev) ((const struct pwm_it8xxx2_cfg * const)(dev)->config) +#define DRV_REG(dev) (struct pwm_it8xxx2_regs *)(DRV_CONFIG(dev)->base) +#define DEV_PINMUX(inst) \ + DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_NODELABEL(pinctrl_pwm##inst), pinctrls, 0)) +#define DEV_PIN(inst) \ + DT_PHA(DT_PHANDLE_BY_IDX(DT_DRV_INST(inst), pinctrl_0, 0), pinctrls, pin) +#define DEV_ALT_FUN(inst) \ + DT_PHA(DT_PHANDLE_BY_IDX(DT_DRV_INST(inst), pinctrl_0, 0), pinctrls, alt_func) + +static void pwm_enable(const struct device *dev, int enabled) +{ + const struct pwm_it8xxx2_cfg *config = DRV_CONFIG(dev); + volatile uint8_t *reg_pcsgr = (uint8_t *)config->reg_pcsgr; + int ch = config->channel; + + if (enabled) + /* PWM channel clock source not gating */ + *reg_pcsgr &= ~BIT(ch); + else + /* PWM channel clock source gating */ + *reg_pcsgr |= BIT(ch); +} + +static int pwm_it8xxx2_get_cycles_per_sec(const struct device *dev, + uint32_t pwm, uint64_t *cycles) +{ + const struct pwm_it8xxx2_cfg *config = DRV_CONFIG(dev); + struct pwm_it8xxx2_regs *const inst = DRV_REG(dev); + int prs_sel = config->prs_sel; + + ARG_UNUSED(pwm); + + /* Get clock source cycles per second that output to prescaler */ + if ((inst->PCFSR) & BIT(prs_sel)) + *cycles = (uint64_t) PWM_EC_FREQ; + else + *cycles = (uint64_t) 32768; + + return 0; +} + +static int pwm_it8xxx2_pin_set(const struct device *dev, + uint32_t pwm, uint32_t period_cycles, + uint32_t pulse_cycles, pwm_flags_t flags) +{ + const struct pwm_it8xxx2_cfg *config = DRV_CONFIG(dev); + struct pwm_it8xxx2_regs *const inst = DRV_REG(dev); + volatile uint8_t *reg_dcr = (uint8_t *)config->reg_dcr; + volatile uint8_t *reg_pwmpol = (uint8_t *)config->reg_pwmpol; + int ch = config->channel; + int prs_sel = config->prs_sel; + uint32_t actual_freq = 0xffffffff, target_freq, deviation, cxcprs, ctr; + uint64_t pwm_clk_src; + + ARG_UNUSED(pwm); + + if (pulse_cycles > period_cycles) + return -EINVAL; + + /* PWM channel clock source gating before configuring */ + pwm_enable(dev, 0); + + /* Select PWM inverted polarity (ex. active-low pulse) */ + if (flags & PWM_POLARITY_INVERTED) + *reg_pwmpol |= BIT(ch); + else + *reg_pwmpol &= ~BIT(ch); + + /* If pulse cycles is 0, set duty cycle 0 and enable pwm channel */ + if (pulse_cycles == 0) { + *reg_dcr = 0; + pwm_enable(dev, 1); + return 0; + } + + pwm_it8xxx2_get_cycles_per_sec(dev, pwm, &pwm_clk_src); + target_freq = ((uint32_t) pwm_clk_src) / period_cycles; + deviation = (target_freq / 100) + 1; + + /* + * Default clock source setting is 8MHz, when ITE chip is in power + * saving mode, clock source 8MHz will be gated (32.768KHz won't). + * So if we still need pwm output in mode, then we should set frequency + * <=324Hz in board dts. Now change prescaler clock source from 8MHz to + * 32.768KHz to support pwm output in mode. + * NOTE: PWM output signal maximum supported frequency 324Hz comes from + * 32768 / (PWM_CTRX_MIN + 1). + */ + if ((target_freq <= 324) && (inst->PCFSR & BIT(prs_sel))) { + inst->PCFSR &= ~BIT(prs_sel); + pwm_clk_src = (uint64_t) 32768; + } + + /* + * PWM output signal frequency is + * pwm_clk_src / ((CxCPRS[15:0] + 1) * (CTRx[7:0] + 1)) + * NOTE: 1) define CTR minimum is 100 for more precisely when + * calculate DCR + * 2) CxCPRS[15:0] value 0001h results in a divisor 2 + * CxCPRS[15:0] value FFFFh results in a divisor 65536 + * CTRx[7:0] value 00h results in a divisor 1 + * CTRx[7:0] value FFh results in a divisor 256 + */ + for (ctr = 0xFF; ctr >= PWM_CTRX_MIN; ctr--) { + cxcprs = (((uint32_t) pwm_clk_src) / (ctr + 1) / target_freq) - 1; + if (cxcprs >= 0) { + actual_freq = ((uint32_t) pwm_clk_src) / (ctr + 1) / (cxcprs + 1); + if (abs(actual_freq - target_freq) < deviation) + break; + } + } + + if (cxcprs > UINT16_MAX) { + LOG_ERR("PWM prescaler CxCPRS only support 2 bytes !"); + return -EINVAL; + } + + /* Set PWM prescaler clock divide and cycle time register */ + if (prs_sel == PWM_PRESCALER_C4) { + inst->C4CPRS = cxcprs & 0xFF; + inst->C4MCPRS = (cxcprs >> 8) & 0xFF; + inst->CTR1 = ctr; + } else if (prs_sel == PWM_PRESCALER_C6) { + inst->C6CPRS = cxcprs & 0xFF; + inst->C6MCPRS = (cxcprs >> 8) & 0xFF; + inst->CTR2 = ctr; + } else if (prs_sel == PWM_PRESCALER_C7) { + inst->C7CPRS = cxcprs & 0xFF; + inst->C7MCPRS = (cxcprs >> 8) & 0xFF; + inst->CTR3 = ctr; + } + + /* Set PWM channel duty cycle register */ + *reg_dcr = (ctr * pulse_cycles) / period_cycles; + + /* PWM channel clock source not gating */ + pwm_enable(dev, 1); + + LOG_DBG("clock source freq %d, target freq %d", + (uint32_t) pwm_clk_src, target_freq); + + return 0; +} + +static int pwm_it8xxx2_init(const struct device *dev) +{ + const struct pwm_it8xxx2_cfg *config = DRV_CONFIG(dev); + struct pwm_it8xxx2_regs *const inst = DRV_REG(dev); + volatile uint8_t *reg_pcssg = (uint8_t *)config->reg_pcssg; + int ch = config->channel; + int prs_sel = config->prs_sel; + int pcssg_shift; + int pcssg_mask; + + /* PWM channel clock source gating before configuring */ + pwm_enable(dev, 0); + + /* Select clock source 8MHz for prescaler */ + inst->PCFSR |= BIT(prs_sel); + + /* Bit shift and mask of prescaler clock source select group register */ + pcssg_shift = (ch % 4) * 2; + pcssg_mask = (prs_sel & PCSSG_MASK) << pcssg_shift; + + /* Select which prescaler output to PWM channel */ + *reg_pcssg &= ~(PCSSG_MASK << pcssg_shift); + *reg_pcssg |= pcssg_mask; + + /* + * The cycle timer1 of it8320 later series was enhanced from + * 8bits to 10bits resolution, and others are still 8bit resolution. + * Because the cycle timer1 high byte default value is not zero, + * we clear cycle timer1 high byte at init and use it as 8-bit + * resolution like others. + */ + inst->CTR1M = 0; + + /* Enable PWMs clock counter */ + inst->ZTIER |= IT8XXX2_PWM_PCCE; + + /* Set alternate mode of PWM pin */ + pinmux_pin_set(config->pinctrls, config->pin, config->alt_fun); + + return 0; +} + +static const struct pwm_driver_api pwm_it8xxx2_api = { + .pin_set = pwm_it8xxx2_pin_set, + .get_cycles_per_sec = pwm_it8xxx2_get_cycles_per_sec, +}; + +/* Device Instance */ +#define PWM_IT8XXX2_INIT(inst) \ + static const struct pwm_it8xxx2_cfg pwm_it8xxx2_cfg_##inst = { \ + .reg_dcr = DT_INST_REG_ADDR_BY_IDX(inst, 0), \ + .reg_pcssg = DT_INST_REG_ADDR_BY_IDX(inst, 1), \ + .reg_pcsgr = DT_INST_REG_ADDR_BY_IDX(inst, 2), \ + .reg_pwmpol = DT_INST_REG_ADDR_BY_IDX(inst, 3), \ + .channel = DT_PROP(DT_INST(inst, ite_it8xxx2_pwm), channel), \ + .base = DT_REG_ADDR(DT_NODELABEL(prs)), \ + .prs_sel = DT_PROP(DT_INST(inst, ite_it8xxx2_pwm), prescaler_cx), \ + .pinctrls = DEV_PINMUX(inst), \ + .pin = DEV_PIN(inst), \ + .alt_fun = DEV_ALT_FUN(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, \ + &pwm_it8xxx2_init, \ + NULL, \ + NULL, \ + &pwm_it8xxx2_cfg_##inst, \ + PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &pwm_it8xxx2_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_IT8XXX2_INIT) diff --git a/dts/bindings/pwm/ite,it8xxx2-pwm.yaml b/dts/bindings/pwm/ite,it8xxx2-pwm.yaml new file mode 100644 index 00000000000..2f9aead27b6 --- /dev/null +++ b/dts/bindings/pwm/ite,it8xxx2-pwm.yaml @@ -0,0 +1,58 @@ +# Copyright (c) 2021 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: ITE, it8xxx2 Pulse Width Modulator (PWM) node + +compatible: "ite,it8xxx2-pwm" + +include: [pwm-controller.yaml, base.yaml] + +properties: + reg: + required: true + + label: + required: true + + interrupts: + required: false + + channel: + type: int + required: true + enum: + - 0 #PWM_CHANNEL_0 + - 1 #PWM_CHANNEL_1 + - 2 #PWM_CHANNEL_2 + - 3 #PWM_CHANNEL_3 + - 4 #PWM_CHANNEL_4 + - 5 #PWM_CHANNEL_5 + - 6 #PWM_CHANNEL_6 + - 7 #PWM_CHANNEL_7 + + pwmctrl: + type: phandle + required: true + description: PWM prescaler controller + + pinctrl-0: + type: phandle + required: true + description: configuration of PWM pinmux controller + + prescaler-cx: + type: int + required: true + enum: + - 1 #PWM_PRESCALER_C4 + - 2 #PWM_PRESCALER_C6 + - 3 #PWM_PRESCALER_C7 + + pwm-output-frequency: + type: int + required: false + description: PWM output frequency for operation + +pwm-cells: + - channel + - flags diff --git a/dts/bindings/pwm/ite,it8xxx2-pwmprs.yaml b/dts/bindings/pwm/ite,it8xxx2-pwmprs.yaml new file mode 100644 index 00000000000..8fa46445e43 --- /dev/null +++ b/dts/bindings/pwm/ite,it8xxx2-pwmprs.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2021 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: ITE, it8xxx2 PWM prescaler node + +compatible: "ite,it8xxx2-pwmprs" + +include: base.yaml + +properties: + reg: + required: true + + label: + required: true + + interrupts: + required: false diff --git a/dts/riscv/it8xxx2-alts-map.dtsi b/dts/riscv/it8xxx2-alts-map.dtsi index 7f6b5e537b2..bffcf1e5ad7 100644 --- a/dts/riscv/it8xxx2-alts-map.dtsi +++ b/dts/riscv/it8xxx2-alts-map.dtsi @@ -36,5 +36,30 @@ pinctrls = <&pinmuxi 7 IT8XXX2_PINMUX_FUNC_1>; }; + /* PWM alternate function */ + pinctrl_pwm0: pwm0 { + pinctrls = <&pinmuxa 0 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm1: pwm1 { + pinctrls = <&pinmuxa 1 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm2: pwm2 { + pinctrls = <&pinmuxa 2 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm3: pwm3 { + pinctrls = <&pinmuxa 3 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm4: pwm4 { + pinctrls = <&pinmuxa 4 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm5: pwm5 { + pinctrls = <&pinmuxa 5 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm6: pwm6 { + pinctrls = <&pinmuxa 6 IT8XXX2_PINMUX_FUNC_1>; + }; + pinctrl_pwm7: pwm7 { + pinctrls = <&pinmuxa 7 IT8XXX2_PINMUX_FUNC_1>; + }; }; }; diff --git a/dts/riscv/it8xxx2.dtsi b/dts/riscv/it8xxx2.dtsi index 9b58fefd642..9fc4abd8d77 100644 --- a/dts/riscv/it8xxx2.dtsi +++ b/dts/riscv/it8xxx2.dtsi @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "it8xxx2-alts-map.dtsi" / { @@ -664,5 +666,114 @@ reg-names = "ecpm"; label = "EC_PM"; }; + prs: pwmprs@f01800 { + compatible = "ite,it8xxx2-pwmprs"; + reg = <0x00f01800 1>; + label = "prescaler"; + }; + pwm0: pwm@f01802 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01802 1 /* DCR */ + 0x00f0180c 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_0"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm0>; /* GPA0 */ + #pwm-cells = <2>; + }; + pwm1: pwm@f01803 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01803 1 /* DCR */ + 0x00f0180c 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_1"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm1>; /* GPA1 */ + #pwm-cells = <2>; + }; + pwm2: pwm@f01804 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01804 1 /* DCR */ + 0x00f0180c 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_2"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm2>; /* GPA2 */ + #pwm-cells = <2>; + }; + pwm3: pwm@f01805 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01805 1 /* DCR */ + 0x00f0180c 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_3"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm3>; /* GPA3 */ + #pwm-cells = <2>; + }; + pwm4: pwm@f01806 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01806 1 /* DCR */ + 0x00f0180d 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_4"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm4>; /* GPA4 */ + #pwm-cells = <2>; + }; + pwm5: pwm@f01807 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01807 1 /* DCR */ + 0x00f0180d 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_5"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm5>; /* GPA5 */ + #pwm-cells = <2>; + }; + pwm6: pwm@f01808 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01808 1 /* DCR */ + 0x00f0180d 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_6"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm6>; /* GPA6 */ + #pwm-cells = <2>; + }; + pwm7: pwm@f01809 { + compatible = "ite,it8xxx2-pwm"; + reg = <0x00f01809 1 /* DCR */ + 0x00f0180d 1 /* PCSSG */ + 0x00f0180f 1 /* PCSG */ + 0x00f0180a 1>; /* PWMPOL */ + channel = ; + label = "pwm_7"; + status = "disabled"; + pwmctrl = <&prs>; + pinctrl-0 = <&pinctrl_pwm7>; /* GPA7 */ + #pwm-cells = <2>; + }; }; }; diff --git a/include/dt-bindings/pwm/it8xxx2_pwm.h b/include/dt-bindings/pwm/it8xxx2_pwm.h new file mode 100644 index 00000000000..0f2ba5b069f --- /dev/null +++ b/include/dt-bindings/pwm/it8xxx2_pwm.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 ITE Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PWM_IT8XXX2_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PWM_IT8XXX2_H_ + +/* PWM prescaler references */ +#define PWM_PRESCALER_C4 1 +#define PWM_PRESCALER_C6 2 +#define PWM_PRESCALER_C7 3 + +/* PWM channel references */ +#define PWM_CHANNEL_0 0 +#define PWM_CHANNEL_1 1 +#define PWM_CHANNEL_2 2 +#define PWM_CHANNEL_3 3 +#define PWM_CHANNEL_4 4 +#define PWM_CHANNEL_5 5 +#define PWM_CHANNEL_6 6 +#define PWM_CHANNEL_7 7 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PWM_IT8XXX2_H_ */ diff --git a/soc/riscv/riscv-ite/common/chip_chipregs.h b/soc/riscv/riscv-ite/common/chip_chipregs.h index 87434a42ded..82c0e10ca09 100644 --- a/soc/riscv/riscv-ite/common/chip_chipregs.h +++ b/soc/riscv/riscv-ite/common/chip_chipregs.h @@ -739,51 +739,54 @@ * (18xxh) PWM & SmartAuto Fan Control (PWM) * */ -#define C0CPRS ECREG(EC_REG_BASE_ADDR + 0x1800) -#define CTR ECREG(EC_REG_BASE_ADDR + 0x1801) -#define DCR0 ECREG(EC_REG_BASE_ADDR + 0x1802) -#define DCR1 ECREG(EC_REG_BASE_ADDR + 0x1803) -#define DCR2 ECREG(EC_REG_BASE_ADDR + 0x1804) -#define DCR3 ECREG(EC_REG_BASE_ADDR + 0x1805) -#define DCR4 ECREG(EC_REG_BASE_ADDR + 0x1806) -#define DCR5 ECREG(EC_REG_BASE_ADDR + 0x1807) -#define DCR6 ECREG(EC_REG_BASE_ADDR + 0x1808) -#define DCR7 ECREG(EC_REG_BASE_ADDR + 0x1809) -#define PWMPOL ECREG(EC_REG_BASE_ADDR + 0x180A) -#define PCFSR ECREG(EC_REG_BASE_ADDR + 0x180B) -#define PCSSGL ECREG(EC_REG_BASE_ADDR + 0x180C) -#define PCSSGH ECREG(EC_REG_BASE_ADDR + 0x180D) -#define CR256PCSSG ECREG(EC_REG_BASE_ADDR + 0x180E) -#define PCSGR ECREG(EC_REG_BASE_ADDR + 0x180F) -#define F1TLRR ECREG(EC_REG_BASE_ADDR + 0x181E) -#define F1TMRR ECREG(EC_REG_BASE_ADDR + 0x181F) -#define F2TLRR ECREG(EC_REG_BASE_ADDR + 0x1820) -#define F2TMRR ECREG(EC_REG_BASE_ADDR + 0x1821) -#define ZINTSCR ECREG(EC_REG_BASE_ADDR + 0x1822) -#define ZTIER ECREG(EC_REG_BASE_ADDR + 0x1823) -#define TSWCTLR ECREG(EC_REG_BASE_ADDR + 0x1824) -#define C4CPRS ECREG(EC_REG_BASE_ADDR + 0x1827) -#define C4MCPRS ECREG(EC_REG_BASE_ADDR + 0x1828) -#define C6CPRS ECREG(EC_REG_BASE_ADDR + 0x182B) -#define C6MCPRS ECREG(EC_REG_BASE_ADDR + 0x182C) -#define C7CPRS ECREG(EC_REG_BASE_ADDR + 0x182D) -#define C7MCPRS ECREG(EC_REG_BASE_ADDR + 0x182E) -#define CLK6MSEL ECREG(EC_REG_BASE_ADDR + 0x1840) -#define CTR1 ECREG(EC_REG_BASE_ADDR + 0x1841) -#define CTR2 ECREG(EC_REG_BASE_ADDR + 0x1842) -#define CTR3 ECREG(EC_REG_BASE_ADDR + 0x1843) -#define PWM5TOCTRL ECREG(EC_REG_BASE_ADDR + 0x1844) -#define CFLRR ECREG(EC_REG_BASE_ADDR + 0x1845) -#define CFMRR ECREG(EC_REG_BASE_ADDR + 0x1846) -#define CFINTCTRL ECREG(EC_REG_BASE_ADDR + 0x1847) -#define TSWCTRL ECREG(EC_REG_BASE_ADDR + 0x1848) -#define PWMODENR ECREG(EC_REG_BASE_ADDR + 0x1849) -#define PWM0LHE ECREG(EC_REG_BASE_ADDR + 0x1850) -#define PWM0LCR1 ECREG(EC_REG_BASE_ADDR + 0x1851) -#define PWM0LCR2 ECREG(EC_REG_BASE_ADDR + 0x1852) -#define PWM1LHE ECREG(EC_REG_BASE_ADDR + 0x1853) -#define PWM1LCR1 ECREG(EC_REG_BASE_ADDR + 0x1854) -#define PWM1LCR2 ECREG(EC_REG_BASE_ADDR + 0x1855) +#ifndef __ASSEMBLER__ +struct pwm_it8xxx2_regs { + /* 0x000: Channel0 Clock Prescaler */ + volatile uint8_t C0CPRS; + /* 0x001: Cycle Time0 */ + volatile uint8_t CTR; + /* 0x002~0x00A: Reserved1 */ + volatile uint8_t Reserved1[9]; + /* 0x00B: Prescaler Clock Frequency Select */ + volatile uint8_t PCFSR; + /* 0x00C~0x00F: Reserved2 */ + volatile uint8_t Reserved2[4]; + /* 0x010: Cycle Time1 MSB */ + volatile uint8_t CTR1M; + /* 0x011~0x022: Reserved3 */ + volatile uint8_t Reserved3[18]; + /* 0x023: PWM Clock Control */ + volatile uint8_t ZTIER; + /* 0x024~0x026: Reserved4 */ + volatile uint8_t Reserved4[3]; + /* 0x027: Channel4 Clock Prescaler */ + volatile uint8_t C4CPRS; + /* 0x028: Channel4 Clock Prescaler MSB */ + volatile uint8_t C4MCPRS; + /* 0x029~0x02A: Reserved5 */ + volatile uint8_t Reserved5[2]; + /* 0x02B: Channel6 Clock Prescaler */ + volatile uint8_t C6CPRS; + /* 0x02C: Channel6 Clock Prescaler MSB */ + volatile uint8_t C6MCPRS; + /* 0x02D: Channel7 Clock Prescaler */ + volatile uint8_t C7CPRS; + /* 0x02E: Channel7 Clock Prescaler MSB */ + volatile uint8_t C7MCPRS; + /* 0x02F~0x040: Reserved6 */ + volatile uint8_t reserved6[18]; + /* 0x041: Cycle Time1 */ + volatile uint8_t CTR1; + /* 0x042: Cycle Time2 */ + volatile uint8_t CTR2; + /* 0x043: Cycle Time3 */ + volatile uint8_t CTR3; +}; +#endif /* !__ASSEMBLER__ */ + +/* PWM register fields */ +/* 0x023: PWM Clock Control */ +#define IT8XXX2_PWM_PCCE BIT(1) /** *