xref: /rk3399_ARM-atf/plat/rockchip/rk3399/drivers/pwm/pwm.c (revision 5d3b10675320aadbb1855a836d65bcd633581f7c)
1*5d3b1067SCaesar Wang /*
2*5d3b1067SCaesar Wang  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3*5d3b1067SCaesar Wang  *
4*5d3b1067SCaesar Wang  * Redistribution and use in source and binary forms, with or without
5*5d3b1067SCaesar Wang  * modification, are permitted provided that the following conditions are met:
6*5d3b1067SCaesar Wang  *
7*5d3b1067SCaesar Wang  * Redistributions of source code must retain the above copyright notice, this
8*5d3b1067SCaesar Wang  * list of conditions and the following disclaimer.
9*5d3b1067SCaesar Wang  *
10*5d3b1067SCaesar Wang  * Redistributions in binary form must reproduce the above copyright notice,
11*5d3b1067SCaesar Wang  * this list of conditions and the following disclaimer in the documentation
12*5d3b1067SCaesar Wang  * and/or other materials provided with the distribution.
13*5d3b1067SCaesar Wang  *
14*5d3b1067SCaesar Wang  * Neither the name of ARM nor the names of its contributors may be used
15*5d3b1067SCaesar Wang  * to endorse or promote products derived from this software without specific
16*5d3b1067SCaesar Wang  * prior written permission.
17*5d3b1067SCaesar Wang  *
18*5d3b1067SCaesar Wang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5d3b1067SCaesar Wang  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5d3b1067SCaesar Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5d3b1067SCaesar Wang  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5d3b1067SCaesar Wang  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5d3b1067SCaesar Wang  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5d3b1067SCaesar Wang  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5d3b1067SCaesar Wang  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5d3b1067SCaesar Wang  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5d3b1067SCaesar Wang  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5d3b1067SCaesar Wang  * POSSIBILITY OF SUCH DAMAGE.
29*5d3b1067SCaesar Wang  */
30*5d3b1067SCaesar Wang 
31*5d3b1067SCaesar Wang #include <plat_private.h>
32*5d3b1067SCaesar Wang #include <pmu.h>
33*5d3b1067SCaesar Wang #include <pwm.h>
34*5d3b1067SCaesar Wang #include <soc.h>
35*5d3b1067SCaesar Wang 
36*5d3b1067SCaesar Wang #define PWM0_IOMUX_PWM_EN		(1 << 0)
37*5d3b1067SCaesar Wang #define PWM1_IOMUX_PWM_EN		(1 << 1)
38*5d3b1067SCaesar Wang #define PWM2_IOMUX_PWM_EN		(1 << 2)
39*5d3b1067SCaesar Wang #define PWM3_IOMUX_PWM_EN		(1 << 3)
40*5d3b1067SCaesar Wang 
41*5d3b1067SCaesar Wang struct pwm_data_s {
42*5d3b1067SCaesar Wang 	uint32_t iomux_bitmask;
43*5d3b1067SCaesar Wang 	uint32_t enable_bitmask;
44*5d3b1067SCaesar Wang };
45*5d3b1067SCaesar Wang 
46*5d3b1067SCaesar Wang static struct pwm_data_s pwm_data;
47*5d3b1067SCaesar Wang 
48*5d3b1067SCaesar Wang /*
49*5d3b1067SCaesar Wang  * Disable the PWMs.
50*5d3b1067SCaesar Wang  */
51*5d3b1067SCaesar Wang void disable_pwms(void)
52*5d3b1067SCaesar Wang {
53*5d3b1067SCaesar Wang 	uint32_t i, val;
54*5d3b1067SCaesar Wang 
55*5d3b1067SCaesar Wang 	pwm_data.iomux_bitmask = 0;
56*5d3b1067SCaesar Wang 
57*5d3b1067SCaesar Wang 	/* Save PWMs pinmux and change PWMs pinmux to GPIOs */
58*5d3b1067SCaesar Wang 	val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
59*5d3b1067SCaesar Wang 	if (((val >> GRF_GPIO4C2_IOMUX_SHIFT) &
60*5d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C2_IOMUX_PWM) {
61*5d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM0_IOMUX_PWM_EN;
62*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
63*5d3b1067SCaesar Wang 				    GRF_GPIO4C2_IOMUX_SHIFT);
64*5d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
65*5d3b1067SCaesar Wang 	}
66*5d3b1067SCaesar Wang 
67*5d3b1067SCaesar Wang 	val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
68*5d3b1067SCaesar Wang 	if (((val >> GRF_GPIO4C6_IOMUX_SHIFT) &
69*5d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C6_IOMUX_PWM) {
70*5d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM1_IOMUX_PWM_EN;
71*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
72*5d3b1067SCaesar Wang 				    GRF_GPIO4C6_IOMUX_SHIFT);
73*5d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
74*5d3b1067SCaesar Wang 	}
75*5d3b1067SCaesar Wang 
76*5d3b1067SCaesar Wang 	val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX);
77*5d3b1067SCaesar Wang 	if (((val >> PMUGRF_GPIO1C3_IOMUX_SHIFT) &
78*5d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO1C3_IOMUX_PWM) {
79*5d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM2_IOMUX_PWM_EN;
80*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
81*5d3b1067SCaesar Wang 				    PMUGRF_GPIO1C3_IOMUX_SHIFT);
82*5d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
83*5d3b1067SCaesar Wang 	}
84*5d3b1067SCaesar Wang 
85*5d3b1067SCaesar Wang 	val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX);
86*5d3b1067SCaesar Wang 	if (((val >> PMUGRF_GPIO0A6_IOMUX_SHIFT) &
87*5d3b1067SCaesar Wang 		GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO0A6_IOMUX_PWM) {
88*5d3b1067SCaesar Wang 		pwm_data.iomux_bitmask |= PWM3_IOMUX_PWM_EN;
89*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
90*5d3b1067SCaesar Wang 				    PMUGRF_GPIO0A6_IOMUX_SHIFT);
91*5d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
92*5d3b1067SCaesar Wang 	}
93*5d3b1067SCaesar Wang 
94*5d3b1067SCaesar Wang 	/* Disable the pwm channel */
95*5d3b1067SCaesar Wang 	pwm_data.enable_bitmask = 0;
96*5d3b1067SCaesar Wang 	for (i = 0; i < 4; i++) {
97*5d3b1067SCaesar Wang 		val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
98*5d3b1067SCaesar Wang 		if ((val & PWM_ENABLE) != PWM_ENABLE)
99*5d3b1067SCaesar Wang 			continue;
100*5d3b1067SCaesar Wang 		pwm_data.enable_bitmask |= (1 << i);
101*5d3b1067SCaesar Wang 		mmio_write_32(PWM_BASE + PWM_CTRL(i), val & ~PWM_ENABLE);
102*5d3b1067SCaesar Wang 	}
103*5d3b1067SCaesar Wang }
104*5d3b1067SCaesar Wang 
105*5d3b1067SCaesar Wang /*
106*5d3b1067SCaesar Wang  * Enable the PWMs.
107*5d3b1067SCaesar Wang  */
108*5d3b1067SCaesar Wang void enable_pwms(void)
109*5d3b1067SCaesar Wang {
110*5d3b1067SCaesar Wang 	uint32_t i, val;
111*5d3b1067SCaesar Wang 
112*5d3b1067SCaesar Wang 	for (i = 0; i < 4; i++) {
113*5d3b1067SCaesar Wang 		val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
114*5d3b1067SCaesar Wang 		if (!(pwm_data.enable_bitmask & (1 << i)))
115*5d3b1067SCaesar Wang 			continue;
116*5d3b1067SCaesar Wang 		mmio_write_32(PWM_BASE + PWM_CTRL(i), val | PWM_ENABLE);
117*5d3b1067SCaesar Wang 	}
118*5d3b1067SCaesar Wang 
119*5d3b1067SCaesar Wang 	/* Restore all IOMUXes */
120*5d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM3_IOMUX_PWM_EN) {
121*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(PMUGRF_GPIO0A6_IOMUX_PWM,
122*5d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
123*5d3b1067SCaesar Wang 				    PMUGRF_GPIO0A6_IOMUX_SHIFT);
124*5d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
125*5d3b1067SCaesar Wang 	}
126*5d3b1067SCaesar Wang 
127*5d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM2_IOMUX_PWM_EN) {
128*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(PMUGRF_GPIO1C3_IOMUX_PWM,
129*5d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
130*5d3b1067SCaesar Wang 				    PMUGRF_GPIO1C3_IOMUX_SHIFT);
131*5d3b1067SCaesar Wang 		mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
132*5d3b1067SCaesar Wang 	}
133*5d3b1067SCaesar Wang 
134*5d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM1_IOMUX_PWM_EN) {
135*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_GPIO4C6_IOMUX_PWM,
136*5d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
137*5d3b1067SCaesar Wang 				    GRF_GPIO4C6_IOMUX_SHIFT);
138*5d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
139*5d3b1067SCaesar Wang 	}
140*5d3b1067SCaesar Wang 
141*5d3b1067SCaesar Wang 	if (pwm_data.iomux_bitmask & PWM0_IOMUX_PWM_EN) {
142*5d3b1067SCaesar Wang 		val = BITS_WITH_WMASK(GRF_GPIO4C2_IOMUX_PWM,
143*5d3b1067SCaesar Wang 				    GRF_IOMUX_2BIT_MASK,
144*5d3b1067SCaesar Wang 				    GRF_GPIO4C2_IOMUX_SHIFT);
145*5d3b1067SCaesar Wang 		mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
146*5d3b1067SCaesar Wang 	}
147*5d3b1067SCaesar Wang }
148