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