From d982ea54b6868b538326b65e5378a6cb6f32aab7 Mon Sep 17 00:00:00 2001 From: Anisetti Avinash Krishna Date: Mon, 26 Jun 2023 20:46:22 +0530 Subject: [PATCH] drivers: pwm: Add support for pch intel blink driver This patch adds support for PWM blink which is found in intel's PCH hardwares. Signed-off-by: Anisetti Avinash Krishna --- drivers/pwm/CMakeLists.txt | 1 + drivers/pwm/Kconfig | 2 + drivers/pwm/Kconfig.intel_blinky | 11 +++ drivers/pwm/pwm_intel_blinky.c | 129 +++++++++++++++++++++++++ dts/bindings/pwm/intel,blinky-pwm.yaml | 35 +++++++ 5 files changed, 178 insertions(+) create mode 100644 drivers/pwm/Kconfig.intel_blinky create mode 100644 drivers/pwm/pwm_intel_blinky.c create mode 100644 dts/bindings/pwm/intel,blinky-pwm.yaml diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index fcd0075eeed..981428ff314 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_PWM_PCA9685 pwm_pca9685.c) zephyr_library_sources_ifdef(CONFIG_PWM_TEST pwm_test.c) zephyr_library_sources_ifdef(CONFIG_PWM_RPI_PICO pwm_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_PWM_BBLED_XEC pwm_mchp_xec_bbled.c) +zephyr_library_sources_ifdef(CONFIG_PWM_INTEL_BLINKY pwm_intel_blinky.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c) zephyr_library_sources_ifdef(CONFIG_PWM_CAPTURE pwm_capture.c) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 021ad308033..f205dbb525a 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -85,4 +85,6 @@ source "drivers/pwm/Kconfig.test" source "drivers/pwm/Kconfig.rpi_pico" +source "drivers/pwm/Kconfig.intel_blinky" + endif # PWM diff --git a/drivers/pwm/Kconfig.intel_blinky b/drivers/pwm/Kconfig.intel_blinky new file mode 100644 index 00000000000..51d192f099e --- /dev/null +++ b/drivers/pwm/Kconfig.intel_blinky @@ -0,0 +1,11 @@ +# Intel Blinky PWM configuration options + +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config PWM_INTEL_BLINKY + bool "Blinky PWM driver" + default y + depends on DT_HAS_INTEL_BLINKY_PWM_ENABLED + help + Enable the INTEL PCH PWM driver found on Intel SoCs diff --git a/drivers/pwm/pwm_intel_blinky.c b/drivers/pwm/pwm_intel_blinky.c new file mode 100644 index 00000000000..cf6df303a74 --- /dev/null +++ b/drivers/pwm/pwm_intel_blinky.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_blinky_pwm + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PWM_ENABLE 0x80000000 +#define PWM_SWUP 0x40000000 +#define PWM_FREQ_INT_SHIFT 8 +#define PWM_BASE_UNIT_FRACTION 14 +#define PWM_FREQ_MAX 0x100 +#define PWM_DUTY_MAX 0x100 + +struct bk_intel_config { + DEVICE_MMIO_NAMED_ROM(reg_base); + uint32_t reg_offset; + uint32_t clock_freq; + uint32_t max_pins; +}; + +struct bk_intel_runtime { + DEVICE_MMIO_NAMED_RAM(reg_base); +}; + +static int bk_intel_set_cycles(const struct device *dev, uint32_t pin, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + struct bk_intel_runtime *rt = dev->data; + const struct bk_intel_config *cfg = dev->config; + uint32_t ret = 0; + uint32_t val = 0; + uint32_t duty; + float period; + float out_freq; + uint32_t base_unit; + + if (pin >= cfg->max_pins) { + ret = -EINVAL; + goto err; + } + + out_freq = cfg->clock_freq / (float) period_cycles; + period = (out_freq * PWM_FREQ_MAX) / cfg->clock_freq; + base_unit = (uint32_t) (period * (1 << PWM_BASE_UNIT_FRACTION)); + duty = (pulse_cycles * PWM_DUTY_MAX) / period_cycles; + + if (duty) { + val = PWM_DUTY_MAX - duty; + val |= (base_unit << PWM_FREQ_INT_SHIFT); + } else { + val = PWM_DUTY_MAX - 1; + } + + val |= PWM_ENABLE | PWM_SWUP; + + if (period >= PWM_FREQ_MAX) { + ret = -EINVAL; + goto err; + } + + if (duty > PWM_DUTY_MAX) { + ret = -EINVAL; + goto err; + } + + sys_write32(val, rt->reg_base + cfg->reg_offset); +err: + return ret; +} + +static int bk_intel_get_cycles_per_sec(const struct device *dev, uint32_t pin, + uint64_t *cycles) +{ + const struct bk_intel_config *cfg = dev->config; + + if (pin >= cfg->max_pins) { + return -EINVAL; + } + + *cycles = cfg->clock_freq; + + return 0; +} + +static const struct pwm_driver_api api_funcs = { + .set_cycles = bk_intel_set_cycles, + .get_cycles_per_sec = bk_intel_get_cycles_per_sec, +}; + +static int bk_intel_init(const struct device *dev) +{ + struct bk_intel_runtime *runtime = dev->data; + const struct bk_intel_config *config = dev->config; + + device_map(&runtime->reg_base, + config->reg_base.phys_addr & ~0xFFU, + config->reg_base.size, + K_MEM_CACHE_NONE); + + return 0; +} + +#define BK_INTEL_DEV_CFG(n) \ + static const struct bk_intel_config bk_cfg_##n = { \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ + .reg_offset = DT_INST_PROP(n, reg_offset), \ + .max_pins = DT_INST_PROP(n, max_pins), \ + .clock_freq = DT_INST_PROP(n, clock_frequency), \ + }; \ + \ + static struct bk_intel_runtime bk_rt_##n; \ + DEVICE_DT_INST_DEFINE(n, &bk_intel_init, NULL, \ + &bk_rt_##n, &bk_cfg_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &api_funcs); \ + +DT_INST_FOREACH_STATUS_OKAY(BK_INTEL_DEV_CFG) diff --git a/dts/bindings/pwm/intel,blinky-pwm.yaml b/dts/bindings/pwm/intel,blinky-pwm.yaml new file mode 100644 index 00000000000..10822317c09 --- /dev/null +++ b/dts/bindings/pwm/intel,blinky-pwm.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Intel blinky PWM + +compatible: "intel,blinky-pwm" + +include: [pwm-controller.yaml, base.yaml] + +properties: + reg: + required: true + + reg-offset: + type: int + required: true + description: PWM control register offset from base + + clock-frequency: + type: int + required: true + description: PWM Peripheral Clock frequency in Hz + + max-pins: + type: int + required: true + description: Maximum number of pins supported by platform + + "#pwm-cells": + const: 2 + +pwm-cells: + - channel + - period