2 * kernel/driver/char/modem_interface/boot_protocol.c
4 * Generic modem boot protocol
6 * Author: Jiayong Yang(Jiayong.Yang@spreadtrum.com)
7 * Created: Jul 27, 2012
8 * Copyright: Spreadtrum Inc.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 /* #define VERBOSE_DEBUG */
17 #include <linux/init.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/semaphore.h>
21 #include <linux/irqflags.h>
22 #include "modem_buffer.h"
23 #include "modem_interface_driver.h"
25 #define SETUP_PACKET_SIZE 8
26 #define ACK_PACKET_SIZE 6
27 typedef struct dl_setup_packet{
28 unsigned short data_packet_size;
29 unsigned short data_type;
30 unsigned short data_check_sum;
31 unsigned short setup_check_sum;
33 typedef enum MBUS_DL_status{
45 extern void modem_intf_ctrl_gpio_handle_boot(int status);
46 extern int dloader_abort();
48 char *boot_status_string(DL_STATUS_E status)
51 case MBUS_DL_IDLE: return "DL_IDLE";
52 case MBUS_DL_WAIT_REQ: return "DL_WAIT_REQ";
53 case MBUS_DL_WAIT_RTS: return "DL_WAIT_RTS";
54 case MBUS_DL_SETUP: return "DL_SETUP";
55 case MBUS_DL_SETUP_COMP: return "DL_SETUP_COMP";
56 case MBUS_DL_DATA: return "DL_DATA";
57 case MBUS_DL_DATA_COMP: return "DL_DATA_COMP";
58 case MBUS_DL_ACK: return "DL_ACK";
61 return "UNKNOWN status";
66 static void boot_idle(struct modem_message_node *msg,struct modem_intf_device *device)
68 int send_bffer_index=0xFF;
71 device->status = (int)MBUS_DL_WAIT_REQ;
73 case MODEM_TRANSFER_REQ:
74 send_bffer_index = pingpang_buffer_send(&device->send_buffer);
75 if (send_bffer_index!= 0xFF) {
76 device->out_transfering = send_bffer_index;
77 device->status = (int)MBUS_DL_WAIT_RTS;
81 modem_intf_set_mode(msg->parameter2, 1);
82 device->status = (int)MBUS_DL_IDLE;
83 device->out_transfering = 0;
90 static void boot_wait_request(struct modem_message_node *msg,struct modem_intf_device *device)
92 int send_bffer_index=0xFF;
94 case MODEM_TRANSFER_REQ:
95 send_bffer_index = pingpang_buffer_send(&device->send_buffer);
96 if(send_bffer_index!= 0xFF){
97 device->out_transfering = send_bffer_index;
98 device->op->write(device->send_buffer.buffer[send_bffer_index].addr,SETUP_PACKET_SIZE);
99 device->status = (int)MBUS_DL_SETUP;
103 modem_intf_set_mode(msg->parameter2, 1);
104 device->status = (int)MBUS_DL_IDLE;
105 device->out_transfering = 0;
108 case MODEM_TRANSFER_END:
114 static void boot_wait_RTS(struct modem_message_node *msg,struct modem_intf_device *device)
116 int send_bffer_index=0xFF;
117 unsigned short *data;
119 case MODEM_SLAVE_RTS:
120 if(device->out_transfering < 2){
121 send_bffer_index = device->out_transfering;
122 data = (unsigned short *)device->send_buffer.buffer[send_bffer_index].addr;
123 device->op->write((char *)data,SETUP_PACKET_SIZE);
124 device->status = (int)MBUS_DL_SETUP;
127 case MODEM_TRANSFER_REQ:
128 device->out_transfer_pending = 1;
131 modem_intf_set_mode(msg->parameter2, 1);
132 device->status = (int)MBUS_DL_IDLE;
133 device->out_transfering = 0;
140 static void boot_setup(struct modem_message_node *msg,struct modem_intf_device *device)
142 int send_bffer_index=0xFF;
146 case MODEM_TRANSFER_END:
147 device->status = (int)MBUS_DL_SETUP_COMP;
149 case MODEM_TRANSFER_REQ:
150 device->out_transfer_pending = 1;
152 case MODEM_SLAVE_RTS:
153 if(device->out_transfering < 2){
154 send_bffer_index = device->out_transfering;
155 buffer = &device->send_buffer.buffer[send_bffer_index].addr[SETUP_PACKET_SIZE];
156 size = device->send_buffer.buffer[send_bffer_index].write_point;
157 if (size <= SETUP_PACKET_SIZE)
159 device->op->write(buffer,size - SETUP_PACKET_SIZE);
160 pingpang_buffer_send_complete(&device->send_buffer,device->out_transfering);
161 device->out_transfering = 0xFF;
162 device->status = (int)MBUS_DL_DATA;
164 if(device->out_transfer_pending){
165 send_bffer_index = pingpang_buffer_send(&device->send_buffer);
166 if(send_bffer_index!= 0xFF){
167 device->out_transfering = send_bffer_index;
168 size = device->send_buffer.buffer[send_bffer_index].write_point;
169 device->op->write(device->send_buffer.buffer[send_bffer_index].addr,size);
171 device->out_transfer_pending = 0;
175 modem_intf_set_mode(msg->parameter2, 1);
176 device->status = (int)MBUS_DL_IDLE;
177 device->out_transfering = 0;
185 static void boot_setup_comp(struct modem_message_node *msg,struct modem_intf_device *device)
187 int send_bffer_index=0xFF;
192 case MODEM_SLAVE_RTS:
193 if(device->out_transfering < 2){
194 send_bffer_index = device->out_transfering;
195 buffer = &device->send_buffer.buffer[send_bffer_index].addr[SETUP_PACKET_SIZE];
196 size = device->send_buffer.buffer[send_bffer_index].write_point;
197 if (size <= SETUP_PACKET_SIZE)
199 device->op->write(buffer,size - SETUP_PACKET_SIZE);
200 device->status = (int)MBUS_DL_DATA;
201 if(device->out_transfer_pending){
202 pingpang_buffer_send_complete(&device->send_buffer,device->out_transfering);
203 device->out_transfering = 0xFF;
204 send_bffer_index = pingpang_buffer_send(&device->send_buffer);
205 if(send_bffer_index!= 0xFF){
206 device->out_transfering = send_bffer_index;
207 size = device->send_buffer.buffer[send_bffer_index].write_point;
208 device->op->write(device->send_buffer.buffer[send_bffer_index].addr,size);
210 device->out_transfer_pending = 0;
214 case MODEM_TRANSFER_REQ:
215 device->out_transfer_pending = 1;
218 modem_intf_set_mode(msg->parameter2, 1);
219 device->status = (int)MBUS_DL_IDLE;
220 device->out_transfering = 0;
228 static void boot_data(struct modem_message_node *msg,struct modem_intf_device *device)
230 unsigned short *data;
231 int send_bffer_index=0xFF;
235 case MODEM_TRANSFER_END:
236 if(device->out_transfering < 2){
237 pingpang_buffer_send_complete(&device->send_buffer,device->out_transfering);
238 device->out_transfering = 0xFF;
239 device->status = (int)MBUS_DL_DATA_COMP;
242 case MODEM_TRANSFER_REQ:
243 if(device->out_transfering < 2){
244 pingpang_buffer_send_complete(&device->send_buffer,device->out_transfering);
245 device->out_transfering = 0xFF;
247 send_bffer_index = pingpang_buffer_send(&device->send_buffer);
248 if(send_bffer_index!= 0xFF){
249 device->out_transfering = send_bffer_index;
250 size = device->send_buffer.buffer[send_bffer_index].write_point;
251 device->op->write(device->send_buffer.buffer[send_bffer_index].addr,size);
254 case MODEM_SLAVE_RTS:
255 pingpang_buffer_send_complete(&device->send_buffer,device->out_transfering);
256 device->op->read(device->recv_buffer.buffer[1].addr,8);
257 device->out_transfering = 0xFF;
258 data = (unsigned short *)device->recv_buffer.buffer[1].addr;
259 device->status = (int)MBUS_DL_ACK;
260 if(device->out_transfer_pending){
261 send_bffer_index = pingpang_buffer_send(&device->send_buffer);
262 if(send_bffer_index!= 0xFF){
263 device->out_transfering = send_bffer_index;
264 size = device->send_buffer.buffer[send_bffer_index].write_point;
265 device->op->write(device->send_buffer.buffer[send_bffer_index].addr,size);
267 device->out_transfer_pending = 0;
271 modem_intf_set_mode(msg->parameter2, 1);
272 device->status = (int)MBUS_DL_IDLE;
273 device->out_transfering = 0;
280 static void boot_data_comp(struct modem_message_node *msg,struct modem_intf_device *device)
282 unsigned short *data;
284 case MODEM_SLAVE_RTS:
285 device->op->read(device->recv_buffer.buffer[1].addr,8);
286 data = (unsigned short *)device->recv_buffer.buffer[1].addr;
287 device->status = (int)MBUS_DL_ACK;
289 case MODEM_TRANSFER_REQ:
290 device->out_transfer_pending = 1;
293 modem_intf_set_mode(msg->parameter2, 1);
294 device->status = (int)MBUS_DL_IDLE;
295 device->out_transfering = 0;
302 static void boot_ack(struct modem_message_node *msg,struct modem_intf_device *device)
304 int send_bffer_index=0xFF;
305 unsigned short *data;
308 case MODEM_TRANSFER_END:
309 save_to_receive_buffer(&device->recv_buffer,device->recv_buffer.buffer[1].addr,ACK_PACKET_SIZE);
310 if(device->out_transfer_pending){
311 device->out_transfer_pending = 0;
312 device->out_transfering = send_bffer_index = pingpang_buffer_send(&device->send_buffer);
313 if(device->out_transfering!=0xff){
314 device->status = (int)MBUS_DL_WAIT_RTS;
318 device->status = (int)MBUS_DL_IDLE;
320 case MODEM_TRANSFER_REQ:
321 device->out_transfer_pending = 1;
323 case MODEM_SLAVE_RTS:
324 data = (unsigned short *)device->recv_buffer.buffer[1].addr;
325 save_to_receive_buffer(&device->recv_buffer,data,ACK_PACKET_SIZE);
326 if(device->out_transfer_pending){
327 device->out_transfer_pending = 0;
328 device->out_transfering = send_bffer_index = pingpang_buffer_send(&device->send_buffer);
330 data = (unsigned short *)device->send_buffer.buffer[send_bffer_index].addr;
331 device->op->write((char *)data,SETUP_PACKET_SIZE);
333 device->status = (int)MBUS_DL_SETUP;
335 device->status = (int)MBUS_DL_WAIT_REQ;
339 modem_intf_set_mode(msg->parameter2, 1);
340 device->status = (int)MBUS_DL_IDLE;
341 device->out_transfering = 0;
348 extern unsigned long sprd_get_system_tick(void);
349 extern void dloader_record_timestamp(unsigned long time);
351 void boot_protocol_process_dl_messages(struct modem_intf_device *device,
352 struct modem_message_node *msg)
356 status =(DL_STATUS_E) device->status;
360 boot_idle(msg,device);
363 boot_setup(msg,device);
365 case MBUS_DL_WAIT_REQ:
366 boot_wait_request(msg,device);
368 case MBUS_DL_WAIT_RTS:
369 boot_wait_RTS(msg,device);
371 case MBUS_DL_SETUP_COMP:
372 boot_setup_comp(msg,device);
375 boot_data(msg,device);
377 case MBUS_DL_DATA_COMP:
378 boot_data_comp(msg,device);
381 boot_ack(msg,device);
386 void boot_protocol(struct modem_message_node *msg)
388 struct modem_intf_device *device;
390 if((msg == NULL)||(msg->parameter1==0))
393 device = (struct modem_intf_device *)msg->parameter1;
395 printk(">>boot entry(%d,%d) status: %s message: %s \n",
396 device->out_transfer_pending,device->out_transfering,
397 boot_status_string((DL_STATUS_E )device->status),
398 modem_intf_msg_string(msg->type));
402 case MODEM_CTRL_GPIO_CHG:
403 modem_intf_ctrl_gpio_handle_boot(msg->parameter2);
406 //now, just ignore user req in boot mode
409 modem_intf_set_mode(MODEM_MODE_BOOTCOMP, 0);
413 boot_protocol_process_dl_messages(device, msg);