8688b25a5cc80eb7488b36ba1d74ff53600c80a7
[kernel/u-boot.git] / cpu / arm_cortexa8 / s5pc1xx / usb_downloader.c
1 /*
2  * Copyright (C) 2009 Samsung Electronics
3  * Minkyu Kang <mk7.kang@samsung.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA
19  *
20  */
21
22 #include <common.h>
23 #include "usbd.h"
24 #include "usb-hs-otg.h"
25 #ifdef CONFIG_S5PC1XXFB
26 #include <fbutils.h>
27 #endif
28
29 static char tx_data[8] = "MPL";
30 static long tx_len = 4;
31
32 static char rx_data[64];
33 static long rx_len = 64;
34
35 extern int s5p_receive_done;
36 extern int s5p_usb_connected;
37 extern otg_dev_t otg;
38
39 static int __usb_board_init(void)
40 {
41         return 0;
42 }
43
44 int usb_board_init(void) __attribute__((weak, alias("__usb_board_init")));
45
46 extern int s5p_no_lcd_support(void);
47 extern void s5pc_fimd_lcd_off(unsigned int win_id);
48 extern void s5pc_fimd_window_off(unsigned int win_id);
49
50 /* clear download informations */
51 static void s5p_usb_clear_dnfile_info(void)
52 {
53         otg.dn_addr = 0;
54         otg.dn_filesize = 0;
55         otg.dn_ptr = 0;
56 }
57
58 /* start the usb controller */
59 static void usb_init(void)
60 {
61         if (usb_board_init()) {
62                 printf("Failed to usb_board_init\n");
63                 return;
64         }
65
66 #ifdef CONFIG_S5PC1XXFB
67         if (!s5p_no_lcd_support()) {
68                 init_font();
69                 set_font_color(FONT_WHITE);
70                 fb_printf("Ready to USB Connection\n");
71         }
72 #endif
73
74         s5p_usbctl_init();
75         s5p_usbc_activate();
76
77         printf("USB Start!! - %s Speed\n",
78                         otg.speed ? "Full" : "High");
79
80         while (!s5p_usb_connected) {
81                 if (s5p_usb_detect_irq()) {
82                         s5p_udc_int_hndlr();
83                         s5p_usb_clear_irq();
84                 }
85         }
86
87         s5p_usb_clear_dnfile_info();
88
89         printf("Connected!!\n");
90
91 #ifdef CONFIG_S5PC1XXFB
92         if (!s5p_no_lcd_support()) {
93                 fb_printf("Download Start\n");
94                 draw_progress(40, 0, FONT_WHITE);
95         }
96 #endif
97 }
98
99 static void usb_stop(void)
100 {
101         s5p_usb_stop();
102 #ifdef CONFIG_S5PC1XXFB
103         if (!s5p_no_lcd_support()) {
104                 exit_font();
105
106                 /* it uses fb3 as default window. */
107                 s5pc_fimd_lcd_off(3);
108                 s5pc_fimd_window_off(3);
109         }
110 #endif
111 }
112
113 /*
114  * receive the packet from host PC
115  * return received size
116  */
117 static int usb_receive_packet(void)
118 {
119         while (1) {
120                 if (s5p_usb_detect_irq()) {
121                         s5p_udc_int_hndlr();
122                         s5p_usb_clear_irq();
123                 }
124
125                 if (s5p_receive_done) {
126                         s5p_receive_done = 0;
127                         return otg.dn_filesize;
128                 }
129         }
130 }
131
132 /* setup the download informations */
133 static void recv_setup(char *addr, int len)
134 {
135         s5p_usb_clear_dnfile_info();
136
137         otg.dn_addr = (u32)addr;
138         otg.dn_ptr = (u8 *) addr;
139         otg.dn_filesize = len;
140 }
141
142 #ifdef CONFIG_GENERIC_MMC
143 #include <mmc.h>
144 extern int s5p_no_mmc_support(void);
145
146 static void usbd_set_mmc_dev(struct usbd_ops *usbd)
147 {
148         struct mmc *mmc;
149
150         if (s5p_no_mmc_support())
151                 return;
152
153         usbd->mmc_dev = 0;
154         /* FIXME */
155         usbd->mmc_max = 0x8000;
156
157         mmc = find_mmc_device(usbd->mmc_dev);
158         mmc_init(mmc);
159
160         usbd->mmc_blk = mmc->read_bl_len;
161
162         if (mmc->high_capacity)
163                 usbd->mmc_total = mmc->capacity;
164         else
165                 usbd->mmc_total = mmc->capacity / mmc->read_bl_len;
166 }
167 #endif
168
169 #ifdef CONFIG_S5PC1XXFB
170 static void set_progress(int progress)
171 {
172         draw_progress(40, progress, FONT_WHITE);
173 }
174 #endif
175 /*
176  * This function is interfaced between
177  * USB Device Controller and USB Downloader
178  */
179 struct usbd_ops *usbd_set_interface(struct usbd_ops *usbd)
180 {
181         usbd->usb_init = usb_init;
182         usbd->usb_stop = usb_stop;
183         usbd->send_data = s5p_usb_tx;
184         usbd->recv_data = usb_receive_packet;
185         usbd->recv_setup = recv_setup;
186         usbd->tx_data = tx_data;
187         usbd->rx_data = rx_data;
188         usbd->tx_len = tx_len;
189         usbd->rx_len = rx_len;
190         usbd->ram_addr = CONFIG_SYS_DOWN_ADDR;
191 #ifdef CONFIG_S5PC1XXFB
192         if (!s5p_no_lcd_support())
193                 usbd->set_progress = set_progress;
194 #endif
195 #ifdef CONFIG_GENERIC_MMC
196         usbd_set_mmc_dev(usbd);
197 #endif
198
199         return usbd;
200 }