blob: f4bafecd0d45c5eae13703abce6151eff4b417b1 [file] [log] [blame]
Lukasz Majewskib528f712013-03-05 12:10:17 +01001/*
2 * Copyright (C) 2011 Samsung Electronics
3 * Lukasz Majewski <l.majewski@samsung.com>
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Lukasz Majewskib528f712013-03-05 12:10:17 +01006 */
7
Przemyslaw Marczak351e9b22013-10-23 14:30:46 +02008#include <errno.h>
Lukasz Majewskib528f712013-03-05 12:10:17 +01009#include <common.h>
10#include <command.h>
Simon Glass24b852a2015-11-08 23:47:45 -070011#include <console.h>
Lukasz Majewskib528f712013-03-05 12:10:17 +010012#include <g_dnl.h>
Stephen Warrenabfe8af2014-05-05 10:40:15 -060013#include <part.h>
Mateusz Zalega16297cf2013-10-04 19:22:26 +020014#include <usb.h>
Lukasz Majewskib528f712013-03-05 12:10:17 +010015#include <usb_mass_storage.h>
16
Stephen Warrenabfe8af2014-05-05 10:40:15 -060017static int ums_read_sector(struct ums *ums_dev,
18 ulong start, lbaint_t blkcnt, void *buf)
19{
20 block_dev_desc_t *block_dev = ums_dev->block_dev;
21 lbaint_t blkstart = start + ums_dev->start_sector;
Stephen Warrenabfe8af2014-05-05 10:40:15 -060022
Stephen Warren7c4213f2015-12-07 11:38:48 -070023 return block_dev->block_read(block_dev, blkstart, blkcnt, buf);
Stephen Warrenabfe8af2014-05-05 10:40:15 -060024}
25
26static int ums_write_sector(struct ums *ums_dev,
27 ulong start, lbaint_t blkcnt, const void *buf)
28{
29 block_dev_desc_t *block_dev = ums_dev->block_dev;
30 lbaint_t blkstart = start + ums_dev->start_sector;
Stephen Warrenabfe8af2014-05-05 10:40:15 -060031
Stephen Warren7c4213f2015-12-07 11:38:48 -070032 return block_dev->block_write(block_dev, blkstart, blkcnt, buf);
Stephen Warrenabfe8af2014-05-05 10:40:15 -060033}
34
35static struct ums ums_dev = {
36 .read_sector = ums_read_sector,
37 .write_sector = ums_write_sector,
38 .name = "UMS disk",
39};
40
Stephen Warrend0cc4562014-05-05 10:40:16 -060041struct ums *ums_init(const char *devtype, const char *devnum)
Stephen Warrenabfe8af2014-05-05 10:40:15 -060042{
Stephen Warrend0cc4562014-05-05 10:40:16 -060043 block_dev_desc_t *block_dev;
44 int ret;
Stephen Warrenabfe8af2014-05-05 10:40:15 -060045
Stephen Warrend0cc4562014-05-05 10:40:16 -060046 ret = get_device(devtype, devnum, &block_dev);
47 if (ret < 0)
Stephen Warrenabfe8af2014-05-05 10:40:15 -060048 return NULL;
49
Stephen Warrend0cc4562014-05-05 10:40:16 -060050 /* f_mass_storage.c assumes SECTOR_SIZE sectors */
51 if (block_dev->blksz != SECTOR_SIZE)
52 return NULL;
53
54 ums_dev.block_dev = block_dev;
Stephen Warrenabfe8af2014-05-05 10:40:15 -060055 ums_dev.start_sector = 0;
Stephen Warrend0cc4562014-05-05 10:40:16 -060056 ums_dev.num_sectors = block_dev->lba;
Stephen Warrenabfe8af2014-05-05 10:40:15 -060057
58 printf("UMS: disk start sector: %#x, count: %#x\n",
59 ums_dev.start_sector, ums_dev.num_sectors);
60
61 return &ums_dev;
62}
63
Lukasz Majewskib528f712013-03-05 12:10:17 +010064int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
65 int argc, char * const argv[])
66{
Stephen Warren1725f122014-05-05 10:40:17 -060067 const char *usb_controller;
68 const char *devtype;
69 const char *devnum;
70 struct ums *ums;
71 unsigned int controller_index;
72 int rc;
73 int cable_ready_timeout __maybe_unused;
74
Mateusz Zalega16297cf2013-10-04 19:22:26 +020075 if (argc < 3)
76 return CMD_RET_USAGE;
Lukasz Majewskib528f712013-03-05 12:10:17 +010077
Stephen Warren1725f122014-05-05 10:40:17 -060078 usb_controller = argv[1];
Stephen Warren8c600452014-05-05 10:40:18 -060079 if (argc >= 4) {
80 devtype = argv[2];
81 devnum = argv[3];
82 } else {
83 devtype = "mmc";
84 devnum = argv[2];
85 }
Lukasz Majewskib528f712013-03-05 12:10:17 +010086
Stephen Warren1725f122014-05-05 10:40:17 -060087 ums = ums_init(devtype, devnum);
Przemyslaw Marczakf4dacf72013-10-23 14:30:43 +020088 if (!ums)
89 return CMD_RET_FAILURE;
Lukasz Majewskib528f712013-03-05 12:10:17 +010090
Stephen Warren1725f122014-05-05 10:40:17 -060091 controller_index = (unsigned int)(simple_strtoul(
92 usb_controller, NULL, 0));
Mateusz Zalega16297cf2013-10-04 19:22:26 +020093 if (board_usb_init(controller_index, USB_INIT_DEVICE)) {
94 error("Couldn't init USB controller.");
Przemyslaw Marczak93c813b2013-10-23 14:30:42 +020095 return CMD_RET_FAILURE;
Mateusz Zalega16297cf2013-10-04 19:22:26 +020096 }
Lukasz Majewskib528f712013-03-05 12:10:17 +010097
Stephen Warren1725f122014-05-05 10:40:17 -060098 rc = fsg_init(ums);
Mateusz Zalega16297cf2013-10-04 19:22:26 +020099 if (rc) {
100 error("fsg_init failed");
Przemyslaw Marczak93c813b2013-10-23 14:30:42 +0200101 return CMD_RET_FAILURE;
Mateusz Zalega16297cf2013-10-04 19:22:26 +0200102 }
103
Stephen Warren66b88b02014-05-01 15:42:10 -0600104 rc = g_dnl_register("usb_dnl_ums");
105 if (rc) {
106 error("g_dnl_register failed");
107 return CMD_RET_FAILURE;
108 }
Lukasz Majewskib528f712013-03-05 12:10:17 +0100109
Przemyslaw Marczak3603e312014-01-07 15:08:37 +0100110 /* Timeout unit: seconds */
Stephen Warren1725f122014-05-05 10:40:17 -0600111 cable_ready_timeout = UMS_CABLE_READY_TIMEOUT;
Przemyslaw Marczak3603e312014-01-07 15:08:37 +0100112
Mateusz Zalega75504e92014-04-30 13:07:48 +0200113 if (!g_dnl_board_usb_cable_connected()) {
114 /*
115 * Won't execute if we don't know whether the cable is
116 * connected.
117 */
Przemyslaw Marczak3603e312014-01-07 15:08:37 +0100118 puts("Please connect USB cable.\n");
119
Mateusz Zalega75504e92014-04-30 13:07:48 +0200120 while (!g_dnl_board_usb_cable_connected()) {
Przemyslaw Marczak3603e312014-01-07 15:08:37 +0100121 if (ctrlc()) {
122 puts("\rCTRL+C - Operation aborted.\n");
123 goto exit;
124 }
125 if (!cable_ready_timeout) {
126 puts("\rUSB cable not detected.\n" \
127 "Command exit.\n");
128 goto exit;
129 }
130
131 printf("\rAuto exit in: %.2d s.", cable_ready_timeout);
132 mdelay(1000);
133 cable_ready_timeout--;
134 }
135 puts("\r\n");
136 }
137
Lukasz Majewskib528f712013-03-05 12:10:17 +0100138 while (1) {
Kishon Vijay Abraham I2d48aa62015-02-23 18:40:23 +0530139 usb_gadget_handle_interrupts(controller_index);
Przemyslaw Marczak351e9b22013-10-23 14:30:46 +0200140
141 rc = fsg_main_thread(NULL);
142 if (rc) {
143 /* Check I/O error */
144 if (rc == -EIO)
145 printf("\rCheck USB cable connection\n");
146
147 /* Check CTRL+C */
148 if (rc == -EPIPE)
149 printf("\rCTRL+C - Operation aborted\n");
150
Lukasz Majewskib528f712013-03-05 12:10:17 +0100151 goto exit;
152 }
Lukasz Majewskib528f712013-03-05 12:10:17 +0100153 }
154exit:
155 g_dnl_unregister();
Inha Song375f2d72015-03-03 17:32:05 +0100156 board_usb_cleanup(controller_index, USB_INIT_DEVICE);
Przemyslaw Marczak93c813b2013-10-23 14:30:42 +0200157 return CMD_RET_SUCCESS;
Lukasz Majewskib528f712013-03-05 12:10:17 +0100158}
159
Stephen Warren8c600452014-05-05 10:40:18 -0600160U_BOOT_CMD(ums, 4, 1, do_usb_mass_storage,
Fabio Estevamee02a652015-02-28 15:11:46 -0300161 "Use the UMS [USB Mass Storage]",
Fabio Estevame5d3e7f2015-02-25 13:03:19 -0300162 "<USB_controller> [<devtype>] <devnum> e.g. ums 0 mmc 0\n"
Stephen Warren8c600452014-05-05 10:40:18 -0600163 " devtype defaults to mmc"
Lukasz Majewskib528f712013-03-05 12:10:17 +0100164);