s5pc110: universal: fix typo
[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[2048];
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
48 /* clear download informations */
49 static void s5p_usb_clear_dnfile_info(void)
50 {
51         otg.dn_addr = 0;
52         otg.dn_filesize = 0;
53         otg.dn_ptr = 0;
54 }
55
56 /* clear upload informations */
57 static void s5p_usb_clear_upfile_info(void)
58 {
59         otg.up_addr = 0;
60         otg.up_size = 0;
61         otg.up_ptr = 0;
62 }
63
64 /* start the usb controller */
65 static void usb_init(void)
66 {
67         if (usb_board_init()) {
68                 printf("Failed to usb_board_init\n");
69                 return;
70         }
71
72 #ifdef CONFIG_S5PC1XXFB
73         if (!s5p_no_lcd_support()) {
74                 init_font();
75                 set_font_color(FONT_WHITE);
76                 fb_printf("Ready to USB Connection\n");
77         }
78 #endif
79
80         s5p_usbctl_init();
81         s5p_usbc_activate();
82
83         printf("USB Start!! - %s Speed\n",
84                         otg.speed ? "Full" : "High");
85
86         while (!s5p_usb_connected) {
87                 if (s5p_usb_detect_irq()) {
88                         s5p_udc_int_hndlr();
89                         s5p_usb_clear_irq();
90                 }
91         }
92
93         s5p_usb_clear_dnfile_info();
94
95         printf("Connected!!\n");
96
97 #ifdef CONFIG_S5PC1XXFB
98         if (!s5p_no_lcd_support()) {
99                 fb_printf("Download Start\n");
100                 draw_progress(40, 0, FONT_WHITE);
101         }
102 #endif
103 }
104
105 static void usb_stop(void)
106 {
107         s5p_usb_stop();
108 #ifdef CONFIG_S5PC1XXFB
109         if (!s5p_no_lcd_support()) {
110                 exit_font();
111
112                 /* it uses fb3 as default window. */
113                 s5pc_fimd_lcd_off(3);
114                 s5pc_fimd_window_off(3);
115         }
116 #endif
117 }
118
119 /*
120  * receive the packet from host PC
121  * return received size
122  */
123 static int usb_receive_packet(void)
124 {
125         while (1) {
126                 if (s5p_usb_detect_irq()) {
127                         s5p_udc_int_hndlr();
128                         s5p_usb_clear_irq();
129                 }
130
131                 if (s5p_receive_done) {
132                         s5p_receive_done = 0;
133                         return otg.dn_filesize;
134                 }
135         }
136 }
137
138 /* setup the download informations */
139 static void recv_setup(char *addr, int len)
140 {
141         s5p_usb_clear_dnfile_info();
142
143         otg.dn_addr = (u32)addr;
144         otg.dn_ptr = (u8 *) addr;
145         otg.dn_filesize = len;
146 }
147
148 #ifdef CONFIG_GENERIC_MMC
149 #include <mmc.h>
150 extern int s5p_no_mmc_support(void);
151
152 static void usbd_set_mmc_dev(struct usbd_ops *usbd)
153 {
154         struct mmc *mmc;
155
156         if (s5p_no_mmc_support())
157                 return;
158
159         usbd->mmc_dev = 0;
160         /* FIXME */
161         usbd->mmc_max = 0x8000;
162
163         mmc = find_mmc_device(usbd->mmc_dev);
164         mmc_init(mmc);
165
166         usbd->mmc_blk = mmc->read_bl_len;
167
168         if (mmc->high_capacity)
169                 usbd->mmc_total = mmc->capacity;
170         else
171                 usbd->mmc_total = mmc->capacity / mmc->read_bl_len;
172 }
173 #endif
174
175 #ifdef CONFIG_S5PC1XXFB
176 static void set_progress(int progress)
177 {
178         draw_progress(40, progress, FONT_WHITE);
179 }
180 #endif
181 /*
182  * This function is interfaced between
183  * USB Device Controller and USB Downloader
184  */
185 struct usbd_ops *usbd_set_interface(struct usbd_ops *usbd)
186 {
187         usbd->usb_init = usb_init;
188         usbd->usb_stop = usb_stop;
189         usbd->send_data = s5p_usb_tx;
190         usbd->recv_data = usb_receive_packet;
191         usbd->recv_setup = recv_setup;
192         usbd->tx_data = tx_data;
193         usbd->rx_data = rx_data;
194         usbd->tx_len = tx_len;
195         usbd->rx_len = rx_len;
196         usbd->ram_addr = CONFIG_SYS_DOWN_ADDR;
197 #ifdef CONFIG_S5PC1XXFB
198         if (!s5p_no_lcd_support())
199                 usbd->set_progress = set_progress;
200 #endif
201 #ifdef CONFIG_GENERIC_MMC
202         usbd_set_mmc_dev(usbd);
203 #endif
204
205         return usbd;
206 }