2 * Copyright (C) 2009 Samsung Electronics
3 * Minkyu Kang <mk7.kang@samsung.com>
4 * Sanghee Kim <sh0130.kim@samsung.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 #include "usb-hs-otg.h"
27 #include <mobile/misc.h>
30 #define RX_DATA_LEN 1024
32 /* required for DMA transfers */
33 __attribute__ ((__aligned__ (__alignof__ (long long))))
34 static char tx_data[TX_DATA_LEN];
35 __attribute__ ((__aligned__ (__alignof__ (long long))))
36 static char rx_data[RX_DATA_LEN * 2];
38 static int downloading;
41 extern int s5p_receive_done;
42 extern int s5p_usb_connected;
45 static struct usbd_ops *usbd_op;
47 static int __usb_board_init(void)
52 int usb_board_init(void) __attribute__((weak, alias("__usb_board_init")));
54 extern void s5pc_fimd_lcd_off(unsigned int win_id);
55 extern void s5pc_fimd_window_off(unsigned int win_id);
56 extern int check_exit_key(void);
58 #ifdef CONFIG_GENERIC_MMC
60 static char mmc_info[64];
62 static void usbd_set_mmc_dev(struct usbd_ops *usbd)
69 mmc = find_mmc_device(usbd->mmc_dev);
72 if (!mmc->read_bl_len) {
79 usbd->mmc_max = 0xf000;
80 usbd->mmc_blk = mmc->read_bl_len;
81 usbd->mmc_total = mmc->capacity / mmc->read_bl_len;
83 sprintf(mmc_name, "%c%c%c", mmc->cid[0] & 0xff,
84 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff);
86 if (!strncmp(mmc_name, "SEM", 3)) {
87 sprintf(mmc_info, "MMC: iNAND %d.%d%s\n",
88 (mmc->version >> 4) & 0xf,
89 (mmc->version & 0xf) == EXT_CSD_REV_1_5 ?
90 (mmc->check_rev? 3 : 41) :
91 ((mmc->version & 0xf) > EXT_CSD_REV_1_5 ?
92 (mmc->version & 0xf) - 1 :
93 (mmc->version & 0xf)),
94 mmc->check_rev? "+":"");
96 sprintf(mmc_info, "MMC: MoviNAND %d.%d%s\n",
97 (mmc->version >> 4) & 0xf,
98 (mmc->version & 0xf) == EXT_CSD_REV_1_5 ?
99 (mmc->check_rev? 3 : 41) :
100 ((mmc->version & 0xf) > EXT_CSD_REV_1_5 ?
101 (mmc->version & 0xf) - 1 :
102 (mmc->version & 0xf)),
103 mmc->check_rev? "+":"");
105 usbd->mmc_info = mmc_info;
109 /* clear download informations */
110 static void s5p_usb_clear_dnfile_info(void)
117 /* start the usb controller */
118 static int usb_init(void)
120 if (usb_board_init()) {
121 puts("Failed to usb_board_init\n");
127 printf("USB Start!! - %s Speed\n",
128 otg.speed ? "Full" : "High");
130 while (!s5p_usb_connected) {
131 if (s5p_usb_detect_irq()) {
136 if (check_exit_key())
140 s5p_usb_clear_dnfile_info();
142 puts("Connected!!\n");
144 if (!board_no_lcd_support()) {
145 fb_printf("Cable is connected\n");
152 static void usb_stop(void)
154 #ifdef CONFIG_MMC_ASYNC_WRITE
155 /* We must wait until finish the writing */
156 mmc_init(find_mmc_device(0));
161 /* it uses fb3 as default window. */
162 s5pc_fimd_lcd_off(3);
163 s5pc_fimd_window_off(3);
167 static void down_start(void)
172 static void down_cancel(int mode)
180 run_command("reset", 0);
183 run_command("usbdown", 0);
186 run_command("usbdown fail", 0);
193 static void upload_start(void)
198 static void upload_cancel(int mode)
206 run_command("reset", 0);
210 run_command("ramdump logo", 0);
211 run_command("ramdump upload", 0);
219 * receive the packet from host PC
220 * return received size
222 static int usb_receive_packet(void)
224 s5p_usb_set_dn_addr(otg.dn_addr, otg.dn_filesize);
226 if (s5p_usb_detect_irq()) {
231 if (!s5p_usb_connected) {
232 puts("Disconnected!!\n");
236 if (s5p_receive_done) {
237 s5p_receive_done = 0;
238 return otg.dn_filesize;
242 if (check_exit_key())
248 /* setup the download informations */
249 static void recv_setup(char *addr, int len)
251 s5p_usb_clear_dnfile_info();
253 otg.dn_addr = (u32)addr;
254 otg.dn_ptr = (u8 *) addr;
255 otg.dn_filesize = len;
256 #ifdef CONFIG_S5P_USB_DMA
257 if (otg.op_mode == USB_DMA) {
258 if ( len > (otg.bulkout_max_pktsize * 1023) )
259 usbd_op->prepare_dma((void *)addr, (otg.bulkout_max_pktsize * 1023), BULK_OUT_TYPE);
261 usbd_op->prepare_dma((void *)addr, len, BULK_OUT_TYPE);
267 * This function is interfaced between
268 * USB Device Controller and USB Downloader
270 struct usbd_ops *usbd_set_interface(struct usbd_ops *usbd, int mode)
274 usbd->usb_init = usb_init;
275 usbd->usb_stop = usb_stop;
276 usbd->send_data = s5p_usb_tx;
277 usbd->recv_data = usb_receive_packet;
278 usbd->recv_setup = recv_setup;
279 usbd->ram_addr = CONFIG_SYS_DOWN_ADDR;
280 usbd->cpu_reset = NULL;
282 usbd->tx_data = tx_data;
283 usbd->rx_data = rx_data;
284 usbd->tx_len = TX_DATA_LEN;
285 usbd->rx_len = RX_DATA_LEN;
286 #ifdef CONFIG_S5P_USB_DMA
287 usbd->prepare_dma = s5p_usb_setdma;
288 usbd->dma_done = s5p_usb_dma_done;
291 if (mode == MODE_UPLOAD) {
292 usbd->start = upload_start;
293 usbd->cancel = upload_cancel;
294 usbd->set_logo = NULL;
295 usbd->set_progress = NULL;
297 usbd->start = down_start;
298 usbd->cancel = down_cancel;
299 usbd->set_logo = set_download_logo;
300 usbd->set_progress = draw_progress_bar;
302 #ifdef CONFIG_GENERIC_MMC
303 usbd_set_mmc_dev(usbd);