|
|
1.1 root 1: /*
2: * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
3: *
4: * Copyright (c) 2006 Openedhand Ltd.
5: * Written by Andrzej Zaborowski <[email protected]>
6: *
7: * This code is licensed under the GPLv2.
1.1.1.7 ! root 8: *
! 9: * Contributions after 2012-01-13 are licensed under the terms of the
! 10: * GNU GPL, version 2 or (at your option) any later version.
1.1 root 11: */
12:
13: #include "hw.h"
14: #include "pcmcia.h"
15: #include "pxa.h"
16:
1.1.1.7 ! root 17:
1.1.1.3 root 18: struct PXA2xxPCMCIAState {
19: PCMCIASocket slot;
20: PCMCIACardState *card;
1.1.1.7 ! root 21: MemoryRegion common_iomem;
! 22: MemoryRegion attr_iomem;
! 23: MemoryRegion iomem;
1.1 root 24:
25: qemu_irq irq;
26: qemu_irq cd_irq;
27: };
28:
1.1.1.7 ! root 29: static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
! 30: target_phys_addr_t offset, unsigned size)
1.1 root 31: {
1.1.1.3 root 32: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 33:
34: if (s->slot.attached) {
35: return s->card->common_read(s->card->state, offset);
36: }
37:
38: return 0;
39: }
40:
1.1.1.7 ! root 41: static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset,
! 42: uint64_t value, unsigned size)
1.1 root 43: {
1.1.1.3 root 44: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 45:
46: if (s->slot.attached) {
47: s->card->common_write(s->card->state, offset, value);
48: }
49: }
50:
1.1.1.7 ! root 51: static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
! 52: target_phys_addr_t offset, unsigned size)
1.1 root 53: {
1.1.1.3 root 54: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 55:
56: if (s->slot.attached) {
57: return s->card->attr_read(s->card->state, offset);
58: }
59:
60: return 0;
61: }
62:
1.1.1.7 ! root 63: static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset,
! 64: uint64_t value, unsigned size)
1.1 root 65: {
1.1.1.3 root 66: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 67:
68: if (s->slot.attached) {
69: s->card->attr_write(s->card->state, offset, value);
70: }
71: }
72:
1.1.1.7 ! root 73: static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
! 74: target_phys_addr_t offset, unsigned size)
1.1 root 75: {
1.1.1.3 root 76: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 77:
78: if (s->slot.attached) {
79: return s->card->io_read(s->card->state, offset);
80: }
81:
82: return 0;
83: }
84:
1.1.1.7 ! root 85: static void pxa2xx_pcmcia_io_write(void *opaque, target_phys_addr_t offset,
! 86: uint64_t value, unsigned size)
1.1 root 87: {
1.1.1.3 root 88: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 89:
90: if (s->slot.attached) {
91: s->card->io_write(s->card->state, offset, value);
92: }
93: }
94:
1.1.1.7 ! root 95: static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
! 96: .read = pxa2xx_pcmcia_common_read,
! 97: .write = pxa2xx_pcmcia_common_write,
! 98: .endianness = DEVICE_NATIVE_ENDIAN
! 99: };
! 100:
! 101: static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
! 102: .read = pxa2xx_pcmcia_attr_read,
! 103: .write = pxa2xx_pcmcia_attr_write,
! 104: .endianness = DEVICE_NATIVE_ENDIAN
! 105: };
! 106:
! 107: static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
! 108: .read = pxa2xx_pcmcia_io_read,
! 109: .write = pxa2xx_pcmcia_io_write,
! 110: .endianness = DEVICE_NATIVE_ENDIAN
1.1 root 111: };
112:
113: static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
114: {
1.1.1.3 root 115: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 116: if (!s->irq)
117: return;
118:
119: qemu_set_irq(s->irq, level);
120: }
121:
1.1.1.7 ! root 122: PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
! 123: target_phys_addr_t base)
1.1 root 124: {
1.1.1.3 root 125: PXA2xxPCMCIAState *s;
1.1 root 126:
1.1.1.3 root 127: s = (PXA2xxPCMCIAState *)
1.1.1.6 root 128: g_malloc0(sizeof(PXA2xxPCMCIAState));
1.1 root 129:
130: /* Socket I/O Memory Space */
1.1.1.7 ! root 131: memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
! 132: "pxa2xx-pcmcia-io", 0x04000000);
! 133: memory_region_add_subregion(sysmem, base | 0x00000000,
! 134: &s->iomem);
1.1 root 135:
136: /* Then next 64 MB is reserved */
137:
138: /* Socket Attribute Memory Space */
1.1.1.7 ! root 139: memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
! 140: "pxa2xx-pcmcia-attribute", 0x04000000);
! 141: memory_region_add_subregion(sysmem, base | 0x08000000,
! 142: &s->attr_iomem);
1.1 root 143:
144: /* Socket Common Memory Space */
1.1.1.7 ! root 145: memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
! 146: "pxa2xx-pcmcia-common", 0x04000000);
! 147: memory_region_add_subregion(sysmem, base | 0x0c000000,
! 148: &s->common_iomem);
1.1 root 149:
150: if (base == 0x30000000)
151: s->slot.slot_string = "PXA PC Card Socket 1";
152: else
153: s->slot.slot_string = "PXA PC Card Socket 0";
154: s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
155: pcmcia_socket_register(&s->slot);
156:
157: return s;
158: }
159:
160: /* Insert a new card into a slot */
1.1.1.3 root 161: int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
1.1 root 162: {
1.1.1.3 root 163: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 164: if (s->slot.attached)
165: return -EEXIST;
166:
167: if (s->cd_irq) {
168: qemu_irq_raise(s->cd_irq);
169: }
170:
171: s->card = card;
172:
173: s->slot.attached = 1;
174: s->card->slot = &s->slot;
175: s->card->attach(s->card->state);
176:
177: return 0;
178: }
179:
180: /* Eject card from the slot */
181: int pxa2xx_pcmcia_dettach(void *opaque)
182: {
1.1.1.3 root 183: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 184: if (!s->slot.attached)
185: return -ENOENT;
186:
187: s->card->detach(s->card->state);
1.1.1.4 root 188: s->card->slot = NULL;
189: s->card = NULL;
1.1 root 190:
191: s->slot.attached = 0;
192:
193: if (s->irq)
194: qemu_irq_lower(s->irq);
195: if (s->cd_irq)
196: qemu_irq_lower(s->cd_irq);
197:
198: return 0;
199: }
200:
201: /* Who to notify on card events */
202: void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
203: {
1.1.1.3 root 204: PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
1.1 root 205: s->irq = irq;
206: s->cd_irq = cd_irq;
207: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.