14bb7efa7SGarrett D'Amore /* 24bb7efa7SGarrett D'Amore * CDDL HEADER START 34bb7efa7SGarrett D'Amore * 44bb7efa7SGarrett D'Amore * The contents of this file are subject to the terms of the 54bb7efa7SGarrett D'Amore * Common Development and Distribution License (the "License"). 64bb7efa7SGarrett D'Amore * You may not use this file except in compliance with the License. 74bb7efa7SGarrett D'Amore * 84bb7efa7SGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94bb7efa7SGarrett D'Amore * or http://www.opensolaris.org/os/licensing. 104bb7efa7SGarrett D'Amore * See the License for the specific language governing permissions 114bb7efa7SGarrett D'Amore * and limitations under the License. 124bb7efa7SGarrett D'Amore * 134bb7efa7SGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each 144bb7efa7SGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154bb7efa7SGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the 164bb7efa7SGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying 174bb7efa7SGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner] 184bb7efa7SGarrett D'Amore * 194bb7efa7SGarrett D'Amore * CDDL HEADER END 204bb7efa7SGarrett D'Amore */ 214bb7efa7SGarrett D'Amore /* 224bb7efa7SGarrett D'Amore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 234bb7efa7SGarrett D'Amore * Use is subject to license terms. 244bb7efa7SGarrett D'Amore */ 254bb7efa7SGarrett D'Amore 264bb7efa7SGarrett D'Amore /* 274bb7efa7SGarrett D'Amore * SD card host support. This is the API that host drivers access. 284bb7efa7SGarrett D'Amore */ 294bb7efa7SGarrett D'Amore 304bb7efa7SGarrett D'Amore #include <sys/types.h> 314bb7efa7SGarrett D'Amore #include <sys/conf.h> 324bb7efa7SGarrett D'Amore #include <sys/cmn_err.h> 334bb7efa7SGarrett D'Amore #include <sys/varargs.h> 344bb7efa7SGarrett D'Amore #include <sys/ddi.h> 354bb7efa7SGarrett D'Amore #include <sys/sunddi.h> 364bb7efa7SGarrett D'Amore #include <sys/sdcard/sda.h> 374bb7efa7SGarrett D'Amore #include <sys/sdcard/sda_impl.h> 384bb7efa7SGarrett D'Amore 394bb7efa7SGarrett D'Amore /* 404bb7efa7SGarrett D'Amore * Static Variables. 414bb7efa7SGarrett D'Amore */ 424bb7efa7SGarrett D'Amore 434bb7efa7SGarrett D'Amore static struct bus_ops sda_host_bus_ops = { 444bb7efa7SGarrett D'Amore BUSO_REV, /* busops_rev */ 454bb7efa7SGarrett D'Amore nullbusmap, /* bus_map */ 464bb7efa7SGarrett D'Amore NULL, /* bus_get_intrspec (OBSOLETE) */ 474bb7efa7SGarrett D'Amore NULL, /* bus_add_intrspec (OBSOLETE) */ 484bb7efa7SGarrett D'Amore NULL, /* bus_remove_intrspec (OBSOLETE) */ 494bb7efa7SGarrett D'Amore i_ddi_map_fault, /* bus_map_fault */ 504bb7efa7SGarrett D'Amore ddi_dma_map, /* bus_dma_map */ 514bb7efa7SGarrett D'Amore ddi_dma_allochdl, /* bus_dma_allochdl */ 524bb7efa7SGarrett D'Amore ddi_dma_freehdl, /* bus_dma_freehdl */ 534bb7efa7SGarrett D'Amore ddi_dma_bindhdl, /* bus_dma_bindhdl */ 544bb7efa7SGarrett D'Amore ddi_dma_unbindhdl, /* bus_dma_unbindhdl */ 554bb7efa7SGarrett D'Amore ddi_dma_flush, /* bus_dma_flush */ 564bb7efa7SGarrett D'Amore ddi_dma_win, /* bus_dma_win */ 574bb7efa7SGarrett D'Amore ddi_dma_mctl, /* bus_dma_ctl */ 584bb7efa7SGarrett D'Amore sda_nexus_bus_ctl, /* bus_ctl */ 594bb7efa7SGarrett D'Amore ddi_bus_prop_op, /* bus_prop_op */ 604bb7efa7SGarrett D'Amore NULL, /* bus_get_eventcookie */ 614bb7efa7SGarrett D'Amore NULL, /* bus_add_eventcall */ 624bb7efa7SGarrett D'Amore NULL, /* bus_remove_eventcall */ 634bb7efa7SGarrett D'Amore NULL, /* bus_post_event */ 644bb7efa7SGarrett D'Amore NULL, /* bus_intr_ctl (OBSOLETE) */ 654bb7efa7SGarrett D'Amore NULL, /* sda_nexus_bus_config, */ /* bus_config */ 664bb7efa7SGarrett D'Amore NULL, /* sda_nexus_bus_unconfig, */ /* bus_unconfig */ 674bb7efa7SGarrett D'Amore NULL, /* bus_fm_init */ 684bb7efa7SGarrett D'Amore NULL, /* bus_fm_fini */ 694bb7efa7SGarrett D'Amore NULL, /* bus_fm_access_enter */ 704bb7efa7SGarrett D'Amore NULL, /* bus_fm_access_exit */ 714bb7efa7SGarrett D'Amore NULL, /* bus_power */ 724bb7efa7SGarrett D'Amore NULL, /* bus_intr_op */ 734bb7efa7SGarrett D'Amore }; 744bb7efa7SGarrett D'Amore 754bb7efa7SGarrett D'Amore static struct cb_ops sda_host_cb_ops = { 764bb7efa7SGarrett D'Amore sda_nexus_open, /* cb_open */ 774bb7efa7SGarrett D'Amore sda_nexus_close, /* cb_close */ 784bb7efa7SGarrett D'Amore nodev, /* cb_strategy */ 794bb7efa7SGarrett D'Amore nodev, /* cb_print */ 804bb7efa7SGarrett D'Amore nodev, /* cb_dump */ 814bb7efa7SGarrett D'Amore nodev, /* cb_read */ 824bb7efa7SGarrett D'Amore nodev, /* cb_write */ 834bb7efa7SGarrett D'Amore sda_nexus_ioctl, /* cb_ioctl */ 844bb7efa7SGarrett D'Amore nodev, /* cb_devmap */ 854bb7efa7SGarrett D'Amore nodev, /* cb_mmap */ 864bb7efa7SGarrett D'Amore nodev, /* cb_segmap */ 874bb7efa7SGarrett D'Amore nochpoll, /* cb_poll */ 884bb7efa7SGarrett D'Amore ddi_prop_op, /* cb_prop_op */ 894bb7efa7SGarrett D'Amore NULL, /* cb_str */ 904bb7efa7SGarrett D'Amore D_MP, /* cb_flag */ 914bb7efa7SGarrett D'Amore CB_REV, /* cb_rev */ 924bb7efa7SGarrett D'Amore nodev, /* cb_aread */ 934bb7efa7SGarrett D'Amore nodev, /* cb_awrite */ 944bb7efa7SGarrett D'Amore }; 954bb7efa7SGarrett D'Amore 964bb7efa7SGarrett D'Amore /* 974bb7efa7SGarrett D'Amore * Implementation. 984bb7efa7SGarrett D'Amore */ 994bb7efa7SGarrett D'Amore 1004bb7efa7SGarrett D'Amore void 1014bb7efa7SGarrett D'Amore sda_host_init_ops(struct dev_ops *devops) 1024bb7efa7SGarrett D'Amore { 1034bb7efa7SGarrett D'Amore devops->devo_getinfo = sda_nexus_getinfo; 1044bb7efa7SGarrett D'Amore devops->devo_cb_ops = &sda_host_cb_ops; 1054bb7efa7SGarrett D'Amore devops->devo_bus_ops = &sda_host_bus_ops; 1064bb7efa7SGarrett D'Amore } 1074bb7efa7SGarrett D'Amore 1084bb7efa7SGarrett D'Amore void 1094bb7efa7SGarrett D'Amore sda_host_fini_ops(struct dev_ops *devops) 1104bb7efa7SGarrett D'Amore { 1114bb7efa7SGarrett D'Amore devops->devo_bus_ops = NULL; 1124bb7efa7SGarrett D'Amore } 1134bb7efa7SGarrett D'Amore 1144bb7efa7SGarrett D'Amore sda_host_t * 1154bb7efa7SGarrett D'Amore sda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma) 1164bb7efa7SGarrett D'Amore { 1174bb7efa7SGarrett D'Amore sda_host_t *h; 1184bb7efa7SGarrett D'Amore 1194bb7efa7SGarrett D'Amore if (ops->so_version != SDA_OPS_VERSION) { 1204bb7efa7SGarrett D'Amore return (NULL); 1214bb7efa7SGarrett D'Amore } 1224bb7efa7SGarrett D'Amore 1234bb7efa7SGarrett D'Amore h = kmem_zalloc(sizeof (*h), KM_SLEEP); 1244bb7efa7SGarrett D'Amore h->h_nslot = nslot; 1254bb7efa7SGarrett D'Amore h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP); 1264bb7efa7SGarrett D'Amore h->h_dma = dma; 1274bb7efa7SGarrett D'Amore h->h_dip = dip; 1284bb7efa7SGarrett D'Amore 1294bb7efa7SGarrett D'Amore /* initialize each slot */ 130*f2b90c3cSGarrett D'Amore for (int i = 0; i < nslot; i++) { 1314bb7efa7SGarrett D'Amore sda_slot_t *slot = &h->h_slots[i]; 1324bb7efa7SGarrett D'Amore 1331cb84fbfSGarrett D'Amore slot->s_hostp = h; 1344bb7efa7SGarrett D'Amore slot->s_slot_num = i; 1354bb7efa7SGarrett D'Amore slot->s_ops = *ops; 1364bb7efa7SGarrett D'Amore 1374bb7efa7SGarrett D'Amore sda_slot_init(slot); 1384bb7efa7SGarrett D'Amore } 1394bb7efa7SGarrett D'Amore 1404bb7efa7SGarrett D'Amore return (h); 1414bb7efa7SGarrett D'Amore } 1424bb7efa7SGarrett D'Amore 1434bb7efa7SGarrett D'Amore void 1444bb7efa7SGarrett D'Amore sda_host_free(sda_host_t *h) 1454bb7efa7SGarrett D'Amore { 146*f2b90c3cSGarrett D'Amore for (int i = 0; i < h->h_nslot; i++) { 1474bb7efa7SGarrett D'Amore sda_slot_fini(&h->h_slots[i]); 1484bb7efa7SGarrett D'Amore } 1494bb7efa7SGarrett D'Amore 1504bb7efa7SGarrett D'Amore kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot); 1514bb7efa7SGarrett D'Amore kmem_free(h, sizeof (*h)); 1524bb7efa7SGarrett D'Amore } 1534bb7efa7SGarrett D'Amore 1544bb7efa7SGarrett D'Amore void 1554bb7efa7SGarrett D'Amore sda_host_set_private(sda_host_t *h, int num, void *private) 1564bb7efa7SGarrett D'Amore { 1574bb7efa7SGarrett D'Amore h->h_slots[num].s_prv = private; 1584bb7efa7SGarrett D'Amore } 1594bb7efa7SGarrett D'Amore 1604bb7efa7SGarrett D'Amore int 1614bb7efa7SGarrett D'Amore sda_host_attach(sda_host_t *h) 1624bb7efa7SGarrett D'Amore { 1634bb7efa7SGarrett D'Amore /* 1644bb7efa7SGarrett D'Amore * Attach slots. 1654bb7efa7SGarrett D'Amore */ 166*f2b90c3cSGarrett D'Amore for (int i = 0; i < h->h_nslot; i++) { 1674bb7efa7SGarrett D'Amore 1684bb7efa7SGarrett D'Amore sda_slot_attach(&h->h_slots[i]); 1694bb7efa7SGarrett D'Amore 1704bb7efa7SGarrett D'Amore /* 1714bb7efa7SGarrett D'Amore * Initiate card detection. 1724bb7efa7SGarrett D'Amore */ 1734bb7efa7SGarrett D'Amore sda_host_detect(h, i); 1744bb7efa7SGarrett D'Amore } 1754bb7efa7SGarrett D'Amore 1764bb7efa7SGarrett D'Amore /* 1774bb7efa7SGarrett D'Amore * Register (create) nexus minor nodes. 1784bb7efa7SGarrett D'Amore */ 1794bb7efa7SGarrett D'Amore sda_nexus_register(h); 1804bb7efa7SGarrett D'Amore 1814bb7efa7SGarrett D'Amore return (DDI_SUCCESS); 1824bb7efa7SGarrett D'Amore } 1834bb7efa7SGarrett D'Amore 1844bb7efa7SGarrett D'Amore void 1854bb7efa7SGarrett D'Amore sda_host_detach(sda_host_t *h) 1864bb7efa7SGarrett D'Amore { 1874bb7efa7SGarrett D'Amore /* 1884bb7efa7SGarrett D'Amore * Unregister nexus minor nodes. 1894bb7efa7SGarrett D'Amore */ 1904bb7efa7SGarrett D'Amore sda_nexus_unregister(h); 1914bb7efa7SGarrett D'Amore 1924bb7efa7SGarrett D'Amore /* 1934bb7efa7SGarrett D'Amore * Detach slots. 1944bb7efa7SGarrett D'Amore */ 195*f2b90c3cSGarrett D'Amore for (int i = 0; i < h->h_nslot; i++) { 1964bb7efa7SGarrett D'Amore sda_slot_detach(&h->h_slots[i]); 1974bb7efa7SGarrett D'Amore } 1984bb7efa7SGarrett D'Amore } 1994bb7efa7SGarrett D'Amore 2004bb7efa7SGarrett D'Amore void 201*f2b90c3cSGarrett D'Amore sda_host_suspend(sda_host_t *h) 202*f2b90c3cSGarrett D'Amore { 203*f2b90c3cSGarrett D'Amore for (int i = 0; i < h->h_nslot; i++) { 204*f2b90c3cSGarrett D'Amore sda_slot_suspend(&h->h_slots[i]); 205*f2b90c3cSGarrett D'Amore } 206*f2b90c3cSGarrett D'Amore } 207*f2b90c3cSGarrett D'Amore 208*f2b90c3cSGarrett D'Amore void 209*f2b90c3cSGarrett D'Amore sda_host_resume(sda_host_t *h) 210*f2b90c3cSGarrett D'Amore { 211*f2b90c3cSGarrett D'Amore for (int i = 0; i < h->h_nslot; i++) { 212*f2b90c3cSGarrett D'Amore sda_slot_resume(&h->h_slots[i]); 213*f2b90c3cSGarrett D'Amore } 214*f2b90c3cSGarrett D'Amore } 215*f2b90c3cSGarrett D'Amore 216*f2b90c3cSGarrett D'Amore void 2174bb7efa7SGarrett D'Amore sda_host_transfer(sda_host_t *h, int num, sda_err_t errno) 2184bb7efa7SGarrett D'Amore { 2194bb7efa7SGarrett D'Amore sda_slot_transfer(&h->h_slots[num], errno); 2204bb7efa7SGarrett D'Amore } 2214bb7efa7SGarrett D'Amore 2224bb7efa7SGarrett D'Amore void 2234bb7efa7SGarrett D'Amore sda_host_detect(sda_host_t *h, int num) 2244bb7efa7SGarrett D'Amore { 2254bb7efa7SGarrett D'Amore sda_slot_detect(&h->h_slots[num]); 2264bb7efa7SGarrett D'Amore } 2274bb7efa7SGarrett D'Amore 2284bb7efa7SGarrett D'Amore void 2294bb7efa7SGarrett D'Amore sda_host_fault(sda_host_t *h, int num, sda_fault_t fail) 2304bb7efa7SGarrett D'Amore { 2314bb7efa7SGarrett D'Amore sda_slot_fault(&h->h_slots[num], fail); 2324bb7efa7SGarrett D'Amore } 2334bb7efa7SGarrett D'Amore 2344bb7efa7SGarrett D'Amore void 2354bb7efa7SGarrett D'Amore sda_host_log(sda_host_t *h, int snum, const char *fmt, ...) 2364bb7efa7SGarrett D'Amore { 2374bb7efa7SGarrett D'Amore va_list ap; 2384bb7efa7SGarrett D'Amore 2394bb7efa7SGarrett D'Amore va_start(ap, fmt); 2404bb7efa7SGarrett D'Amore if (h != NULL) { 2414bb7efa7SGarrett D'Amore sda_slot_log(&h->h_slots[snum], fmt, ap); 2424bb7efa7SGarrett D'Amore } else { 2434bb7efa7SGarrett D'Amore sda_slot_log(NULL, fmt, ap); 2444bb7efa7SGarrett D'Amore } 2454bb7efa7SGarrett D'Amore va_end(ap); 2464bb7efa7SGarrett D'Amore } 247