Skip to content

Commit a913c72

Browse files
committed
feat(core): introduce TPS61062 backlight driver
[no changelog]
1 parent da2ddbd commit a913c72

File tree

7 files changed

+287
-42
lines changed

7 files changed

+287
-42
lines changed
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/*
2+
* This file is part of the Trezor project, https://trezor.io/
3+
*
4+
* Copyright (c) SatoshiLabs
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#ifdef KERNEL_MODE
21+
22+
#include <sys/irq.h>
23+
#include <sys/systick.h>
24+
#include <trezor_bsp.h>
25+
#include <trezor_rtl.h>
26+
27+
#include <io/backlight.h>
28+
29+
#define BACKLIGHT_CONTROL_T_UP_US 30 // may be in range 1-75
30+
#define BACKLIGHT_CONTROL_T_DOWN_US 198 // may be in range 180-300
31+
32+
// unused - for reference
33+
// #define BACKLIGHT_CONTROL_T_START_US 110 // may be in range 100-150
34+
// #define BACKLIGHT_CONTROL_T_D_US 2
35+
// #define BACKLIGHT_CONTROL_T_OFF_US 550
36+
37+
#define TIMER_PERIOD 32000 // 5 kHz @ 160MHz
38+
#define MAX_PULSE_WIDTH_US 200 // 5kHz
39+
40+
#define TIM_PULSE(width) \
41+
(TIMER_PERIOD - (width) * TIMER_PERIOD / MAX_PULSE_WIDTH_US)
42+
43+
#define STEPS 32
44+
#define DEFAULT_STEP 16 // DAC value after reset
45+
46+
// Backlight driver state
47+
typedef struct {
48+
// Set if driver is initialized
49+
bool initialized;
50+
// Level requested (0-255)
51+
int set_level;
52+
// Current backlight level in range 0-32
53+
int current_level;
54+
55+
DMA_HandleTypeDef dma;
56+
TIM_HandleTypeDef tim;
57+
58+
uint32_t pwm_data[STEPS + 2]; // max steps + 2 for start and end
59+
60+
} backlight_driver_t;
61+
62+
static backlight_driver_t g_backlight_driver = {
63+
.initialized = false,
64+
};
65+
66+
static void backlight_control_up(uint32_t *data, int steps);
67+
static void backlight_control_down(uint32_t *data, int steps);
68+
static void backlight_shutdown();
69+
70+
void backlight_init(backlight_action_t action) {
71+
backlight_driver_t *drv = &g_backlight_driver;
72+
73+
if (drv->initialized) {
74+
return;
75+
}
76+
77+
memset(drv, 0, sizeof(backlight_driver_t));
78+
79+
TPS61062_ILED_CLK_ENA();
80+
TPS61062_EN_CLK_ENA();
81+
82+
// action = BACKLIGHT_RESET.
83+
// action = BACKLIGHT_RETAIN is not implemented
84+
85+
// Initialize EN GPIO
86+
GPIO_InitTypeDef GPIO_EN_InitStructure = {0};
87+
GPIO_EN_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
88+
GPIO_EN_InitStructure.Pull = GPIO_NOPULL;
89+
GPIO_EN_InitStructure.Speed = GPIO_SPEED_LOW;
90+
GPIO_EN_InitStructure.Pin = TPS61062_EN_PIN;
91+
HAL_GPIO_Init(TPS61062_EN_PORT, &GPIO_EN_InitStructure);
92+
93+
HAL_GPIO_WritePin(TPS61062_EN_PORT, TPS61062_EN_PIN, GPIO_PIN_RESET);
94+
drv->current_level = 0;
95+
96+
__HAL_RCC_TIM3_CLK_ENABLE();
97+
drv->tim.State = HAL_TIM_STATE_RESET;
98+
drv->tim.Instance = TIM3;
99+
drv->tim.Init.Period = TIMER_PERIOD;
100+
drv->tim.Init.Prescaler = 0;
101+
drv->tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
102+
drv->tim.Init.CounterMode = TIM_COUNTERMODE_UP;
103+
drv->tim.Init.RepetitionCounter = 0;
104+
HAL_TIM_PWM_Init(&drv->tim);
105+
106+
TIM_OC_InitTypeDef TIM_OC_InitStructure = {0};
107+
TIM_OC_InitStructure.Pulse = 0;
108+
TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM1;
109+
TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;
110+
TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE;
111+
TIM_OC_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;
112+
TIM_OC_InitStructure.OCIdleState = TIM_OCIDLESTATE_RESET;
113+
TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
114+
HAL_TIM_PWM_ConfigChannel(&drv->tim, &TIM_OC_InitStructure, TIM_CHANNEL_1);
115+
116+
// Initialize ILED GPIO
117+
GPIO_InitTypeDef GPIO_ILED_InitStructure = {0};
118+
GPIO_ILED_InitStructure.Mode = GPIO_MODE_AF_PP;
119+
GPIO_ILED_InitStructure.Pull = GPIO_NOPULL;
120+
GPIO_ILED_InitStructure.Speed = GPIO_SPEED_LOW;
121+
GPIO_ILED_InitStructure.Pin = TPS61062_ILED_PIN;
122+
GPIO_ILED_InitStructure.Alternate = GPIO_AF2_TIM3;
123+
HAL_GPIO_Init(TPS61062_ILED_PORT, &GPIO_ILED_InitStructure);
124+
125+
__HAL_RCC_GPDMA1_CLK_ENABLE();
126+
drv->dma.Instance = GPDMA1_Channel3;
127+
drv->dma.Init.Direction = DMA_MEMORY_TO_PERIPH;
128+
drv->dma.Init.Mode = DMA_NORMAL;
129+
drv->dma.Init.Request = GPDMA1_REQUEST_TIM3_UP;
130+
drv->dma.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
131+
drv->dma.Init.SrcInc = DMA_SINC_INCREMENTED;
132+
drv->dma.Init.DestInc = DMA_DINC_FIXED;
133+
drv->dma.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
134+
drv->dma.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
135+
drv->dma.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
136+
drv->dma.Init.SrcBurstLength = 1;
137+
drv->dma.Init.DestBurstLength = 1;
138+
drv->dma.Init.TransferAllocatedPort =
139+
DMA_SRC_ALLOCATED_PORT1 | DMA_DEST_ALLOCATED_PORT0;
140+
drv->dma.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
141+
142+
HAL_DMA_Init(&drv->dma);
143+
HAL_DMA_ConfigChannelAttributes(
144+
&drv->dma, DMA_CHANNEL_PRIV | DMA_CHANNEL_SEC | DMA_CHANNEL_SRC_SEC |
145+
DMA_CHANNEL_DEST_SEC);
146+
147+
__HAL_TIM_ENABLE_DMA(&drv->tim, TIM_DMA_UPDATE);
148+
149+
HAL_TIM_Base_Start(&drv->tim);
150+
HAL_TIM_PWM_Start(&drv->tim, TIM_CHANNEL_1);
151+
152+
drv->initialized = true;
153+
}
154+
155+
void backlight_deinit(backlight_action_t action) {
156+
backlight_driver_t *drv = &g_backlight_driver;
157+
158+
if (!drv->initialized) {
159+
return;
160+
}
161+
162+
if (HAL_DMA_GetState(&drv->dma) == HAL_DMA_STATE_BUSY) {
163+
while (HAL_DMA_PollForTransfer(&drv->dma, HAL_DMA_FULL_TRANSFER,
164+
HAL_MAX_DELAY) != HAL_OK) {
165+
}
166+
}
167+
168+
if (action == BACKLIGHT_RESET) {
169+
backlight_shutdown();
170+
HAL_GPIO_DeInit(TPS61062_ILED_PORT, TPS61062_ILED_PIN);
171+
HAL_GPIO_DeInit(TPS61062_EN_PORT, TPS61062_EN_PIN);
172+
}
173+
174+
drv->initialized = false;
175+
}
176+
177+
int backlight_set(int val) {
178+
backlight_driver_t *drv = &g_backlight_driver;
179+
180+
if (!drv->initialized) {
181+
return 0;
182+
}
183+
184+
if (val < 0) {
185+
return drv->set_level;
186+
}
187+
188+
drv->set_level = val;
189+
val = STEPS * val / 255;
190+
191+
if (val == drv->current_level) {
192+
return val;
193+
}
194+
195+
if (val == 0) {
196+
backlight_shutdown();
197+
drv->current_level = 0;
198+
return val;
199+
}
200+
201+
if (HAL_DMA_GetState(&drv->dma) == HAL_DMA_STATE_BUSY) {
202+
while (HAL_DMA_PollForTransfer(&drv->dma, HAL_DMA_FULL_TRANSFER,
203+
HAL_MAX_DELAY) != HAL_OK) {
204+
}
205+
}
206+
207+
int pwm_data_idx = 0;
208+
memset(drv->pwm_data, 0, sizeof(drv->pwm_data));
209+
210+
if (drv->current_level == 0) {
211+
HAL_GPIO_WritePin(TPS61062_EN_PORT, TPS61062_EN_PIN, GPIO_PIN_SET);
212+
// if brightness control is shutdown, start with initial pulse
213+
drv->pwm_data[0] = TIMER_PERIOD;
214+
pwm_data_idx++;
215+
drv->current_level = DEFAULT_STEP;
216+
}
217+
218+
if (val > drv->current_level) {
219+
int steps = val - drv->current_level;
220+
backlight_control_up(&drv->pwm_data[pwm_data_idx], steps);
221+
pwm_data_idx += steps;
222+
223+
} else if (val < drv->current_level) {
224+
int steps = drv->current_level - val;
225+
backlight_control_down(&drv->pwm_data[pwm_data_idx], steps);
226+
pwm_data_idx += steps;
227+
}
228+
229+
drv->pwm_data[pwm_data_idx] = TIMER_PERIOD;
230+
231+
HAL_DMA_Start(&drv->dma, (uint32_t)drv->pwm_data,
232+
(uint32_t)&drv->tim.Instance->CCR1,
233+
(pwm_data_idx + 1) * sizeof(uint32_t));
234+
235+
drv->current_level = val;
236+
237+
return drv->current_level;
238+
}
239+
240+
int backlight_get(void) {
241+
backlight_driver_t *drv = &g_backlight_driver;
242+
243+
if (!drv->initialized) {
244+
return 0;
245+
}
246+
247+
return drv->set_level;
248+
}
249+
250+
static void backlight_control_up(uint32_t *data, int steps) {
251+
for (int i = 0; i < steps; i++) {
252+
data[i] = TIM_PULSE(BACKLIGHT_CONTROL_T_UP_US);
253+
}
254+
}
255+
256+
static void backlight_control_down(uint32_t *data, int steps) {
257+
for (int i = 0; i < steps; i++) {
258+
data[i] = TIM_PULSE(BACKLIGHT_CONTROL_T_DOWN_US);
259+
}
260+
}
261+
262+
static void backlight_shutdown() {
263+
HAL_GPIO_WritePin(TPS61062_EN_PORT, TPS61062_EN_PIN, GPIO_PIN_RESET);
264+
}
265+
266+
#endif

core/embed/models/T3W1/boards/trezor_t3w1_revA.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,12 @@
2323
#define DISPLAY_PWREN_PORT GPIOE
2424
#define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
2525

26-
#define TPS61043_FREQ 200
27-
#define TPS61043_TIM TIM17
28-
#define TPS61043_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE
29-
#define TPS61043_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE
30-
#define TPS61043_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET
31-
#define TPS61043_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET
32-
#define TPS61043_TIM_AF GPIO_AF14_TIM17
33-
#define TPS61043_TIM_OCMODE TIM_OCMODE_PWM1
34-
#define TPS61043_TIM_CHANNEL TIM_CHANNEL_1
35-
#define TPS61043_TIM_CCR CCR1
36-
#define TPS61043_PIN GPIO_PIN_9
37-
#define TPS61043_PORT GPIOB
38-
#define TPS61043_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
26+
#define TPS61062_ILED_PIN GPIO_PIN_3
27+
#define TPS61062_ILED_PORT GPIOE
28+
#define TPS61062_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
29+
#define TPS61062_EN_PIN GPIO_PIN_9
30+
#define TPS61062_EN_PORT GPIOB
31+
#define TPS61062_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
3932

4033
#define NPM1300_I2C_INSTANCE 0
4134

core/embed/models/T3W1/boards/trezor_t3w1_revA0.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,12 @@
2222
#define DISPLAY_PWREN_PORT GPIOE
2323
#define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
2424

25-
#define TPS61043_FREQ 200
26-
#define TPS61043_TIM TIM17
27-
#define TPS61043_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE
28-
#define TPS61043_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE
29-
#define TPS61043_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET
30-
#define TPS61043_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET
31-
#define TPS61043_TIM_AF GPIO_AF14_TIM17
32-
#define TPS61043_TIM_OCMODE TIM_OCMODE_PWM1
33-
#define TPS61043_TIM_CHANNEL TIM_CHANNEL_1
34-
#define TPS61043_TIM_CCR CCR1
35-
#define TPS61043_PIN GPIO_PIN_9
36-
#define TPS61043_PORT GPIOB
37-
#define TPS61043_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
25+
#define TPS61062_ILED_PIN GPIO_PIN_3
26+
#define TPS61062_ILED_PORT GPIOE
27+
#define TPS61062_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
28+
#define TPS61062_EN_PIN GPIO_PIN_9
29+
#define TPS61062_EN_PORT GPIOB
30+
#define TPS61062_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
3831

3932
#define NPM1300_I2C_INSTANCE 0
4033

core/embed/models/T3W1/boards/trezor_t3w1_revB.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,12 @@
2323
#define DISPLAY_PWREN_PORT GPIOG
2424
#define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOG_CLK_ENABLE
2525

26-
#define TPS61043_FREQ 200
27-
#define TPS61043_TIM TIM17
28-
#define TPS61043_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE
29-
#define TPS61043_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE
30-
#define TPS61043_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET
31-
#define TPS61043_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET
32-
#define TPS61043_TIM_AF GPIO_AF14_TIM17
33-
#define TPS61043_TIM_OCMODE TIM_OCMODE_PWM1
34-
#define TPS61043_TIM_CHANNEL TIM_CHANNEL_1
35-
#define TPS61043_TIM_CCR CCR1
36-
#define TPS61043_PIN GPIO_PIN_9
37-
#define TPS61043_PORT GPIOB
38-
#define TPS61043_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
26+
#define TPS61062_ILED_PIN GPIO_PIN_3
27+
#define TPS61062_ILED_PORT GPIOE
28+
#define TPS61062_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
29+
#define TPS61062_EN_PIN GPIO_PIN_9
30+
#define TPS61062_EN_PORT GPIOB
31+
#define TPS61062_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
3932

4033
#define NPM1300_I2C_INSTANCE 0
4134

core/site_scons/models/T3W1/trezor_t3w1_revA.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def configure(
5151

5252
features_available.append("backlight")
5353
defines += [("USE_BACKLIGHT", "1")]
54-
sources += ["embed/io/backlight/stm32/tps61043.c"]
54+
sources += ["embed/io/backlight/stm32u5/tps61062.c"]
5555
paths += ["embed/io/backlight/inc"]
5656

5757
if "input" in features_wanted:

core/site_scons/models/T3W1/trezor_t3w1_revA0.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def configure(
5050

5151
features_available.append("backlight")
5252
defines += [("USE_BACKLIGHT", "1")]
53-
sources += ["embed/io/backlight/stm32/tps61043.c"]
53+
sources += ["embed/io/backlight/stm32u5/tps61062.c"]
5454
paths += ["embed/io/backlight/inc"]
5555

5656
if "input" in features_wanted:

core/site_scons/models/T3W1/trezor_t3w1_revB.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def configure(
5151

5252
features_available.append("backlight")
5353
defines += [("USE_BACKLIGHT", "1")]
54-
sources += ["embed/io/backlight/stm32/tps61043.c"]
54+
sources += ["embed/io/backlight/stm32u5/tps61062.c"]
5555
paths += ["embed/io/backlight/inc"]
5656

5757
if "input" in features_wanted:

0 commit comments

Comments
 (0)