xref: /rk3399_ARM-atf/plat/rockchip/rk3399/drivers/pwm/pwm.c (revision f132b4a05b23916c1101add4bd6d973a99983719)
15d3b1067SCaesar Wang /*
25d3b1067SCaesar Wang  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
35d3b1067SCaesar Wang  *
4*82cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
55d3b1067SCaesar Wang  */
65d3b1067SCaesar Wang 
75d3b1067SCaesar Wang #include <plat_private.h>
85d3b1067SCaesar Wang #include <pmu.h>
95d3b1067SCaesar Wang #include <pwm.h>
105d3b1067SCaesar Wang #include <soc.h>
115d3b1067SCaesar Wang 
125d3b1067SCaesar Wang #define PWM0_IOMUX_PWM_EN		(1 << 0)
135d3b1067SCaesar Wang #define PWM1_IOMUX_PWM_EN		(1 << 1)
145d3b1067SCaesar Wang #define PWM2_IOMUX_PWM_EN		(1 << 2)
155d3b1067SCaesar Wang #define PWM3_IOMUX_PWM_EN		(1 << 3)
165d3b1067SCaesar Wang 
175d3b1067SCaesar Wang struct pwm_data_s {
185d3b1067SCaesar Wang 	uint32_t iomux_bitmask;
195d3b1067SCaesar Wang 	uint32_t enable_bitmask;
205d3b1067SCaesar Wang };
215d3b1067SCaesar Wang 
225d3b1067SCaesar Wang static struct pwm_data_s pwm_data;
235d3b1067SCaesar Wang 
245d3b1067SCaesar Wang /*
255d3b1067SCaesar Wang  * Disable the PWMs.
265d3b1067SCaesar Wang  */
disable_pwms(void)275d3b1067SCaesar Wang void disable_pwms(void)
285d3b1067SCaesar Wang {
295d3b1067SCaesar Wang 	uint32_t i, val;
305d3b1067SCaesar Wang 
315d3b1067SCaesar Wang 	pwm_data.iomux_bitmask = 0;
325d3b1067SCaesar Wang 
335d3b1067SCaesar Wang 	/* Save PWMs pinmux and change PWMs pinmux to GPIOs */
345d3b1067SCaesar Wang 	val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
355d3b1067SCaesar Wang 	if (((val >> GRF_GPIO4C2_IOMUX_SHIFT) &
365d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C2_IOMUX_PWM) {
375d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM0_IOMUX_PWM_EN;
385d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
395d3b1067SCaesar Wang 				    GRF_GPIO4C2_IOMUX_SHIFT);
405d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
415d3b1067SCaesar Wang 	}
425d3b1067SCaesar Wang 
435d3b1067SCaesar Wang 	val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
445d3b1067SCaesar Wang 	if (((val >> GRF_GPIO4C6_IOMUX_SHIFT) &
455d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C6_IOMUX_PWM) {
465d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM1_IOMUX_PWM_EN;
475d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
485d3b1067SCaesar Wang 				    GRF_GPIO4C6_IOMUX_SHIFT);
495d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
505d3b1067SCaesar Wang 	}
515d3b1067SCaesar Wang 
525d3b1067SCaesar Wang 	val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX);
535d3b1067SCaesar Wang 	if (((val >> PMUGRF_GPIO1C3_IOMUX_SHIFT) &
545d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO1C3_IOMUX_PWM) {
555d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM2_IOMUX_PWM_EN;
565d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
575d3b1067SCaesar Wang 				    PMUGRF_GPIO1C3_IOMUX_SHIFT);
585d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
595d3b1067SCaesar Wang 	}
605d3b1067SCaesar Wang 
615d3b1067SCaesar Wang 	val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX);
625d3b1067SCaesar Wang 	if (((val >> PMUGRF_GPIO0A6_IOMUX_SHIFT) &
635d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO0A6_IOMUX_PWM) {
645d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM3_IOMUX_PWM_EN;
655d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
665d3b1067SCaesar Wang 				    PMUGRF_GPIO0A6_IOMUX_SHIFT);
675d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
685d3b1067SCaesar Wang 	}
695d3b1067SCaesar Wang 
705d3b1067SCaesar Wang 	/* Disable the pwm channel */
715d3b1067SCaesar Wang 	pwm_data.enable_bitmask = 0;
725d3b1067SCaesar Wang 	for (i = 0; i < 4; i++) {
735d3b1067SCaesar Wang 		val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
745d3b1067SCaesar Wang 		if ((val & PWM_ENABLE) != PWM_ENABLE)
755d3b1067SCaesar Wang 			continue;
765d3b1067SCaesar Wang 		pwm_data.enable_bitmask |= (1 << i);
775d3b1067SCaesar Wang 		mmio_write_32(PWM_BASE + PWM_CTRL(i), val & ~PWM_ENABLE);
785d3b1067SCaesar Wang 	}
795d3b1067SCaesar Wang }
805d3b1067SCaesar Wang 
815d3b1067SCaesar Wang /*
825d3b1067SCaesar Wang  * Enable the PWMs.
835d3b1067SCaesar Wang  */
enable_pwms(void)845d3b1067SCaesar Wang void enable_pwms(void)
855d3b1067SCaesar Wang {
865d3b1067SCaesar Wang 	uint32_t i, val;
875d3b1067SCaesar Wang 
885d3b1067SCaesar Wang 	for (i = 0; i < 4; i++) {
895d3b1067SCaesar Wang 		val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
905d3b1067SCaesar Wang 		if (!(pwm_data.enable_bitmask & (1 << i)))
915d3b1067SCaesar Wang 			continue;
925d3b1067SCaesar Wang 		mmio_write_32(PWM_BASE + PWM_CTRL(i), val | PWM_ENABLE);
935d3b1067SCaesar Wang 	}
945d3b1067SCaesar Wang 
955d3b1067SCaesar Wang 	/* Restore all IOMUXes */
965d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM3_IOMUX_PWM_EN) {
975d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(PMUGRF_GPIO0A6_IOMUX_PWM,
985d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
995d3b1067SCaesar Wang 				    PMUGRF_GPIO0A6_IOMUX_SHIFT);
1005d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
1015d3b1067SCaesar Wang 	}
1025d3b1067SCaesar Wang 
1035d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM2_IOMUX_PWM_EN) {
1045d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(PMUGRF_GPIO1C3_IOMUX_PWM,
1055d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
1065d3b1067SCaesar Wang 				    PMUGRF_GPIO1C3_IOMUX_SHIFT);
1075d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
1085d3b1067SCaesar Wang 	}
1095d3b1067SCaesar Wang 
1105d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM1_IOMUX_PWM_EN) {
1115d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_GPIO4C6_IOMUX_PWM,
1125d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
1135d3b1067SCaesar Wang 				    GRF_GPIO4C6_IOMUX_SHIFT);
1145d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
1155d3b1067SCaesar Wang 	}
1165d3b1067SCaesar Wang 
1175d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM0_IOMUX_PWM_EN) {
1185d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_GPIO4C2_IOMUX_PWM,
1195d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
1205d3b1067SCaesar Wang 				    GRF_GPIO4C2_IOMUX_SHIFT);
1215d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
1225d3b1067SCaesar Wang 	}
1235d3b1067SCaesar Wang }
124