blob: f297ff00814073832a40eb63541cef03c67cf22f [file] [log] [blame]
Junyi Zhaoc0858502024-01-17 10:59:34 +08001/*
2 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include "fd650.h"
8#include "common.h"
9#include "uart.h"
10#include "FreeRTOS.h"
11#include "timer_source.h"
12#include <task.h>
13#include <fd650_plat.h>
14#include <string.h>
15#include "mailbox-api.h"
16#include "vrtc.h"
17#include "timers.h" /* Software timer related API prototypes. */
18
19#define DRIVER_NAME "FD650"
20#define DEFAULT_UDELAY 3
21
22static struct fd650_bus *current_bus;
23static uint8_t fd650_state = FD650_STATE_TIME;
24
25static int fd650_sda_get(struct fd650_bus *bus)
26{
27 int value;
28
29 xGpioSetDir(bus->sda, GPIO_DIR_IN);
30 value = xGpioGetValue(bus->sda);
31 xGpioSetDir(bus->sda, GPIO_DIR_OUT);
32
33 return value;
34}
35
36static void fd650_sda_set(struct fd650_bus *bus, enum GpioOutLevelType bit)
37{
38 xGpioSetValue(bus->sda, bit);
39}
40
41static void fd650_scl_set(struct fd650_bus *bus, enum GpioOutLevelType bit)
42{
43 xGpioSetValue(bus->scl, bit);
44}
45
46void fd650_start(struct fd650_bus *bus)
47{
48 fd650_sda_set(bus, GPIO_LEVEL_HIGH);
49 fd650_scl_set(bus, GPIO_LEVEL_HIGH);
50 udelay(bus->udelay);
51 fd650_sda_set(bus, GPIO_LEVEL_LOW);
52 udelay(bus->udelay);
53 fd650_scl_set(bus, GPIO_LEVEL_LOW);
54}
55
56void fd650_stop(struct fd650_bus *bus)
57{
58 fd650_sda_set(bus, GPIO_LEVEL_LOW);
59 udelay(bus->udelay);
60 fd650_scl_set(bus, GPIO_LEVEL_HIGH);
61 udelay(bus->udelay);
62 fd650_sda_set(bus, GPIO_LEVEL_HIGH);
63 udelay(bus->udelay);
64}
65
66void fd650_wrbyte(struct fd650_bus *bus, uint8_t dat)
67{
68 uint8_t i;
69
70 for (i = 0; i != 8; i++) {
71 if (dat & 0x80)
72 fd650_sda_set(bus, GPIO_LEVEL_HIGH);
73 else
74 fd650_sda_set(bus, GPIO_LEVEL_LOW);
75 udelay(bus->udelay);
76 fd650_scl_set(bus, GPIO_LEVEL_HIGH);
77 dat <<= 1;
78 udelay(bus->udelay);
79 fd650_scl_set(bus, GPIO_LEVEL_LOW);
80 }
81 fd650_sda_set(bus, GPIO_LEVEL_HIGH);
82 udelay(bus->udelay);
83 fd650_scl_set(bus, GPIO_LEVEL_HIGH);
84 udelay(bus->udelay);
85 fd650_scl_set(bus, GPIO_LEVEL_LOW);
86}
87
88uint8_t fd650_rdbyte(struct fd650_bus *bus)
89{
90 uint8_t dat, i;
91
92 fd650_sda_set(bus, GPIO_LEVEL_HIGH);
93 dat = 0;
94 for (i = 0; i != 8; i++) {
95 udelay(bus->udelay);
96 fd650_scl_set(bus, GPIO_LEVEL_HIGH);
97 udelay(bus->udelay);
98 dat <<= 1;
99 if (fd650_sda_get(bus))
100 dat++;
101 fd650_scl_set(bus, GPIO_LEVEL_LOW);
102 }
103 fd650_sda_set(bus, GPIO_LEVEL_HIGH);
104 udelay(bus->udelay);
105 fd650_scl_set(bus, GPIO_LEVEL_HIGH);
106 udelay(bus->udelay);
107 fd650_scl_set(bus, GPIO_LEVEL_LOW);
108
109 return dat;
110}
111
112void fd650_write(struct fd650_bus *bus, uint32_t cmd)
113{
114 fd650_start(bus);
115 fd650_wrbyte(bus, ((uint8_t)(cmd >> 7) & 0x3E) | 0x40);
116 fd650_wrbyte(bus, (uint8_t)cmd);
117 fd650_stop(bus);
118
119}
120
121uint8_t fd650_read(struct fd650_bus *bus)
122{
123 uint8_t keycode = 0;
124
125 fd650_start(bus);
126 fd650_wrbyte(bus, ((uint8_t)(FD650_GET_KEY >> 7) & 0x3E) | (0x01 | 0x40));
127 keycode = fd650_rdbyte(bus);
128 fd650_stop(bus);
129 if ((keycode & 0x00000040) == 0)
130 keycode = 0;
131 return keycode;
132}
133
134#define LEDMAPNUM 22
135
136struct led_bitmap {
137 uint8_t character;
138 uint8_t bitmap;
139};
140
141const struct led_bitmap bcd_decode_tab[LEDMAPNUM] = {
142 {'0', 0x3F}, {'1', 0x06}, {'2', 0x5B}, {'3', 0x4F},
143 {'4', 0x66}, {'5', 0x6D}, {'6', 0x7D}, {'7', 0x07},
144 {'8', 0x7F}, {'9', 0x6F}, {'a', 0x77}, {'A', 0x77},
145 {'b', 0x7C}, {'B', 0x7C}, {'c', 0x58}, {'C', 0x39},
146 {'d', 0x5E}, {'D', 0x5E}, {'e', 0x79}, {'E', 0x79},
147 {'f', 0x71}, {'F', 0x71}
148};
149
150uint8_t led_get_code(char ch)
151{
152 uint8_t i, bitmap = 0x00;
153
154 for (i = 0; i < LEDMAPNUM; i++) {
155 if (bcd_decode_tab[i].character == ch) {
156 bitmap = bcd_decode_tab[i].bitmap;
157 break;
158 }
159 }
160
161 return bitmap;
162}
163
164void led_show_650(char *str, unsigned char sec_flag, unsigned char lock)
165{
166 int i, iLenth;
167 int ret;
168 int data[4] = {0x00, 0x00, 0x00, 0x00};
169 struct udevice *dev;
170
171 if (!current_bus) {
172 printf("invalid fd650 bus\n");
173 return;
174 }
175
176 if (strcmp(str, "") == 0) {
177 printf("invalid fd650 string\n");
178 return;
179 }
180 iLenth = strlen(str);
181 if (iLenth > 4)
182 iLenth = 4;
183 for (i = 0; i < iLenth; i++)
184 data[i] = led_get_code(str[i]);
185
186 fd650_write(current_bus, FD650_SYSON_8);
187 fd650_write(current_bus, FD650_DIG0 | (uint8_t)data[0] | FD650_DOT);
188 if (sec_flag)
189 fd650_write(current_bus, FD650_DIG1 | (uint8_t)data[1] | FD650_DOT);
190 else
191 fd650_write(current_bus, FD650_DIG1 | (uint8_t)data[1]);
192 if (lock)
193 fd650_write(current_bus, FD650_DIG2 | (uint8_t)data[2] | FD650_DOT);
194 else
195 fd650_write(current_bus, FD650_DIG2 | (uint8_t)data[2]);
196 fd650_write(current_bus, FD650_DIG3 | (uint8_t)data[3] | FD650_DOT);
197}
198
199static void *prvFD650GetInfo(void *msg)
200{
201 uint8_t data[5] = {0};
202 uint8_t state = *(((uint8_t *)msg));
203 int colon_on = *(((uint8_t *)msg) + 1);
204
205 switch (state) {
206 case FD650_STATE_SHOW:
207 data[0] = *(((uint8_t *)msg) + 2);
208 data[1] = *(((uint8_t *)msg) + 3);
209 data[2] = *(((uint8_t *)msg) + 4);
210 data[3] = *(((uint8_t *)msg) + 5);
211 led_show_650(data, colon_on, 1);
212 fd650_state = FD650_STATE_SHOW;
213 break;
214 case FD650_STATE_TIME:
215 fd650_state = FD650_STATE_TIME;
216 break;
217 default:
218 break;
219 } /* end switch */
220
221 return NULL;
222}
223
224static void fd650ShowTime(TimerHandle_t xTimer)
225{
226 char str[5];
227
228 if (fd650_state == FD650_STATE_TIME) {
Junyi Zhao821ee652024-03-05 13:59:45 +0800229 poweroff_get_rtc_min_sec(str);
Junyi Zhaoc0858502024-01-17 10:59:34 +0800230 led_show_650(str, 1, 1);
231 }
232}
233
234int fd650_bus_init(uint32_t id)
235{
236 TimerHandle_t xFD650Timer = NULL;
237 int ret;
238
239 current_bus = &fd650_plat_data[id];
240 xPinmuxSet(current_bus->sda, PIN_FUNC0);
241 xPinmuxSet(current_bus->scl, PIN_FUNC0);
242 xGpioSetDir(current_bus->sda, GPIO_DIR_OUT);
243 xGpioSetDir(current_bus->scl, GPIO_DIR_OUT);
244 xGpioSetValue(current_bus->sda, GPIO_LEVEL_LOW);
245 xGpioSetValue(current_bus->scl, GPIO_LEVEL_LOW);
246
247 fd650_sda_set(current_bus, GPIO_LEVEL_HIGH);
248 fd650_scl_set(current_bus, GPIO_LEVEL_HIGH);
249 udelay(100);
250 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_FD650_INFO,
251 prvFD650GetInfo, 1);
252 if (ret == MBOX_CALL_MAX) {
253 iprintf("%s: mbox cmd 0x%x register fail\n", DRIVER_NAME, MBX_CMD_GET_FD650_INFO);
254 return -pdFREERTOS_ERRNO_EINVAL;
255 }
256
257 /* creat fd650 timer */
258 xFD650Timer = xTimerCreate("Timer", pdMS_TO_TICKS(500), pdTRUE, NULL, fd650ShowTime);
259 iprintf("%s: Starting fd650 task ...\n", DRIVER_NAME);
260 xTimerStart(xFD650Timer, 0);
261
262}