Revision a984a69e
b/hw/ads7846.c | ||
---|---|---|
7 | 7 |
* This code is licensed under the GNU GPL v2. |
8 | 8 |
*/ |
9 | 9 |
|
10 |
#include "hw.h" |
|
11 |
#include "devices.h" |
|
10 |
#include "ssi.h" |
|
12 | 11 |
#include "console.h" |
13 | 12 |
|
14 |
struct ADS7846State { |
|
13 |
typedef struct { |
|
14 |
SSISlave ssidev; |
|
15 | 15 |
qemu_irq interrupt; |
16 | 16 |
|
17 | 17 |
int input[8]; |
... | ... | |
20 | 20 |
|
21 | 21 |
int cycle; |
22 | 22 |
int output; |
23 |
}; |
|
23 |
} ADS7846State;
|
|
24 | 24 |
|
25 | 25 |
/* Control-byte bitfields */ |
26 | 26 |
#define CB_PD0 (1 << 0) |
... | ... | |
52 | 52 |
qemu_set_irq(s->interrupt, s->pressure == 0); |
53 | 53 |
} |
54 | 54 |
|
55 |
uint32_t ads7846_read(void *opaque) |
|
56 |
{ |
|
57 |
ADS7846State *s = (ADS7846State *) opaque; |
|
58 |
|
|
59 |
return s->output; |
|
60 |
} |
|
61 |
|
|
62 |
void ads7846_write(void *opaque, uint32_t value) |
|
55 |
static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value) |
|
63 | 56 |
{ |
64 |
ADS7846State *s = (ADS7846State *) opaque;
|
|
57 |
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
|
|
65 | 58 |
|
66 | 59 |
switch (s->cycle ++) { |
67 | 60 |
case 0: |
... | ... | |
89 | 82 |
s->cycle = 0; |
90 | 83 |
break; |
91 | 84 |
} |
85 |
return s->output; |
|
92 | 86 |
} |
93 | 87 |
|
94 | 88 |
static void ads7846_ts_event(void *opaque, |
... | ... | |
140 | 134 |
return 0; |
141 | 135 |
} |
142 | 136 |
|
143 |
ADS7846State *ads7846_init(qemu_irq penirq)
|
|
137 |
static void ads7846_init(SSISlave *dev)
|
|
144 | 138 |
{ |
145 |
ADS7846State *s; |
|
146 |
s = (ADS7846State *) |
|
147 |
qemu_mallocz(sizeof(ADS7846State)); |
|
148 |
memset(s, 0, sizeof(ADS7846State)); |
|
139 |
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev); |
|
149 | 140 |
|
150 |
s->interrupt = penirq;
|
|
141 |
qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1);
|
|
151 | 142 |
|
152 | 143 |
s->input[0] = ADS_TEMP0; /* TEMP0 */ |
153 | 144 |
s->input[2] = ADS_VBAT; /* VBAT */ |
... | ... | |
161 | 152 |
ads7846_int_update(s); |
162 | 153 |
|
163 | 154 |
register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s); |
155 |
} |
|
164 | 156 |
|
165 |
return s; |
|
157 |
static SSISlaveInfo ads7846_info = { |
|
158 |
.init = ads7846_init, |
|
159 |
.transfer = ads7846_transfer |
|
160 |
}; |
|
161 |
|
|
162 |
static void ads7846_register_devices(void) |
|
163 |
{ |
|
164 |
ssi_register_slave("ads7846", sizeof(ADS7846State), &ads7846_info); |
|
166 | 165 |
} |
166 |
|
|
167 |
device_init(ads7846_register_devices) |
b/hw/devices.h | ||
---|---|---|
6 | 6 |
/* smc91c111.c */ |
7 | 7 |
void smc91c111_init(NICInfo *, uint32_t, qemu_irq); |
8 | 8 |
|
9 |
/* ads7846.c */ |
|
10 |
typedef struct ADS7846State ADS7846State; |
|
11 |
uint32_t ads7846_read(void *opaque); |
|
12 |
void ads7846_write(void *opaque, uint32_t value); |
|
13 |
ADS7846State *ads7846_init(qemu_irq penirq); |
|
14 |
|
|
15 | 9 |
/* tsc210x.c */ |
16 | 10 |
uWireSlave *tsc2102_init(qemu_irq pint); |
17 | 11 |
uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav); |
b/hw/i2c.h | ||
---|---|---|
61 | 61 |
|
62 | 62 |
DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, int addr); |
63 | 63 |
|
64 |
/* max111x.c */ |
|
65 |
typedef struct MAX111xState MAX111xState; |
|
66 |
uint32_t max111x_read(void *opaque); |
|
67 |
void max111x_write(void *opaque, uint32_t value); |
|
68 |
MAX111xState *max1110_init(qemu_irq cb); |
|
69 |
MAX111xState *max1111_init(qemu_irq cb); |
|
70 |
void max111x_set_input(MAX111xState *s, int line, uint8_t value); |
|
71 |
|
|
72 | 64 |
/* max7310.c */ |
73 | 65 |
void max7310_reset(i2c_slave *i2c); |
74 | 66 |
qemu_irq *max7310_gpio_in_get(i2c_slave *i2c); |
b/hw/max111x.c | ||
---|---|---|
7 | 7 |
* This code is licensed under the GNU GPLv2. |
8 | 8 |
*/ |
9 | 9 |
|
10 |
#include "hw.h" |
|
11 |
#include "i2c.h" |
|
10 |
#include "ssi.h" |
|
12 | 11 |
|
13 |
struct MAX111xState { |
|
12 |
typedef struct { |
|
13 |
SSISlave ssidev; |
|
14 | 14 |
qemu_irq interrupt; |
15 | 15 |
uint8_t tb1, rb2, rb3; |
16 | 16 |
int cycle; |
17 | 17 |
|
18 | 18 |
int input[8]; |
19 | 19 |
int inputs, com; |
20 |
}; |
|
20 |
} MAX111xState;
|
|
21 | 21 |
|
22 | 22 |
/* Control-byte bitfields */ |
23 | 23 |
#define CB_PD0 (1 << 0) |
... | ... | |
34 | 34 |
(((v) >> (3 + (b1))) & 2) | \ |
35 | 35 |
(((v) >> (4 + (b2))) & 1)) |
36 | 36 |
|
37 |
uint32_t max111x_read(void *opaque)
|
|
37 |
static uint32_t max111x_read(MAX111xState *s)
|
|
38 | 38 |
{ |
39 |
MAX111xState *s = (MAX111xState *) opaque; |
|
40 |
|
|
41 | 39 |
if (!s->tb1) |
42 | 40 |
return 0; |
43 | 41 |
|
... | ... | |
52 | 50 |
} |
53 | 51 |
|
54 | 52 |
/* Interpret a control-byte */ |
55 |
void max111x_write(void *opaque, uint32_t value)
|
|
53 |
static void max111x_write(MAX111xState *s, uint32_t value)
|
|
56 | 54 |
{ |
57 |
MAX111xState *s = (MAX111xState *) opaque; |
|
58 | 55 |
int measure, chan; |
59 | 56 |
|
60 | 57 |
/* Ignore the value if START bit is zero */ |
... | ... | |
86 | 83 |
s->rb2 = (measure >> 2) & 0x3f; |
87 | 84 |
s->rb3 = (measure << 6) & 0xc0; |
88 | 85 |
|
89 |
if (s->interrupt) |
|
90 |
qemu_irq_raise(s->interrupt); |
|
86 |
/* FIXME: When should the IRQ be lowered? */ |
|
87 |
qemu_irq_raise(s->interrupt); |
|
88 |
} |
|
89 |
|
|
90 |
static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) |
|
91 |
{ |
|
92 |
MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev); |
|
93 |
max111x_write(s, value); |
|
94 |
return max111x_read(s); |
|
91 | 95 |
} |
92 | 96 |
|
93 | 97 |
static void max111x_save(QEMUFile *f, void *opaque) |
... | ... | |
121 | 125 |
return 0; |
122 | 126 |
} |
123 | 127 |
|
124 |
static MAX111xState *max111x_init(qemu_irq cb)
|
|
128 |
static void max111x_init(SSISlave *dev, int inputs)
|
|
125 | 129 |
{ |
126 |
MAX111xState *s; |
|
127 |
s = (MAX111xState *) |
|
128 |
qemu_mallocz(sizeof(MAX111xState)); |
|
129 |
memset(s, 0, sizeof(MAX111xState)); |
|
130 |
MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev); |
|
130 | 131 |
|
131 |
s->interrupt = cb;
|
|
132 |
qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1);
|
|
132 | 133 |
|
134 |
s->inputs = inputs; |
|
133 | 135 |
/* TODO: add a user interface for setting these */ |
134 | 136 |
s->input[0] = 0xf0; |
135 | 137 |
s->input[1] = 0xe0; |
... | ... | |
142 | 144 |
s->com = 0; |
143 | 145 |
|
144 | 146 |
register_savevm("max111x", -1, 0, max111x_save, max111x_load, s); |
145 |
|
|
146 |
return s; |
|
147 | 147 |
} |
148 | 148 |
|
149 |
MAX111xState *max1110_init(qemu_irq cb)
|
|
149 |
static void max1110_init(SSISlave *dev)
|
|
150 | 150 |
{ |
151 |
MAX111xState *s = max111x_init(cb); |
|
152 |
s->inputs = 8; |
|
153 |
return s; |
|
151 |
max111x_init(dev, 8); |
|
154 | 152 |
} |
155 | 153 |
|
156 |
MAX111xState *max1111_init(qemu_irq cb)
|
|
154 |
static void max1111_init(SSISlave *dev)
|
|
157 | 155 |
{ |
158 |
MAX111xState *s = max111x_init(cb); |
|
159 |
s->inputs = 4; |
|
160 |
return s; |
|
156 |
max111x_init(dev, 4); |
|
161 | 157 |
} |
162 | 158 |
|
163 |
void max111x_set_input(MAX111xState *s, int line, uint8_t value)
|
|
159 |
void max111x_set_input(DeviceState *dev, int line, uint8_t value)
|
|
164 | 160 |
{ |
165 |
if (line >= s->inputs) { |
|
166 |
printf("%s: There's no input %i\n", __FUNCTION__, line); |
|
167 |
return; |
|
168 |
} |
|
169 |
|
|
161 |
MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, SSI_SLAVE_FROM_QDEV(dev)); |
|
162 |
assert(line >= 0 && line < s->inputs); |
|
170 | 163 |
s->input[line] = value; |
171 | 164 |
} |
165 |
|
|
166 |
static SSISlaveInfo max1110_info = { |
|
167 |
.init = max1110_init, |
|
168 |
.transfer = max111x_transfer |
|
169 |
}; |
|
170 |
|
|
171 |
static SSISlaveInfo max1111_info = { |
|
172 |
.init = max1111_init, |
|
173 |
.transfer = max111x_transfer |
|
174 |
}; |
|
175 |
|
|
176 |
static void max111x_register_devices(void) |
|
177 |
{ |
|
178 |
ssi_register_slave("max1110", sizeof(MAX111xState), &max1110_info); |
|
179 |
ssi_register_slave("max1111", sizeof(MAX111xState), &max1111_info); |
|
180 |
} |
|
181 |
|
|
182 |
device_init(max111x_register_devices) |
b/hw/pxa.h | ||
---|---|---|
119 | 119 |
int size); |
120 | 120 |
|
121 | 121 |
/* pxa2xx.c */ |
122 |
typedef struct PXA2xxSSPState PXA2xxSSPState; |
|
123 |
void pxa2xx_ssp_attach(PXA2xxSSPState *port, |
|
124 |
uint32_t (*readfn)(void *opaque), |
|
125 |
void (*writefn)(void *opaque, uint32_t value), void *opaque); |
|
126 |
|
|
127 | 122 |
typedef struct PXA2xxI2CState PXA2xxI2CState; |
128 | 123 |
PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base, |
129 | 124 |
qemu_irq irq, uint32_t page_size); |
... | ... | |
139 | 134 |
PXA2xxDMAState *dma; |
140 | 135 |
PXA2xxGPIOInfo *gpio; |
141 | 136 |
PXA2xxLCDState *lcd; |
142 |
PXA2xxSSPState **ssp;
|
|
137 |
SSIBus **ssp;
|
|
143 | 138 |
PXA2xxI2CState *i2c[2]; |
144 | 139 |
PXA2xxMMCIState *mmc; |
145 | 140 |
PXA2xxPCMCIAState *pcmcia[2]; |
b/hw/pxa2xx.c | ||
---|---|---|
7 | 7 |
* This code is licenced under the GPL. |
8 | 8 |
*/ |
9 | 9 |
|
10 |
#include "hw.h"
|
|
10 |
#include "sysbus.h"
|
|
11 | 11 |
#include "pxa.h" |
12 | 12 |
#include "sysemu.h" |
13 | 13 |
#include "pc.h" |
14 | 14 |
#include "i2c.h" |
15 |
#include "ssi.h" |
|
15 | 16 |
#include "qemu-timer.h" |
16 | 17 |
#include "qemu-char.h" |
17 | 18 |
|
... | ... | |
547 | 548 |
} |
548 | 549 |
|
549 | 550 |
/* Synchronous Serial Ports */ |
550 |
struct PXA2xxSSPState { |
|
551 |
typedef struct { |
|
552 |
SysBusDevice busdev; |
|
551 | 553 |
qemu_irq irq; |
552 | 554 |
int enable; |
555 |
SSIBus *bus; |
|
553 | 556 |
|
554 | 557 |
uint32_t sscr[2]; |
555 | 558 |
uint32_t sspsp; |
... | ... | |
563 | 566 |
uint32_t rx_fifo[16]; |
564 | 567 |
int rx_level; |
565 | 568 |
int rx_start; |
566 |
|
|
567 |
uint32_t (*readfn)(void *opaque); |
|
568 |
void (*writefn)(void *opaque, uint32_t value); |
|
569 |
void *opaque; |
|
570 |
}; |
|
569 |
} PXA2xxSSPState; |
|
571 | 570 |
|
572 | 571 |
#define SSCR0 0x00 /* SSP Control register 0 */ |
573 | 572 |
#define SSCR1 0x04 /* SSP Control register 1 */ |
... | ... | |
763 | 762 |
* there directly to the slave, no need to buffer it. |
764 | 763 |
*/ |
765 | 764 |
if (s->enable) { |
766 |
if (s->writefn) |
|
767 |
s->writefn(s->opaque, value); |
|
768 |
|
|
765 |
uint32_t readval; |
|
766 |
readval = ssi_transfer(s->bus, value); |
|
769 | 767 |
if (s->rx_level < 0x10) { |
770 |
if (s->readfn) |
|
771 |
s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = |
|
772 |
s->readfn(s->opaque); |
|
773 |
else |
|
774 |
s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = 0x0; |
|
775 |
} else |
|
768 |
s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = readval; |
|
769 |
} else { |
|
776 | 770 |
s->sssr |= SSSR_ROR; |
771 |
} |
|
777 | 772 |
} |
778 | 773 |
pxa2xx_ssp_fifo_update(s); |
779 | 774 |
break; |
... | ... | |
796 | 791 |
} |
797 | 792 |
} |
798 | 793 |
|
799 |
void pxa2xx_ssp_attach(PXA2xxSSPState *port, |
|
800 |
uint32_t (*readfn)(void *opaque), |
|
801 |
void (*writefn)(void *opaque, uint32_t value), void *opaque) |
|
802 |
{ |
|
803 |
if (!port) { |
|
804 |
printf("%s: no such SSP\n", __FUNCTION__); |
|
805 |
exit(-1); |
|
806 |
} |
|
807 |
|
|
808 |
port->opaque = opaque; |
|
809 |
port->readfn = readfn; |
|
810 |
port->writefn = writefn; |
|
811 |
} |
|
812 |
|
|
813 | 794 |
static CPUReadMemoryFunc *pxa2xx_ssp_readfn[] = { |
814 | 795 |
pxa2xx_ssp_read, |
815 | 796 |
pxa2xx_ssp_read, |
... | ... | |
869 | 850 |
return 0; |
870 | 851 |
} |
871 | 852 |
|
853 |
static void pxa2xx_ssp_init(SysBusDevice *dev) |
|
854 |
{ |
|
855 |
int iomemtype; |
|
856 |
PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev); |
|
857 |
|
|
858 |
sysbus_init_irq(dev, &s->irq); |
|
859 |
|
|
860 |
iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn, |
|
861 |
pxa2xx_ssp_writefn, s); |
|
862 |
sysbus_init_mmio(dev, 0x1000, iomemtype); |
|
863 |
register_savevm("pxa2xx_ssp", -1, 0, |
|
864 |
pxa2xx_ssp_save, pxa2xx_ssp_load, s); |
|
865 |
|
|
866 |
s->bus = ssi_create_bus(); |
|
867 |
qdev_attach_child_bus(&dev->qdev, "ssi", s->bus); |
|
868 |
} |
|
869 |
|
|
872 | 870 |
/* Real-Time Clock */ |
873 | 871 |
#define RCNR 0x00 /* RTC Counter register */ |
874 | 872 |
#define RTAR 0x04 /* RTC Alarm register */ |
... | ... | |
2034 | 2032 |
PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision) |
2035 | 2033 |
{ |
2036 | 2034 |
PXA2xxState *s; |
2037 |
PXA2xxSSPState *ssp; |
|
2038 | 2035 |
int iomemtype, i; |
2039 | 2036 |
int index; |
2040 | 2037 |
s = (PXA2xxState *) qemu_mallocz(sizeof(PXA2xxState)); |
... | ... | |
2115 | 2112 |
register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s); |
2116 | 2113 |
|
2117 | 2114 |
for (i = 0; pxa27x_ssp[i].io_base; i ++); |
2118 |
s->ssp = (PXA2xxSSPState **) |
|
2119 |
qemu_mallocz(sizeof(PXA2xxSSPState *) * i); |
|
2120 |
ssp = (PXA2xxSSPState *) |
|
2121 |
qemu_mallocz(sizeof(PXA2xxSSPState) * i); |
|
2115 |
s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i); |
|
2122 | 2116 |
for (i = 0; pxa27x_ssp[i].io_base; i ++) { |
2123 |
target_phys_addr_t ssp_base; |
|
2124 |
s->ssp[i] = &ssp[i]; |
|
2125 |
ssp_base = pxa27x_ssp[i].io_base; |
|
2126 |
ssp[i].irq = s->pic[pxa27x_ssp[i].irqn]; |
|
2127 |
|
|
2128 |
iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn, |
|
2129 |
pxa2xx_ssp_writefn, &ssp[i]); |
|
2130 |
cpu_register_physical_memory(ssp_base, 0x1000, iomemtype); |
|
2131 |
register_savevm("pxa2xx_ssp", i, 0, |
|
2132 |
pxa2xx_ssp_save, pxa2xx_ssp_load, s); |
|
2117 |
DeviceState *dev; |
|
2118 |
dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base, |
|
2119 |
s->pic[pxa27x_ssp[i].irqn]); |
|
2120 |
s->ssp[i] = qdev_get_child_bus(dev, "ssi"); |
|
2133 | 2121 |
} |
2134 | 2122 |
|
2135 | 2123 |
if (usb_enabled) { |
... | ... | |
2163 | 2151 |
PXA2xxState *pxa255_init(unsigned int sdram_size) |
2164 | 2152 |
{ |
2165 | 2153 |
PXA2xxState *s; |
2166 |
PXA2xxSSPState *ssp; |
|
2167 | 2154 |
int iomemtype, i; |
2168 | 2155 |
int index; |
2169 | 2156 |
|
... | ... | |
2237 | 2224 |
register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s); |
2238 | 2225 |
|
2239 | 2226 |
for (i = 0; pxa255_ssp[i].io_base; i ++); |
2240 |
s->ssp = (PXA2xxSSPState **) |
|
2241 |
qemu_mallocz(sizeof(PXA2xxSSPState *) * i); |
|
2242 |
ssp = (PXA2xxSSPState *) |
|
2243 |
qemu_mallocz(sizeof(PXA2xxSSPState) * i); |
|
2227 |
s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i); |
|
2244 | 2228 |
for (i = 0; pxa255_ssp[i].io_base; i ++) { |
2245 |
target_phys_addr_t ssp_base; |
|
2246 |
s->ssp[i] = &ssp[i]; |
|
2247 |
ssp_base = pxa255_ssp[i].io_base; |
|
2248 |
ssp[i].irq = s->pic[pxa255_ssp[i].irqn]; |
|
2249 |
|
|
2250 |
iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn, |
|
2251 |
pxa2xx_ssp_writefn, &ssp[i]); |
|
2252 |
cpu_register_physical_memory(ssp_base, 0x1000, iomemtype); |
|
2253 |
register_savevm("pxa2xx_ssp", i, 0, |
|
2254 |
pxa2xx_ssp_save, pxa2xx_ssp_load, s); |
|
2229 |
DeviceState *dev; |
|
2230 |
dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base, |
|
2231 |
s->pic[pxa255_ssp[i].irqn]); |
|
2232 |
s->ssp[i] = qdev_get_child_bus(dev, "ssi"); |
|
2255 | 2233 |
} |
2256 | 2234 |
|
2257 | 2235 |
if (usb_enabled) { |
... | ... | |
2283 | 2261 |
{ |
2284 | 2262 |
i2c_register_slave("pxa2xx-i2c-slave", sizeof(PXA2xxI2CSlaveState), |
2285 | 2263 |
&pxa2xx_i2c_slave_info); |
2264 |
sysbus_register_dev("pxa2xx-ssp", sizeof(PXA2xxSSPState), pxa2xx_ssp_init); |
|
2286 | 2265 |
} |
2287 | 2266 |
|
2288 | 2267 |
device_init(pxa2xx_register_devices) |
b/hw/spitz.c | ||
---|---|---|
13 | 13 |
#include "sysemu.h" |
14 | 14 |
#include "pcmcia.h" |
15 | 15 |
#include "i2c.h" |
16 |
#include "ssi.h" |
|
16 | 17 |
#include "flash.h" |
17 | 18 |
#include "qemu-timer.h" |
18 | 19 |
#include "devices.h" |
... | ... | |
525 | 526 |
#define LCDTG_PICTRL 0x06 |
526 | 527 |
#define LCDTG_POLCTRL 0x07 |
527 | 528 |
|
528 |
static int bl_intensity, bl_power; |
|
529 |
typedef struct { |
|
530 |
SSISlave ssidev; |
|
531 |
int bl_intensity; |
|
532 |
int bl_power; |
|
533 |
} SpitzLCDTG; |
|
529 | 534 |
|
530 |
static void spitz_bl_update(PXA2xxState *s)
|
|
535 |
static void spitz_bl_update(SpitzLCDTG *s)
|
|
531 | 536 |
{ |
532 |
if (bl_power && bl_intensity)
|
|
533 |
zaurus_printf("LCD Backlight now at %i/63\n", bl_intensity); |
|
537 |
if (s->bl_power && s->bl_intensity)
|
|
538 |
zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity);
|
|
534 | 539 |
else |
535 | 540 |
zaurus_printf("LCD Backlight now off\n"); |
536 | 541 |
} |
537 | 542 |
|
543 |
/* FIXME: Implement GPIO properly and remove this hack. */ |
|
544 |
static SpitzLCDTG *spitz_lcdtg; |
|
545 |
|
|
538 | 546 |
static inline void spitz_bl_bit5(void *opaque, int line, int level) |
539 | 547 |
{ |
540 |
int prev = bl_intensity; |
|
548 |
SpitzLCDTG *s = spitz_lcdtg; |
|
549 |
int prev = s->bl_intensity; |
|
541 | 550 |
|
542 | 551 |
if (level) |
543 |
bl_intensity &= ~0x20; |
|
552 |
s->bl_intensity &= ~0x20;
|
|
544 | 553 |
else |
545 |
bl_intensity |= 0x20; |
|
554 |
s->bl_intensity |= 0x20;
|
|
546 | 555 |
|
547 |
if (bl_power && prev != bl_intensity)
|
|
548 |
spitz_bl_update((PXA2xxState *) opaque);
|
|
556 |
if (s->bl_power && prev != s->bl_intensity)
|
|
557 |
spitz_bl_update(s);
|
|
549 | 558 |
} |
550 | 559 |
|
551 | 560 |
static inline void spitz_bl_power(void *opaque, int line, int level) |
552 | 561 |
{ |
553 |
bl_power = !!level; |
|
554 |
spitz_bl_update((PXA2xxState *) opaque); |
|
562 |
SpitzLCDTG *s = spitz_lcdtg; |
|
563 |
s->bl_power = !!level; |
|
564 |
spitz_bl_update(s); |
|
555 | 565 |
} |
556 | 566 |
|
557 |
static void spitz_lcdtg_dac_put(void *opaque, uint8_t cmd)
|
|
567 |
static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
|
|
558 | 568 |
{ |
559 |
int addr, value; |
|
560 |
addr = cmd >> 5; |
|
561 |
value = cmd & 0x1f; |
|
569 |
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev); |
|
570 |
int addr; |
|
571 |
addr = value >> 5; |
|
572 |
value &= 0x1f; |
|
562 | 573 |
|
563 | 574 |
switch (addr) { |
564 | 575 |
case LCDTG_RESCTL: |
... | ... | |
569 | 580 |
break; |
570 | 581 |
|
571 | 582 |
case LCDTG_DUTYCTRL: |
572 |
bl_intensity &= ~0x1f; |
|
573 |
bl_intensity |= value; |
|
574 |
if (bl_power) |
|
575 |
spitz_bl_update((PXA2xxState *) opaque);
|
|
583 |
s->bl_intensity &= ~0x1f;
|
|
584 |
s->bl_intensity |= value;
|
|
585 |
if (s->bl_power)
|
|
586 |
spitz_bl_update(s);
|
|
576 | 587 |
break; |
577 | 588 |
|
578 | 589 |
case LCDTG_POWERREG0: |
579 | 590 |
/* Set common voltage to M62332FP */ |
580 | 591 |
break; |
581 | 592 |
} |
593 |
return 0; |
|
594 |
} |
|
595 |
|
|
596 |
static void spitz_lcdtg_save(QEMUFile *f, void *opaque) |
|
597 |
{ |
|
598 |
SpitzLCDTG *s = (SpitzLCDTG *)opaque; |
|
599 |
qemu_put_be32(f, s->bl_intensity); |
|
600 |
qemu_put_be32(f, s->bl_power); |
|
601 |
} |
|
602 |
|
|
603 |
static int spitz_lcdtg_load(QEMUFile *f, void *opaque, int version_id) |
|
604 |
{ |
|
605 |
SpitzLCDTG *s = (SpitzLCDTG *)opaque; |
|
606 |
s->bl_intensity = qemu_get_be32(f); |
|
607 |
s->bl_power = qemu_get_be32(f); |
|
608 |
return 0; |
|
609 |
} |
|
610 |
|
|
611 |
static void spitz_lcdtg_init(SSISlave *dev) |
|
612 |
{ |
|
613 |
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev); |
|
614 |
|
|
615 |
spitz_lcdtg = s; |
|
616 |
s->bl_power = 0; |
|
617 |
s->bl_intensity = 0x20; |
|
618 |
|
|
619 |
register_savevm("spitz-lcdtg", -1, 1, |
|
620 |
spitz_lcdtg_save, spitz_lcdtg_load, s); |
|
582 | 621 |
} |
583 | 622 |
|
584 | 623 |
/* SSP devices */ |
... | ... | |
590 | 629 |
#define SPITZ_GPIO_MAX1111_CS 20 |
591 | 630 |
#define SPITZ_GPIO_TP_INT 11 |
592 | 631 |
|
593 |
static int lcd_en, ads_en, max_en; |
|
594 |
static MAX111xState *max1111; |
|
595 |
static ADS7846State *ads7846; |
|
632 |
static DeviceState *max1111; |
|
596 | 633 |
|
597 | 634 |
/* "Demux" the signal based on current chipselect */ |
598 |
static uint32_t corgi_ssp_read(void *opaque) |
|
599 |
{ |
|
600 |
if (lcd_en) |
|
601 |
return 0; |
|
602 |
if (ads_en) |
|
603 |
return ads7846_read(ads7846); |
|
604 |
if (max_en) |
|
605 |
return max111x_read(max1111); |
|
606 |
return 0; |
|
607 |
} |
|
635 |
typedef struct { |
|
636 |
SSISlave ssidev; |
|
637 |
SSIBus *bus[3]; |
|
638 |
int enable[3]; |
|
639 |
} CorgiSSPState; |
|
608 | 640 |
|
609 |
static void corgi_ssp_write(void *opaque, uint32_t value)
|
|
641 |
static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
|
|
610 | 642 |
{ |
611 |
if (lcd_en) |
|
612 |
spitz_lcdtg_dac_put(opaque, value); |
|
613 |
if (ads_en) |
|
614 |
ads7846_write(ads7846, value); |
|
615 |
if (max_en) |
|
616 |
max111x_write(max1111, value); |
|
643 |
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); |
|
644 |
int i; |
|
645 |
|
|
646 |
for (i = 0; i < 3; i++) { |
|
647 |
if (s->enable[i]) { |
|
648 |
return ssi_transfer(s->bus[i], value); |
|
649 |
} |
|
650 |
} |
|
651 |
return 0; |
|
617 | 652 |
} |
618 | 653 |
|
619 | 654 |
static void corgi_ssp_gpio_cs(void *opaque, int line, int level) |
620 | 655 |
{ |
621 |
switch (line) { |
|
622 |
case 0: |
|
623 |
lcd_en = !level; |
|
624 |
break; |
|
625 |
case 1: |
|
626 |
ads_en = !level; |
|
627 |
break; |
|
628 |
case 2: |
|
629 |
max_en = !level; |
|
630 |
break; |
|
631 |
} |
|
656 |
CorgiSSPState *s = (CorgiSSPState *)opaque; |
|
657 |
assert(line >= 0 && line < 3); |
|
658 |
s->enable[line] = !level; |
|
632 | 659 |
} |
633 | 660 |
|
634 | 661 |
#define MAX1111_BATT_VOLT 1 |
... | ... | |
652 | 679 |
|
653 | 680 |
static void spitz_ssp_save(QEMUFile *f, void *opaque) |
654 | 681 |
{ |
655 |
qemu_put_be32(f, lcd_en); |
|
656 |
qemu_put_be32(f, ads_en); |
|
657 |
qemu_put_be32(f, max_en); |
|
658 |
qemu_put_be32(f, bl_intensity); |
|
659 |
qemu_put_be32(f, bl_power); |
|
682 |
CorgiSSPState *s = (CorgiSSPState *)opaque; |
|
683 |
int i; |
|
684 |
|
|
685 |
for (i = 0; i < 3; i++) { |
|
686 |
qemu_put_be32(f, s->enable[i]); |
|
687 |
} |
|
660 | 688 |
} |
661 | 689 |
|
662 | 690 |
static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id) |
663 | 691 |
{ |
664 |
lcd_en = qemu_get_be32(f); |
|
665 |
ads_en = qemu_get_be32(f); |
|
666 |
max_en = qemu_get_be32(f); |
|
667 |
bl_intensity = qemu_get_be32(f); |
|
668 |
bl_power = qemu_get_be32(f); |
|
692 |
CorgiSSPState *s = (CorgiSSPState *)opaque; |
|
693 |
int i; |
|
669 | 694 |
|
695 |
if (version_id != 1) { |
|
696 |
return -EINVAL; |
|
697 |
} |
|
698 |
for (i = 0; i < 3; i++) { |
|
699 |
s->enable[i] = qemu_get_be32(f); |
|
700 |
} |
|
670 | 701 |
return 0; |
671 | 702 |
} |
672 | 703 |
|
704 |
static void corgi_ssp_init(SSISlave *dev) |
|
705 |
{ |
|
706 |
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); |
|
707 |
|
|
708 |
qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3); |
|
709 |
s->bus[0] = ssi_create_bus(); |
|
710 |
qdev_attach_child_bus(&dev->qdev, "ssi0", s->bus[0]); |
|
711 |
s->bus[1] = ssi_create_bus(); |
|
712 |
qdev_attach_child_bus(&dev->qdev, "ssi1", s->bus[1]); |
|
713 |
s->bus[2] = ssi_create_bus(); |
|
714 |
qdev_attach_child_bus(&dev->qdev, "ssi2", s->bus[2]); |
|
715 |
|
|
716 |
register_savevm("spitz_ssp", -1, 1, spitz_ssp_save, spitz_ssp_load, s); |
|
717 |
} |
|
718 |
|
|
673 | 719 |
static void spitz_ssp_attach(PXA2xxState *cpu) |
674 | 720 |
{ |
675 |
qemu_irq *chipselects; |
|
721 |
DeviceState *mux; |
|
722 |
DeviceState *dev; |
|
723 |
void *bus; |
|
724 |
|
|
725 |
mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp"); |
|
676 | 726 |
|
677 |
lcd_en = ads_en = max_en = 0; |
|
727 |
bus = qdev_get_child_bus(mux, "ssi0"); |
|
728 |
dev = ssi_create_slave(bus, "spitz-lcdtg"); |
|
678 | 729 |
|
679 |
ads7846 = ads7846_init(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]); |
|
730 |
bus = qdev_get_child_bus(mux, "ssi1"); |
|
731 |
dev = ssi_create_slave(bus, "ads7846"); |
|
732 |
qdev_connect_gpio_out(dev, 0, |
|
733 |
pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]); |
|
680 | 734 |
|
681 |
max1111 = max1111_init(0); |
|
735 |
bus = qdev_get_child_bus(mux, "ssi2"); |
|
736 |
max1111 = ssi_create_slave(bus, "max1111"); |
|
682 | 737 |
max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT); |
683 | 738 |
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); |
684 | 739 |
max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN); |
685 | 740 |
|
686 |
pxa2xx_ssp_attach(cpu->ssp[CORGI_SSP_PORT - 1], corgi_ssp_read, |
|
687 |
corgi_ssp_write, cpu); |
|
688 |
|
|
689 |
chipselects = qemu_allocate_irqs(corgi_ssp_gpio_cs, cpu, 3); |
|
690 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS, chipselects[0]); |
|
691 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS, chipselects[1]); |
|
692 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS, chipselects[2]); |
|
693 |
|
|
694 |
bl_intensity = 0x20; |
|
695 |
bl_power = 0; |
|
696 |
|
|
697 |
register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu); |
|
741 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS, |
|
742 |
qdev_get_gpio_in(mux, 0)); |
|
743 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS, |
|
744 |
qdev_get_gpio_in(mux, 1)); |
|
745 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS, |
|
746 |
qdev_get_gpio_in(mux, 2)); |
|
698 | 747 |
} |
699 | 748 |
|
700 | 749 |
/* CF Microdrive */ |
... | ... | |
1018 | 1067 |
.desc = "Terrier PDA (PXA270)", |
1019 | 1068 |
.init = terrier_init, |
1020 | 1069 |
}; |
1070 |
|
|
1071 |
static SSISlaveInfo corgi_ssp_info = { |
|
1072 |
.init = corgi_ssp_init, |
|
1073 |
.transfer = corgi_ssp_transfer |
|
1074 |
}; |
|
1075 |
|
|
1076 |
static SSISlaveInfo spitz_lcdtg_info = { |
|
1077 |
.init = spitz_lcdtg_init, |
|
1078 |
.transfer = spitz_lcdtg_transfer |
|
1079 |
}; |
|
1080 |
|
|
1081 |
static void spitz_register_devices(void) |
|
1082 |
{ |
|
1083 |
ssi_register_slave("corgi-ssp", sizeof(CorgiSSPState), &corgi_ssp_info); |
|
1084 |
ssi_register_slave("spitz-lcdtg", sizeof(SpitzLCDTG), &spitz_lcdtg_info); |
|
1085 |
} |
|
1086 |
|
|
1087 |
device_init(spitz_register_devices) |
b/hw/ssi.h | ||
---|---|---|
38 | 38 |
|
39 | 39 |
uint32_t ssi_transfer(SSIBus *bus, uint32_t val); |
40 | 40 |
|
41 |
/* max111x.c */ |
|
42 |
void max111x_set_input(DeviceState *dev, int line, uint8_t value); |
|
43 |
|
|
41 | 44 |
#endif |
b/hw/tosa.c | ||
---|---|---|
18 | 18 |
#include "block.h" |
19 | 19 |
#include "boards.h" |
20 | 20 |
#include "i2c.h" |
21 |
#include "ssi.h" |
|
21 | 22 |
|
22 | 23 |
#define TOSA_RAM 0x04000000 |
23 | 24 |
#define TOSA_ROM 0x00800000 |
... | ... | |
114 | 115 |
scoop_gpio_out_set(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio)); |
115 | 116 |
} |
116 | 117 |
|
117 |
static uint32_t tosa_ssp_read(void *opaque)
|
|
118 |
static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
|
|
118 | 119 |
{ |
120 |
fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f); |
|
119 | 121 |
return 0; |
120 | 122 |
} |
121 | 123 |
|
122 |
static void tosa_ssp_write(void *opaque, uint32_t value)
|
|
124 |
static void tosa_ssp_init(SSISlave *dev)
|
|
123 | 125 |
{ |
124 |
fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
|
|
126 |
/* Nothing to do. */
|
|
125 | 127 |
} |
126 | 128 |
|
127 | 129 |
typedef struct { |
... | ... | |
187 | 189 |
{ |
188 | 190 |
i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); |
189 | 191 |
i2c_create_slave(bus, "tosa_dac", DAC_BASE); |
190 |
pxa2xx_ssp_attach(cpu->ssp[1], tosa_ssp_read, |
|
191 |
tosa_ssp_write, cpu); |
|
192 |
ssi_create_slave(cpu->ssp[1], "tosa-ssp"); |
|
192 | 193 |
} |
193 | 194 |
|
194 | 195 |
|
... | ... | |
250 | 251 |
.send = tosa_dac_send |
251 | 252 |
}; |
252 | 253 |
|
254 |
static SSISlaveInfo tosa_ssp_info = { |
|
255 |
.init = tosa_ssp_init, |
|
256 |
.transfer = tosa_ssp_tansfer |
|
257 |
}; |
|
258 |
|
|
253 | 259 |
static void tosa_register_devices(void) |
254 | 260 |
{ |
255 | 261 |
i2c_register_slave("tosa_dac", sizeof(TosaDACState), &tosa_dac_info); |
262 |
ssi_register_slave("tosa-ssp", sizeof(SSISlave), &tosa_ssp_info); |
|
256 | 263 |
} |
257 | 264 |
|
258 | 265 |
device_init(tosa_register_devices) |
Also available in: Unified diff