aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@nokia.com>2009-03-12 11:08:26 -0400
committerPierre Ossman <drzeus@drzeus.cx>2009-03-24 16:30:07 -0400
commite13bb3003a33df8f82cd027f8abfa5cd73f2eec0 (patch)
tree4b4b47777c8a8a4243b00131f29f0a3bcf964d6e /drivers/mmc/host
parentf3e2f1dd3bbe9352654eec8223495d35e1f52af2 (diff)
omap_hsmmc: Wait for SDBP
It is necessary to wait for bus power before sending any commands. Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 61883093e25b..488f222054f8 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -498,6 +498,19 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
498 return IRQ_HANDLED; 498 return IRQ_HANDLED;
499} 499}
500 500
501static void set_sd_bus_power(struct mmc_omap_host *host)
502{
503 unsigned long i;
504
505 OMAP_HSMMC_WRITE(host->base, HCTL,
506 OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
507 for (i = 0; i < loops_per_jiffy; i++) {
508 if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP)
509 break;
510 cpu_relax();
511 }
512}
513
501/* 514/*
502 * Switch MMC interface voltage ... only relevant for MMC1. 515 * Switch MMC interface voltage ... only relevant for MMC1.
503 * 516 *
@@ -554,9 +567,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
554 reg_val |= SDVS30; 567 reg_val |= SDVS30;
555 568
556 OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); 569 OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
557 570 set_sd_bus_power(host);
558 OMAP_HSMMC_WRITE(host->base, HCTL,
559 OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
560 571
561 return 0; 572 return 0;
562err: 573err:
@@ -942,8 +953,7 @@ static void omap_hsmmc_init(struct mmc_omap_host *host)
942 OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); 953 OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
943 954
944 /* Set SD bus power bit */ 955 /* Set SD bus power bit */
945 value = OMAP_HSMMC_READ(host->base, HCTL); 956 set_sd_bus_power(host);
946 OMAP_HSMMC_WRITE(host->base, HCTL, value | SDBP);
947} 957}
948 958
949static struct mmc_host_ops mmc_omap_ops = { 959static struct mmc_host_ops mmc_omap_ops = {
d->udev, usb_sndctrlpipe(d->udev,0), req, USB_TYPE_VENDOR | USB_DIR_OUT, value,index,b,blen, 2000) != blen) { warn("usb out operation failed."); ret = -EIO; } else ret = 0; mutex_unlock(&d->usb_mutex); return ret; } static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) { int ret; const struct firmware *fw = NULL; const u8 *ptr; u8 *buf; if ((ret = request_firmware(&fw, bcm4500_firmware, &d->udev->dev)) != 0) { err("did not find the bcm4500 firmware file. (%s) " "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", bcm4500_firmware,ret); return ret; } ret = -EINVAL; if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) goto out_rel_fw; info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware); ptr = fw->data; buf = kmalloc(64, GFP_KERNEL | GFP_DMA); while (ptr[0] != 0xff) { u16 buflen = ptr[0] + 4; if (ptr + buflen >= fw->data + fw->size) { err("failed to load bcm4500 firmware."); goto out_free; } memcpy(buf, ptr, buflen); if (dvb_usb_generic_write(d, buf, buflen)) { err("failed to load bcm4500 firmware."); goto out_free; } ptr += buflen; } ret = 0; out_free: kfree(buf); out_rel_fw: release_firmware(fw); return ret; } static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) { u8 status, buf; int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); if (onoff) { gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); if (! (status & bm8pskStarted)) { /* started */ if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0); if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) return -EINVAL; } if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */ if(gp8psk_load_bcm4500fw(d)) return -EINVAL; if (! (status & bmIntersilOn)) /* LNB Power */ if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, &buf, 1)) return -EINVAL; /* Set DVB mode to 1 */ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) return -EINVAL; /* Abort possible TS (if previous tune crashed) */ if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0)) return -EINVAL; } else { /* Turn off LNB power */ if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) return -EINVAL; /* Turn off 8psk power */ if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) return -EINVAL; if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0); } return 0; } static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0); } static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap) { adap->fe = gp8psk_fe_attach(adap->dev); return 0; } static struct dvb_usb_device_properties gp8psk_properties; static int gp8psk_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { int ret; struct usb_device *udev = interface_to_usbdev(intf); ret = dvb_usb_device_init(intf, &gp8psk_properties, THIS_MODULE, NULL, adapter_nr); if (ret == 0) { info("found Genpix USB device pID = %x (hex)", le16_to_cpu(udev->descriptor.idProduct)); } return ret; } static struct usb_device_id gp8psk_usb_table [] = { { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, { 0 }, }; MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); static struct dvb_usb_device_properties gp8psk_properties = { .usb_ctrl = CYPRESS_FX2, .firmware = "dvb-usb-gp8psk-01.fw", .num_adapters = 1, .adapter = { { .streaming_ctrl = gp8psk_streaming_ctrl, .frontend_attach = gp8psk_frontend_attach, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, .count = 7, .endpoint = 0x82, .u = { .bulk = { .buffersize = 8192, } } }, } }, .power_ctrl = gp8psk_power_ctrl, .generic_bulk_ctrl_endpoint = 0x01, .num_device_descs = 4, .devices = { { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", .cold_ids = { &gp8psk_usb_table[0], NULL }, .warm_ids = { &gp8psk_usb_table[1], NULL }, }, { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver", .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[2], NULL }, }, { .name = "Genpix SkyWalker-1 DVB-S receiver", .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[3], NULL }, }, { .name = "Genpix SkyWalker-CW3K DVB-S receiver", .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[4], NULL }, }, { NULL }, } }; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gp8psk_usb_driver = { .name = "dvb_usb_gp8psk", .probe = gp8psk_usb_probe, .disconnect = dvb_usb_device_exit, .id_table = gp8psk_usb_table, }; /* module stuff */ static int __init gp8psk_usb_module_init(void) { int result; if ((result = usb_register(&gp8psk_usb_driver))) { err("usb_register failed. (%d)",result); return result; } return 0; } static void __exit gp8psk_usb_module_exit(void) { /* deregister this driver from the USB subsystem */ usb_deregister(&gp8psk_usb_driver); } module_init(gp8psk_usb_module_init); module_exit(gp8psk_usb_module_exit); MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); MODULE_DESCRIPTION("Driver for Genpix 8psk-to-USB2 DVB-S"); MODULE_VERSION("1.1"); MODULE_LICENSE("GPL");