sdhci.c (b019f5e5375224a003f260c89d424fea7767b7fc) sdhci.c (ce864603443567b8186dc435ebba08338ef4a6d6)
1/*
2 * SD Association Host Standard Specification v2.0 controller emulation
3 *
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5 * Mitsyanko Igor <i.mitsyanko@samsung.com>
6 * Peter A.G. Crosthwaite <peter.crosthwaite@petalogix.com>
7 *
8 * Based on MMC controller for Samsung S5PC1xx-based board emulation

--- 26 unchanged lines hidden (view full) ---

35#include "qemu/log.h"
36#include "trace.h"
37
38#define TYPE_SDHCI_BUS "sdhci-bus"
39#define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS)
40
41#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
42
1/*
2 * SD Association Host Standard Specification v2.0 controller emulation
3 *
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5 * Mitsyanko Igor <i.mitsyanko@samsung.com>
6 * Peter A.G. Crosthwaite <peter.crosthwaite@petalogix.com>
7 *
8 * Based on MMC controller for Samsung S5PC1xx-based board emulation

--- 26 unchanged lines hidden (view full) ---

35#include "qemu/log.h"
36#include "trace.h"
37
38#define TYPE_SDHCI_BUS "sdhci-bus"
39#define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS)
40
41#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
42
43/* Default SD/MMC host controller features information, which will be
44 * presented in CAPABILITIES register of generic SD host controller at reset.
45 *
46 * support:
47 * - 3.3v and 1.8v voltages
48 * - SDMA/ADMA1/ADMA2
49 * - high-speed
50 * max host controller R/W buffers size: 512B
51 * max clock frequency for SDclock: 52 MHz
52 * timeout clock frequency: 52 MHz
53 *
54 * does not support:
55 * - 3.0v voltage
56 * - 64-bit system bus
57 * - suspend/resume
58 */
59#define SDHC_CAPAB_REG_DEFAULT 0x057834b4
60
61static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
62{
63 return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
64}
65
66/* return true on error */
67static bool sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
68 uint8_t freq, Error **errp)

--- 1254 unchanged lines hidden (view full) ---

1323 if (local_err) {
1324 error_propagate(errp, local_err);
1325 return;
1326 }
1327}
1328
1329/* --- qdev common --- */
1330
43static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
44{
45 return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
46}
47
48/* return true on error */
49static bool sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
50 uint8_t freq, Error **errp)

--- 1254 unchanged lines hidden (view full) ---

1305 if (local_err) {
1306 error_propagate(errp, local_err);
1307 return;
1308 }
1309}
1310
1311/* --- qdev common --- */
1312
1331#define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \
1332 DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
1333 DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \
1334 \
1335 /* Capabilities registers provide information on supported
1336 * features of this specific host controller implementation */ \
1337 DEFINE_PROP_UINT64("capareg", _state, capareg, SDHC_CAPAB_REG_DEFAULT), \
1338 DEFINE_PROP_UINT64("maxcurr", _state, maxcurr, 0)
1339
1340static void sdhci_initfn(SDHCIState *s)
1313void sdhci_initfn(SDHCIState *s)
1341{
1342 qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
1343 TYPE_SDHCI_BUS, DEVICE(s), "sd-bus");
1344
1345 s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
1346 s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
1347
1348 s->io_ops = &sdhci_mmio_ops;
1349}
1350
1314{
1315 qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
1316 TYPE_SDHCI_BUS, DEVICE(s), "sd-bus");
1317
1318 s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
1319 s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
1320
1321 s->io_ops = &sdhci_mmio_ops;
1322}
1323
1351static void sdhci_uninitfn(SDHCIState *s)
1324void sdhci_uninitfn(SDHCIState *s)
1352{
1353 timer_del(s->insert_timer);
1354 timer_free(s->insert_timer);
1355 timer_del(s->transfer_timer);
1356 timer_free(s->transfer_timer);
1357
1358 g_free(s->fifo_buffer);
1359 s->fifo_buffer = NULL;
1360}
1361
1325{
1326 timer_del(s->insert_timer);
1327 timer_free(s->insert_timer);
1328 timer_del(s->transfer_timer);
1329 timer_free(s->transfer_timer);
1330
1331 g_free(s->fifo_buffer);
1332 s->fifo_buffer = NULL;
1333}
1334
1362static void sdhci_common_realize(SDHCIState *s, Error **errp)
1335void sdhci_common_realize(SDHCIState *s, Error **errp)
1363{
1364 Error *local_err = NULL;
1365
1366 sdhci_init_readonly_registers(s, &local_err);
1367 if (local_err) {
1368 error_propagate(errp, local_err);
1369 return;
1370 }
1371 s->buf_maxsz = sdhci_get_fifolen(s);
1372 s->fifo_buffer = g_malloc0(s->buf_maxsz);
1373
1374 memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
1375 SDHC_REGISTERS_MAP_SIZE);
1376}
1377
1336{
1337 Error *local_err = NULL;
1338
1339 sdhci_init_readonly_registers(s, &local_err);
1340 if (local_err) {
1341 error_propagate(errp, local_err);
1342 return;
1343 }
1344 s->buf_maxsz = sdhci_get_fifolen(s);
1345 s->fifo_buffer = g_malloc0(s->buf_maxsz);
1346
1347 memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
1348 SDHC_REGISTERS_MAP_SIZE);
1349}
1350
1378static void sdhci_common_unrealize(SDHCIState *s, Error **errp)
1351void sdhci_common_unrealize(SDHCIState *s, Error **errp)
1379{
1380 /* This function is expected to be called only once for each class:
1381 * - SysBus: via DeviceClass->unrealize(),
1382 * - PCI: via PCIDeviceClass->exit().
1383 * However to avoid double-free and/or use-after-free we still nullify
1384 * this variable (better safe than sorry!). */
1385 g_free(s->fifo_buffer);
1386 s->fifo_buffer = NULL;

--- 53 unchanged lines hidden (view full) ---

1440 VMSTATE_END_OF_LIST()
1441 },
1442 .subsections = (const VMStateDescription*[]) {
1443 &sdhci_pending_insert_vmstate,
1444 NULL
1445 },
1446};
1447
1352{
1353 /* This function is expected to be called only once for each class:
1354 * - SysBus: via DeviceClass->unrealize(),
1355 * - PCI: via PCIDeviceClass->exit().
1356 * However to avoid double-free and/or use-after-free we still nullify
1357 * this variable (better safe than sorry!). */
1358 g_free(s->fifo_buffer);
1359 s->fifo_buffer = NULL;

--- 53 unchanged lines hidden (view full) ---

1413 VMSTATE_END_OF_LIST()
1414 },
1415 .subsections = (const VMStateDescription*[]) {
1416 &sdhci_pending_insert_vmstate,
1417 NULL
1418 },
1419};
1420
1448static void sdhci_common_class_init(ObjectClass *klass, void *data)
1421void sdhci_common_class_init(ObjectClass *klass, void *data)
1449{
1450 DeviceClass *dc = DEVICE_CLASS(klass);
1451
1452 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1453 dc->vmsd = &sdhci_vmstate;
1454 dc->reset = sdhci_poweron_reset;
1455}
1456
1422{
1423 DeviceClass *dc = DEVICE_CLASS(klass);
1424
1425 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1426 dc->vmsd = &sdhci_vmstate;
1427 dc->reset = sdhci_poweron_reset;
1428}
1429
1457/* --- qdev PCI --- */
1458
1459static Property sdhci_pci_properties[] = {
1460 DEFINE_SDHCI_COMMON_PROPERTIES(SDHCIState),
1461 DEFINE_PROP_END_OF_LIST(),
1462};
1463
1464static void sdhci_pci_realize(PCIDevice *dev, Error **errp)
1465{
1466 SDHCIState *s = PCI_SDHCI(dev);
1467 Error *local_err = NULL;
1468
1469 sdhci_initfn(s);
1470 sdhci_common_realize(s, &local_err);
1471 if (local_err) {
1472 error_propagate(errp, local_err);
1473 return;
1474 }
1475
1476 dev->config[PCI_CLASS_PROG] = 0x01; /* Standard Host supported DMA */
1477 dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
1478 s->irq = pci_allocate_irq(dev);
1479 s->dma_as = pci_get_address_space(dev);
1480 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->iomem);
1481}
1482
1483static void sdhci_pci_exit(PCIDevice *dev)
1484{
1485 SDHCIState *s = PCI_SDHCI(dev);
1486
1487 sdhci_common_unrealize(s, &error_abort);
1488 sdhci_uninitfn(s);
1489}
1490
1491static void sdhci_pci_class_init(ObjectClass *klass, void *data)
1492{
1493 DeviceClass *dc = DEVICE_CLASS(klass);
1494 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1495
1496 k->realize = sdhci_pci_realize;
1497 k->exit = sdhci_pci_exit;
1498 k->vendor_id = PCI_VENDOR_ID_REDHAT;
1499 k->device_id = PCI_DEVICE_ID_REDHAT_SDHCI;
1500 k->class_id = PCI_CLASS_SYSTEM_SDHCI;
1501 dc->props = sdhci_pci_properties;
1502
1503 sdhci_common_class_init(klass, data);
1504}
1505
1506static const TypeInfo sdhci_pci_info = {
1507 .name = TYPE_PCI_SDHCI,
1508 .parent = TYPE_PCI_DEVICE,
1509 .instance_size = sizeof(SDHCIState),
1510 .class_init = sdhci_pci_class_init,
1511 .interfaces = (InterfaceInfo[]) {
1512 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
1513 { },
1514 },
1515};
1516
1517/* --- qdev SysBus --- */
1518
1519static Property sdhci_sysbus_properties[] = {
1520 DEFINE_SDHCI_COMMON_PROPERTIES(SDHCIState),
1521 DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
1522 false),
1523 DEFINE_PROP_LINK("dma", SDHCIState,
1524 dma_mr, TYPE_MEMORY_REGION, MemoryRegion *),

--- 316 unchanged lines hidden (view full) ---

1841static const TypeInfo imx_usdhc_info = {
1842 .name = TYPE_IMX_USDHC,
1843 .parent = TYPE_SYSBUS_SDHCI,
1844 .instance_init = imx_usdhc_init,
1845};
1846
1847static void sdhci_register_types(void)
1848{
1430/* --- qdev SysBus --- */
1431
1432static Property sdhci_sysbus_properties[] = {
1433 DEFINE_SDHCI_COMMON_PROPERTIES(SDHCIState),
1434 DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
1435 false),
1436 DEFINE_PROP_LINK("dma", SDHCIState,
1437 dma_mr, TYPE_MEMORY_REGION, MemoryRegion *),

--- 316 unchanged lines hidden (view full) ---

1754static const TypeInfo imx_usdhc_info = {
1755 .name = TYPE_IMX_USDHC,
1756 .parent = TYPE_SYSBUS_SDHCI,
1757 .instance_init = imx_usdhc_init,
1758};
1759
1760static void sdhci_register_types(void)
1761{
1849 type_register_static(&sdhci_pci_info);
1850 type_register_static(&sdhci_sysbus_info);
1851 type_register_static(&sdhci_bus_info);
1852 type_register_static(&imx_usdhc_info);
1853}
1854
1855type_init(sdhci_register_types)
1762 type_register_static(&sdhci_sysbus_info);
1763 type_register_static(&sdhci_bus_info);
1764 type_register_static(&imx_usdhc_info);
1765}
1766
1767type_init(sdhci_register_types)