1 // license:BSD-3-Clause
2 // copyright-holders:Tim Schuerewegen
3 /*******************************************************************************
4
5 Samsung S3C2400 / S3C2410 / S3C2440
6
7 *******************************************************************************/
8
9 #include "emu.h"
10 #include "cpu/arm7/arm7.h"
11 #include "cpu/arm7/arm7core.h"
12 #include "coreutil.h"
13
14 /*******************************************************************************
15 MACROS & CONSTANTS
16 *******************************************************************************/
17
18 #define UART_PRINTF
19
20 #define CLOCK_MULTIPLIER 1
21
22 #if defined(DEVICE_S3C2400)
23
24 #define S3C24XX_TPAL_GET_TPALEN(x) BIT(x,16)
25 #define S3C24XX_TPAL_GET_TPALVAL(x) BITS(x,15,0)
26
27 #else
28
29 #define S3C24XX_TPAL_GET_TPALEN(x) BIT(x,24)
30 #define S3C24XX_TPAL_GET_TPALVAL(x) BITS(x,23,0)
31
32 #endif
33
34 #define S3C24XX_DCON_GET_TC(x) BITS(x,19,0)
35 #define S3C24XX_DCON_GET_DSZ(x) BITS(x,21,20)
36 #define S3C24XX_DCON_GET_RELOAD(x) BIT(x,22)
37 #define S3C24XX_DCON_GET_SWHWSEL(x) BIT(x,23)
38
39 #define S3C24XX_DSTAT_GET_CURR_TC(x) BITS(x,19,0)
40 #define S3C24XX_DSTAT_SET_CURR_TC(x,m) (CLR_BITS(x,19,0) | m)
41
42 #define S3C24XX_DMASKTRIG_GET_ON_OFF(x) BIT(x,1)
43
44 #if defined(DEVICE_S3C2400)
45
46 #define S3C24XX_DCON_GET_HWSRCSEL(x) BITS(x,25,24)
47 #define S3C24XX_DCON_GET_SERVMODE(x) BIT(x,26)
48 #define S3C24XX_DCON_GET_TSZ(x) BIT(x,27)
49 #define S3C24XX_DCON_GET_INT(x) BIT(x,28)
50
51 #define S3C24XX_DISRC_GET_SADDR(x) BITS(x,28,0)
52
53 #define S3C24XX_DIDST_GET_DADDR(x) BITS(x,28,0)
54
55 #define S3C24XX_DCSRC_GET_CURR_SRC(x) BITS(x,28,0)
56 #define S3C24XX_DCSRC_SET_CURR_SRC(x,m) (CLR_BITS(x,28,0) | m)
57
58 #define S3C24XX_DCDST_GET_CURR_DST(x) BITS(x,28,0)
59 #define S3C24XX_DCDST_SET_CURR_DST(x,m) (CLR_BITS(x,28,0) | m)
60
61 #else
62
63 #define S3C24XX_DCON_GET_HWSRCSEL(x) BITS(x,26,24)
64 #define S3C24XX_DCON_GET_SERVMODE(x) BIT(x,27)
65 #define S3C24XX_DCON_GET_TSZ(x) BIT(x,28)
66 #define S3C24XX_DCON_GET_INT(x) BIT(x,29)
67
68 #define S3C24XX_DISRC_GET_SADDR(x) BITS(x,30,0)
69
70 #define S3C24XX_DIDST_GET_DADDR(x) BITS(x,30,0)
71
72 #define S3C24XX_DCSRC_GET_CURR_SRC(x) BITS(x,30,0)
73 #define S3C24XX_DCSRC_SET_CURR_SRC(x,m) (CLR_BITS(x,30,0) | m)
74
75 #define S3C24XX_DCDST_GET_CURR_DST(x) BITS(x,30,0)
76 #define S3C24XX_DCDST_SET_CURR_DST(x,m) (CLR_BITS(x,30,0) | m)
77
78 #endif
79
80 #define LOG_RESET (u64(1) << 1)
81 #define LOG_ADC (u64(1) << 2)
82 #define LOG_LCD_DMA (u64(1) << 3)
83 #define LOG_LCD_TIMER (u64(1) << 4)
84 #define LOG_LCD_REGS (u64(1) << 5)
85 #define LOG_SPI (u64(1) << 6)
86 #define LOG_LCD_CFG (u64(1) << 7)
87 #define LOG_LCD_TFT (u64(1) << 8)
88 #define LOG_LCD_STN (u64(1) << 9)
89 #define LOG_CLKPOW (u64(1) << 10)
90 #define LOG_MMC (u64(1) << 11)
91 #define LOG_IRQS (u64(1) << 12)
92 #define LOG_IRQ_REGS (u64(1) << 13)
93 #define LOG_FLASH (u64(1) << 14)
94 #define LOG_PWM (u64(1) << 15)
95 #define LOG_PWM_REGS (u64(1) << 16)
96 #define LOG_CAM (u64(1) << 17)
97 #define LOG_DMA (u64(1) << 18)
98 #define LOG_DMA_REQS (u64(1) << 19)
99 #define LOG_DMA_REGS (u64(1) << 20)
100 #define LOG_AC97 (u64(1) << 21)
101 #define LOG_DMA_TIMERS (u64(1) << 22)
102 #define LOG_GPIO (u64(1) << 23)
103 #define LOG_MEMCON (u64(1) << 24)
104 #define LOG_USBHOST (u64(1) << 25)
105 #define LOG_UART (u64(1) << 26)
106 #define LOG_USB (u64(1) << 27)
107 #define LOG_WDT (u64(1) << 28)
108 #define LOG_I2C (u64(1) << 29)
109 #define LOG_I2S (u64(1) << 30)
110 #define LOG_RTC (u64(1) << 31)
111 #define LOG_SDI (u64(1) << 32)
112
113 #define LOG_ALL (LOG_RESET | LOG_ADC | LOG_LCD_DMA | LOG_LCD_TIMER | LOG_LCD_REGS | LOG_SPI | LOG_LCD_CFG | LOG_LCD_TFT | LOG_LCD_STN \
114 | LOG_CLKPOW | LOG_MMC | LOG_IRQS | LOG_IRQ_REGS | LOG_FLASH | LOG_PWM | LOG_PWM_REGS | LOG_CAM | LOG_DMA | LOG_DMA_REQS \
115 | LOG_DMA_REGS | LOG_AC97 | LOG_DMA_TIMERS | LOG_GPIO | LOG_MEMCON | LOG_USBHOST | LOG_UART | LOG_USB \
116 | LOG_WDT | LOG_I2C | LOG_I2S | LOG_RTC | LOG_SDI)
117
118 //#define VERBOSE (LOG_ALL & ~(LOG_FLASH | LOG_UART))
119 #include "logmacro.h"
120
121 /***************************************************************************
122 IMPLEMENTATION
123 ***************************************************************************/
124
125 /* ... */
126
s3c24xx_reset()127 void S3C24_CLASS_NAME::s3c24xx_reset()
128 {
129 LOGMASKED(LOG_RESET, "reset\n");
130 m_cpu->reset();
131 this->reset();
132 }
133
iface_core_pin_r(int pin)134 int S3C24_CLASS_NAME::iface_core_pin_r(int pin)
135 {
136 if (!m_pin_r_cb.isnull())
137 {
138 return (m_pin_r_cb)(pin);
139 }
140 else
141 {
142 return 0;
143 }
144 }
145
146 /* LCD Controller */
147
s3c24xx_lcd_reset()148 void S3C24_CLASS_NAME::s3c24xx_lcd_reset()
149 {
150 memset( &m_lcd.regs, 0, sizeof( m_lcd.regs));
151 #if defined(DEVICE_S3C2410)
152 m_lcd.regs.lcdintmsk = 3;
153 m_lcd.regs.lpcsel = 4;
154 #elif defined(DEVICE_S3C2440)
155 m_lcd.regs.lcdintmsk = 3;
156 m_lcd.regs.tconsel = 0x0F84;
157 #endif
158 m_lcd.vramaddr_cur = m_lcd.vramaddr_max = 0;
159 m_lcd.offsize = 0;
160 m_lcd.pagewidth_cur = m_lcd.pagewidth_max = 0;
161 m_lcd.bppmode = 0;
162 m_lcd.bswp = m_lcd.hwswp = 0;
163 m_lcd.vpos = m_lcd.hpos = 0;
164 m_lcd.framerate = 0;
165 m_lcd.tpal = 0;
166 m_lcd.hpos_min = m_lcd.hpos_max = m_lcd.vpos_min = m_lcd.vpos_max = 0;
167 m_lcd.dma_data = m_lcd.dma_bits = 0;
168 m_lcd.timer->adjust(attotime::never);
169 }
170
s3c24xx_get_color_tft_16(uint16_t data)171 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_tft_16(uint16_t data)
172 {
173 if ((m_lcd.regs.lcdcon5 & (1 << 11)) == 0)
174 {
175 uint8_t r, g, b, i;
176 r = (BITS( data, 15, 11) << 3);
177 g = (BITS( data, 10, 6) << 3);
178 b = (BITS( data, 5, 1) << 3);
179 i = BIT( data, 1) << 2;
180 return rgb_t( r | i, g | i, b | i);
181 }
182 else
183 {
184 uint8_t r, g, b;
185 r = BITS( data, 15, 11) << 3;
186 g = BITS( data, 10, 5) << 2;
187 b = BITS( data, 4, 0) << 3;
188 return rgb_t( r, g, b);
189 }
190 }
191
192 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
193
s3c24xx_get_color_tft_24(uint32_t data)194 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_tft_24(uint32_t data)
195 {
196 uint8_t r, g, b;
197 r = BITS( data, 23, 16);
198 g = BITS( data, 15, 8);
199 b = BITS( data, 7, 0);
200 return rgb_t( r, g, b);
201 }
202
203 #endif
204
s3c24xx_get_color_stn_12(uint16_t data)205 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_stn_12(uint16_t data)
206 {
207 uint8_t r, g, b;
208 r = BITS( data, 11, 8) << 4;
209 g = BITS( data, 7, 4) << 4;
210 b = BITS( data, 3, 0) << 4;
211 return rgb_t( r, g, b);
212 }
213
s3c24xx_get_color_stn_08(uint8_t data)214 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_stn_08( uint8_t data)
215 {
216 uint8_t r, g, b;
217 r = ((m_lcd.regs.redlut >> (BITS( data, 7, 5) << 2)) & 0xF) << 4;
218 g = ((m_lcd.regs.greenlut >> (BITS( data, 4, 2) << 2)) & 0xF) << 4;
219 b = ((m_lcd.regs.bluelut >> (BITS( data, 1, 0) << 2)) & 0xF) << 4;
220 return rgb_t( r, g, b);
221 }
222
s3c24xx_get_color_stn_01(uint8_t data)223 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_stn_01(uint8_t data)
224 {
225 if ((data & 1) == 0)
226 {
227 return rgb_t::black();
228 }
229 else
230 {
231 return rgb_t::white();
232 }
233 }
234
s3c24xx_get_color_stn_02(uint8_t data)235 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_stn_02(uint8_t data)
236 {
237 uint8_t r, g, b;
238 r = g = b = ((m_lcd.regs.bluelut >> (BITS( data, 1, 0) << 2)) & 0xF) << 4;
239 return rgb_t( r, g, b);
240 }
241
s3c24xx_get_color_stn_04(uint8_t data)242 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_stn_04(uint8_t data)
243 {
244 uint8_t r, g, b;
245 r = g = b = BITS( data, 3, 0) << 4;
246 return rgb_t( r, g, b);
247 }
248
s3c24xx_get_color_tpal()249 rgb_t S3C24_CLASS_NAME::s3c24xx_get_color_tpal()
250 {
251 #if defined(DEVICE_S3C2400)
252 return s3c24xx_get_color_tft_16(S3C24XX_TPAL_GET_TPALVAL( m_lcd.tpal));
253 #else
254 return s3c24xx_get_color_tft_24(S3C24XX_TPAL_GET_TPALVAL( m_lcd.tpal));
255 #endif
256 }
257
s3c24xx_lcd_dma_reload()258 void S3C24_CLASS_NAME::s3c24xx_lcd_dma_reload()
259 {
260 m_lcd.vramaddr_cur = m_lcd.regs.lcdsaddr1 << 1;
261 m_lcd.vramaddr_max = ((m_lcd.regs.lcdsaddr1 & 0xFFE00000) | m_lcd.regs.lcdsaddr2) << 1;
262 m_lcd.offsize = BITS( m_lcd.regs.lcdsaddr3, 21, 11);
263 m_lcd.pagewidth_cur = 0;
264 m_lcd.pagewidth_max = BITS( m_lcd.regs.lcdsaddr3, 10, 0);
265 if (m_lcd.pagewidth_max == 0)
266 {
267 if (m_lcd.bppmode == S3C24XX_BPPMODE_STN_12_P)
268 {
269 m_lcd.pagewidth_max = (m_lcd.hpos_max - m_lcd.hpos_min + 1) / 16 * 12;
270 }
271 }
272 LOGMASKED(LOG_LCD_DMA, "LCD - vramaddr %08X %08X offsize %08X pagewidth %08X\n", m_lcd.vramaddr_cur, m_lcd.vramaddr_max, m_lcd.offsize, m_lcd.pagewidth_max);
273 m_lcd.dma_data = 0;
274 m_lcd.dma_bits = 0;
275 }
276
s3c24xx_lcd_dma_init()277 void S3C24_CLASS_NAME::s3c24xx_lcd_dma_init()
278 {
279 m_lcd.bppmode = BITS( m_lcd.regs.lcdcon1, 4, 1);
280 s3c24xx_lcd_dma_reload();
281 m_lcd.bswp = BIT( m_lcd.regs.lcdcon5, 1);
282 m_lcd.hwswp = BIT( m_lcd.regs.lcdcon5, 0);
283 m_lcd.tpal = m_lcd.regs.tpal;
284 LOGMASKED(LOG_LCD_DMA, "LCD - bppmode %d hwswp %d bswp %d\n", m_lcd.bppmode, m_lcd.hwswp, m_lcd.bswp);
285 m_lcd.dma_data = 0;
286 m_lcd.dma_bits = 0;
287 }
288
289 #if 0
290 uint32_t S3C24_CLASS_NAME::s3c24xx_lcd_dma_read()
291 {
292 uint8_t data[4];
293 for (int i = 0; i < 2; i++)
294 {
295 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur + 0);
296 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur + 1);
297 m_lcd.vramaddr_cur += 2;
298 m_lcd.pagewidth_cur++;
299 if (m_lcd.pagewidth_cur >= m_lcd.pagewidth_max)
300 {
301 m_lcd.vramaddr_cur += m_lcd.offsize << 1;
302 m_lcd.pagewidth_cur = 0;
303 }
304 }
305 if (m_lcd.hwswp == 0)
306 {
307 if (m_lcd.bswp == 0)
308 {
309 return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | (data[0] << 0);
310 }
311 else
312 {
313 return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0);
314 }
315 }
316 else
317 {
318 if (m_lcd.bswp == 0)
319 {
320 return (data[1] << 24) | (data[0] << 16) | (data[3] << 8) | (data[2] << 0);
321 }
322 else
323 {
324 return (data[2] << 24) | (data[3] << 16) | (data[0] << 8) | (data[1] << 0);
325 }
326 }
327 }
328 #endif
329
s3c24xx_lcd_dma_read()330 uint32_t S3C24_CLASS_NAME::s3c24xx_lcd_dma_read()
331 {
332 uint8_t data[4];
333 for (int i = 0; i < 2; i++)
334 {
335 if (m_lcd.hwswp == 0)
336 {
337 if (m_lcd.bswp == 0)
338 {
339 if ((m_lcd.vramaddr_cur & 2) == 0)
340 {
341 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur + 3);
342 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur + 2);
343 }
344 else
345 {
346 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur - 1);
347 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur - 2);
348 }
349 }
350 else
351 {
352 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur + 0);
353 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur + 1);
354 }
355 }
356 else
357 {
358 if (m_lcd.bswp == 0)
359 {
360 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur + 1);
361 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur + 0);
362 }
363 else
364 {
365 if ((m_lcd.vramaddr_cur & 2) == 0)
366 {
367 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur + 2);
368 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur + 3);
369 }
370 else
371 {
372 data[i*2+0] = m_cache.read_byte(m_lcd.vramaddr_cur - 2);
373 data[i*2+1] = m_cache.read_byte(m_lcd.vramaddr_cur - 1);
374 }
375 }
376 }
377 m_lcd.vramaddr_cur += 2;
378 m_lcd.pagewidth_cur++;
379 if (m_lcd.pagewidth_cur >= m_lcd.pagewidth_max)
380 {
381 m_lcd.vramaddr_cur += m_lcd.offsize << 1;
382 m_lcd.pagewidth_cur = 0;
383 }
384 }
385 if (m_flags & S3C24XX_INTERFACE_LCD_REVERSE)
386 {
387 return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | (data[0] << 0);
388 }
389 else
390 {
391 return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0);
392 }
393 }
394
s3c24xx_lcd_dma_read_bits(int count)395 uint32_t S3C24_CLASS_NAME::s3c24xx_lcd_dma_read_bits(int count)
396 {
397 uint32_t data;
398 if (count <= m_lcd.dma_bits)
399 {
400 m_lcd.dma_bits -= count;
401 data = BITS( m_lcd.dma_data, 31, 32 - count);
402 m_lcd.dma_data = m_lcd.dma_data << count;
403 }
404 else
405 {
406 if (m_lcd.dma_bits == 0)
407 {
408 if (count == 32)
409 {
410 data = s3c24xx_lcd_dma_read();
411 }
412 else
413 {
414 uint32_t temp = s3c24xx_lcd_dma_read();
415 data = BITS( temp, 31, 32 - count);
416 m_lcd.dma_data = temp << count;
417 m_lcd.dma_bits = 32 - count;
418 }
419 }
420 else
421 {
422 uint32_t temp = s3c24xx_lcd_dma_read();
423 data = (m_lcd.dma_data >> (32 - count)) | BITS( temp, 31, 32 - (count - m_lcd.dma_bits));
424 m_lcd.dma_data = temp << (count - m_lcd.dma_bits);
425 m_lcd.dma_bits = 32 - (count - m_lcd.dma_bits);
426 }
427 }
428 return data;
429 }
430
s3c24xx_lcd_render_tpal()431 void S3C24_CLASS_NAME::s3c24xx_lcd_render_tpal()
432 {
433 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
434 uint32_t color = s3c24xx_get_color_tpal();
435 for (int y = m_lcd.vpos_min; y <= m_lcd.vpos_max; y++)
436 {
437 uint32_t *scanline = &bitmap.pix(y, m_lcd.hpos_min);
438 for (int x = m_lcd.hpos_min; x <= m_lcd.hpos_max; x++)
439 {
440 *scanline++ = color;
441 }
442 }
443 }
444
s3c24xx_lcd_render_stn_01()445 void S3C24_CLASS_NAME::s3c24xx_lcd_render_stn_01()
446 {
447 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
448 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
449 for (int i = 0; i < 4; i++)
450 {
451 uint32_t data = s3c24xx_lcd_dma_read();
452 for (int j = 0; j < 32; j++)
453 {
454 if (m_flags & S3C24XX_INTERFACE_LCD_REVERSE)
455 {
456 *scanline++ = s3c24xx_get_color_stn_01( data & 0x01);
457 data = data >> 1;
458 }
459 else
460 {
461 *scanline++ = s3c24xx_get_color_stn_01((data >> 31) & 0x01);
462 data = data << 1;
463 }
464 m_lcd.hpos++;
465 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 4))
466 {
467 m_lcd.vpos++;
468 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
469 m_lcd.hpos = m_lcd.hpos_min;
470 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
471 }
472 }
473 }
474 }
475
s3c24xx_lcd_render_stn_02()476 void S3C24_CLASS_NAME::s3c24xx_lcd_render_stn_02()
477 {
478 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
479 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
480 for (int i = 0; i < 4; i++)
481 {
482 uint32_t data = s3c24xx_lcd_dma_read();
483 for (int j = 0; j < 16; j++)
484 {
485 *scanline++ = s3c24xx_get_color_stn_02((data >> 30) & 0x03);
486 data = data << 2;
487 m_lcd.hpos++;
488 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 3))
489 {
490 m_lcd.vpos++;
491 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
492 m_lcd.hpos = m_lcd.hpos_min;
493 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
494 }
495 }
496 }
497 }
498
s3c24xx_lcd_render_stn_04()499 void S3C24_CLASS_NAME::s3c24xx_lcd_render_stn_04()
500 {
501 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
502 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
503 for (int i = 0; i < 4; i++)
504 {
505 uint32_t data = s3c24xx_lcd_dma_read();
506 for (int j = 0; j < 8; j++)
507 {
508 *scanline++ = s3c24xx_get_color_stn_04((data >> 28) & 0x0F);
509 data = data << 4;
510 m_lcd.hpos++;
511 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 2))
512 {
513 m_lcd.vpos++;
514 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
515 m_lcd.hpos = m_lcd.hpos_min;
516 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
517 }
518 }
519 }
520 }
521
s3c24xx_lcd_render_stn_08()522 void S3C24_CLASS_NAME::s3c24xx_lcd_render_stn_08()
523 {
524 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
525 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
526 for (int i = 0; i < 4; i++)
527 {
528 uint32_t data = s3c24xx_lcd_dma_read();
529 for (int j = 0; j < 4; j++)
530 {
531 *scanline++ = s3c24xx_get_color_stn_08((data >> 24) & 0xFF);
532 data = data << 8;
533 m_lcd.hpos++;
534 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 1))
535 {
536 m_lcd.vpos++;
537 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
538 m_lcd.hpos = m_lcd.hpos_min;
539 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
540 }
541 }
542 }
543 }
544
s3c24xx_lcd_render_stn_12_p()545 void S3C24_CLASS_NAME::s3c24xx_lcd_render_stn_12_p()
546 {
547 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
548 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
549 for (int i = 0; i < 16; i++)
550 {
551 *scanline++ = s3c24xx_get_color_stn_12(s3c24xx_lcd_dma_read_bits(12));
552 m_lcd.hpos++;
553 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max * 16 / 12))
554 {
555 m_lcd.vpos++;
556 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
557 m_lcd.hpos = m_lcd.hpos_min;
558 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
559 }
560 }
561 }
562
s3c24xx_lcd_render_stn_12_u()563 void S3C24_CLASS_NAME::s3c24xx_lcd_render_stn_12_u() // not tested
564 {
565 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
566 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
567 for (int i = 0; i < 4; i++)
568 {
569 uint32_t data = s3c24xx_lcd_dma_read();
570 for (int j = 0; j < 2; j++)
571 {
572 *scanline++ = s3c24xx_get_color_stn_12((data >> 16) & 0x0FFF);
573 data = data << 16;
574 m_lcd.hpos++;
575 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 0))
576 {
577 m_lcd.vpos++;
578 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
579 m_lcd.hpos = m_lcd.hpos_min;
580 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
581 }
582 }
583 }
584 }
585
s3c24xx_lcd_render_tft_01()586 void S3C24_CLASS_NAME::s3c24xx_lcd_render_tft_01()
587 {
588 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
589 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
590 for (int i = 0; i < 4; i++)
591 {
592 uint32_t data = s3c24xx_lcd_dma_read();
593 for (int j = 0; j < 32; j++)
594 {
595 *scanline++ = m_palette->pen_color((data >> 31) & 0x01);
596 data = data << 1;
597 m_lcd.hpos++;
598 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 4))
599 {
600 m_lcd.vpos++;
601 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
602 m_lcd.hpos = m_lcd.hpos_min;
603 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
604 }
605 }
606 }
607 }
608
s3c24xx_lcd_render_tft_02()609 void S3C24_CLASS_NAME::s3c24xx_lcd_render_tft_02()
610 {
611 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
612 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
613 for (int i = 0; i < 4; i++)
614 {
615 uint32_t data = s3c24xx_lcd_dma_read();
616 for (int j = 0; j < 16; j++)
617 {
618 *scanline++ = m_palette->pen_color((data >> 30) & 0x03);
619 data = data << 2;
620 m_lcd.hpos++;
621 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 3))
622 {
623 m_lcd.vpos++;
624 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
625 m_lcd.hpos = m_lcd.hpos_min;
626 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
627 }
628 }
629 }
630 }
631
s3c24xx_lcd_render_tft_04()632 void S3C24_CLASS_NAME::s3c24xx_lcd_render_tft_04()
633 {
634 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
635 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
636 for (int i = 0; i < 4; i++)
637 {
638 uint32_t data = s3c24xx_lcd_dma_read();
639 for (int j = 0; j < 8; j++)
640 {
641 *scanline++ = m_palette->pen_color((data >> 28) & 0x0F);
642 data = data << 4;
643 m_lcd.hpos++;
644 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 2))
645 {
646 m_lcd.vpos++;
647 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
648 m_lcd.hpos = m_lcd.hpos_min;
649 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
650 }
651 }
652 }
653 }
654
s3c24xx_lcd_render_tft_08()655 void S3C24_CLASS_NAME::s3c24xx_lcd_render_tft_08()
656 {
657 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
658 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
659 for (int i = 0; i < 4; i++)
660 {
661 uint32_t data = s3c24xx_lcd_dma_read();
662 for (int j = 0; j < 4; j++)
663 {
664 *scanline++ = m_palette->pen_color((data >> 24) & 0xFF);
665 data = data << 8;
666 m_lcd.hpos++;
667 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 1))
668 {
669 m_lcd.vpos++;
670 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
671 m_lcd.hpos = m_lcd.hpos_min;
672 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
673 }
674 }
675 }
676 }
677
s3c24xx_lcd_render_tft_16()678 void S3C24_CLASS_NAME::s3c24xx_lcd_render_tft_16()
679 {
680 bitmap_rgb32 &bitmap = *m_lcd.bitmap[0];
681 uint32_t *scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
682 for (int i = 0; i < 4; i++)
683 {
684 uint32_t data = s3c24xx_lcd_dma_read();
685 for (int j = 0; j < 2; j++)
686 {
687 *scanline++ = s3c24xx_get_color_tft_16((data >> 16) & 0xFFFF);
688 data = data << 16;
689 m_lcd.hpos++;
690 if (m_lcd.hpos >= m_lcd.hpos_min + (m_lcd.pagewidth_max << 0))
691 {
692 m_lcd.vpos++;
693 if (m_lcd.vpos > m_lcd.vpos_max) m_lcd.vpos = m_lcd.vpos_min;
694 m_lcd.hpos = m_lcd.hpos_min;
695 scanline = &bitmap.pix(m_lcd.vpos, m_lcd.hpos);
696 }
697 }
698 }
699 }
700
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_lcd_timer_exp)701 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_lcd_timer_exp )
702 {
703 LOGMASKED(LOG_LCD_TIMER, "LCD timer callback\n");
704 m_lcd.vpos = m_screen->vpos();
705 m_lcd.hpos = m_screen->hpos();
706 LOGMASKED(LOG_LCD_TIMER, "LCD - vpos %d hpos %d\n", m_lcd.vpos, m_lcd.hpos);
707 uint32_t tpalen = S3C24XX_TPAL_GET_TPALEN( m_lcd.tpal);
708 if (tpalen == 0)
709 {
710 if (m_lcd.vramaddr_cur >= m_lcd.vramaddr_max)
711 {
712 s3c24xx_lcd_dma_reload();
713 }
714 LOGMASKED(LOG_LCD_TIMER, "LCD - vramaddr %08X\n", m_lcd.vramaddr_cur);
715 while (m_lcd.vramaddr_cur < m_lcd.vramaddr_max)
716 {
717 switch (m_lcd.bppmode)
718 {
719 case S3C24XX_BPPMODE_STN_01: s3c24xx_lcd_render_stn_01(); break;
720 case S3C24XX_BPPMODE_STN_02: s3c24xx_lcd_render_stn_02(); break;
721 case S3C24XX_BPPMODE_STN_04: s3c24xx_lcd_render_stn_04(); break;
722 case S3C24XX_BPPMODE_STN_08: s3c24xx_lcd_render_stn_08(); break;
723 case S3C24XX_BPPMODE_STN_12_P: s3c24xx_lcd_render_stn_12_p(); break;
724 case S3C24XX_BPPMODE_STN_12_U: s3c24xx_lcd_render_stn_12_u(); break;
725 case S3C24XX_BPPMODE_TFT_01: s3c24xx_lcd_render_tft_01(); break;
726 case S3C24XX_BPPMODE_TFT_02: s3c24xx_lcd_render_tft_02(); break;
727 case S3C24XX_BPPMODE_TFT_04: s3c24xx_lcd_render_tft_04(); break;
728 case S3C24XX_BPPMODE_TFT_08: s3c24xx_lcd_render_tft_08(); break;
729 case S3C24XX_BPPMODE_TFT_16: s3c24xx_lcd_render_tft_16(); break;
730 default: LOGMASKED(LOG_LCD_TIMER, "s3c24xx_lcd_timer_exp: bppmode %d not supported\n", m_lcd.bppmode); break;
731 }
732 if ((m_lcd.vpos == m_lcd.vpos_min) && (m_lcd.hpos == m_lcd.hpos_min)) break;
733 }
734 }
735 else
736 {
737 s3c24xx_lcd_render_tpal();
738 }
739 m_lcd.timer->adjust(m_screen->time_until_pos(m_lcd.vpos, m_lcd.hpos));
740 }
741
s3c24xx_video_start()742 void S3C24_CLASS_NAME::s3c24xx_video_start()
743 {
744 m_lcd.bitmap[0] = std::make_unique<bitmap_rgb32>(m_screen->width(), m_screen->height());
745 m_lcd.bitmap[1] = std::make_unique<bitmap_rgb32>(m_screen->width(), m_screen->height());
746
747 m_cpu->space(AS_PROGRAM).cache(m_cache);
748 }
749
bitmap_blend(bitmap_rgb32 & bitmap_dst,bitmap_rgb32 & bitmap_src_1,bitmap_rgb32 & bitmap_src_2)750 void S3C24_CLASS_NAME::bitmap_blend( bitmap_rgb32 &bitmap_dst, bitmap_rgb32 &bitmap_src_1, bitmap_rgb32 &bitmap_src_2)
751 {
752 for (int y = 0; y < bitmap_dst.height(); y++)
753 {
754 uint32_t const *const line0 = &bitmap_src_1.pix(y);
755 uint32_t const *const line1 = &bitmap_src_2.pix(y);
756 uint32_t *const line2 = &bitmap_dst.pix(y);
757 for (int x = 0; x < bitmap_dst.width(); x++)
758 {
759 uint32_t color0 = line0[x];
760 uint32_t color1 = line1[x];
761 uint16_t r0 = (color0 >> 16) & 0x000000ff;
762 uint16_t g0 = (color0 >> 8) & 0x000000ff;
763 uint16_t b0 = (color0 >> 0) & 0x000000ff;
764 uint16_t r1 = (color1 >> 16) & 0x000000ff;
765 uint16_t g1 = (color1 >> 8) & 0x000000ff;
766 uint16_t b1 = (color1 >> 0) & 0x000000ff;
767 uint8_t r = uint8_t((r0 + r1) >> 1);
768 uint8_t g = uint8_t((g0 + g1) >> 1);
769 uint8_t b = uint8_t((b0 + b1) >> 1);
770 line2[x] = (r << 16) | (g << 8) | b;
771 }
772 }
773 }
774
s3c24xx_video_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)775 uint32_t S3C24_CLASS_NAME::s3c24xx_video_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
776 {
777 if (m_lcd.regs.lcdcon1 & (1 << 0))
778 {
779 if (m_lcd.framerate >= 1195)
780 {
781 bitmap_blend( bitmap, *m_lcd.bitmap[0], *m_lcd.bitmap[1]);
782 copybitmap( *m_lcd.bitmap[1], *m_lcd.bitmap[0], 0, 0, 0, 0, cliprect);
783 }
784 else
785 {
786 copybitmap( bitmap, *m_lcd.bitmap[0], 0, 0, 0, 0, cliprect);
787 }
788 s3c24xx_lcd_dma_init();
789 }
790 return 0;
791 }
792
793
s3c24xx_lcd_r(offs_t offset,uint32_t mem_mask)794 uint32_t S3C24_CLASS_NAME::s3c24xx_lcd_r(offs_t offset, uint32_t mem_mask)
795 {
796 uint32_t data = ((uint32_t*)&m_lcd.regs)[offset];
797 switch (offset)
798 {
799 case S3C24XX_LCDCON1:
800 {
801 // make sure line counter is going
802 uint32_t vpos = m_screen->vpos();
803 if (vpos < m_lcd.vpos_min) vpos = m_lcd.vpos_min;
804 if (vpos > m_lcd.vpos_max) vpos = m_lcd.vpos_max;
805 data = (data & ~0xFFFC0000) | ((m_lcd.vpos_max - vpos) << 18);
806 LOGMASKED(LOG_LCD_REGS, "%s: lcd read: LCDCON1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
807 }
808 break;
809 case S3C24XX_LCDCON5:
810 {
811 uint32_t vpos = m_screen->vpos();
812 data = data & ~0x00018000;
813 if (vpos < m_lcd.vpos_min) data = data | 0x00000000;
814 if (vpos > m_lcd.vpos_max) data = data | 0x00018000;
815 // todo: 00 = VSYNC, 01 = BACK Porch, 10 = ACTIVE, 11 = FRONT Porch
816 LOGMASKED(LOG_LCD_REGS, "%s: lcd read: LCDCON5 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
817 }
818 break;
819 }
820 LOGMASKED(LOG_LCD_REGS, "%s: lcd read: %08X = %08X & %08x\n", machine().describe_context(), S3C24XX_BASE_LCD + (offset << 2), data, mem_mask);
821 return data;
822 }
823
s3c24xx_lcd_configure_tft()824 int S3C24_CLASS_NAME::s3c24xx_lcd_configure_tft()
825 {
826 LOGMASKED(LOG_LCD_TFT, "s3c24xx_lcd_configure_tft\n");
827 uint32_t vspw = BITS( m_lcd.regs.lcdcon2, 5, 0);
828 uint32_t vbpd = BITS( m_lcd.regs.lcdcon2, 31, 24);
829 uint32_t lineval = BITS( m_lcd.regs.lcdcon2, 23, 14);
830 uint32_t vfpd = BITS( m_lcd.regs.lcdcon2, 13, 6);
831 uint32_t hspw = BITS( m_lcd.regs.lcdcon4, 7, 0);
832 uint32_t hbpd = BITS( m_lcd.regs.lcdcon3, 25, 19);
833 uint32_t hfpd = BITS( m_lcd.regs.lcdcon3, 7, 0);
834 uint32_t hozval = BITS( m_lcd.regs.lcdcon3, 18, 8);
835 uint32_t clkval = BITS( m_lcd.regs.lcdcon1, 17, 8);
836 uint32_t hclk = s3c24xx_get_hclk();
837 LOGMASKED(LOG_LCD_TFT, "LCD - vspw %d vbpd %d lineval %d vfpd %d hspw %d hbpd %d hfpd %d hozval %d clkval %d hclk %d\n", vspw, vbpd, lineval, vfpd, hspw, hbpd, hfpd, hozval, clkval, hclk);
838
839 double vclk = (double)(hclk / ((clkval + 1) * 2));
840 LOGMASKED(LOG_LCD_TFT, "LCD - vclk %f\n", vclk);
841
842 double framerate = vclk / (((vspw + 1) + (vbpd + 1) + (lineval + 1) + (vfpd + 1)) * ((hspw + 1) + (hbpd + 1) + (hozval + 1) + (hfpd + 1)));
843 LOGMASKED(LOG_LCD_TFT, "LCD - framerate %f\n", framerate);
844 m_lcd.framerate = framerate;
845
846 uint32_t width = (hspw + 1) + (hbpd + 1) + (hozval + 1) + (hfpd + 1);
847 uint32_t height = (vspw + 1) + (vbpd + 1) + (lineval + 1) + (vfpd + 1);
848
849 rectangle visarea;
850 visarea.min_x = (hspw + 1) + (hbpd + 1);
851 visarea.min_y = (vspw + 1) + (vbpd + 1);
852 visarea.max_x = visarea.min_x + (hozval + 1) - 1;
853 visarea.max_y = visarea.min_y + (lineval + 1) - 1;
854 LOGMASKED(LOG_LCD_TFT, "LCD - visarea min_x %d min_y %d max_x %d max_y %d\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y);
855 LOGMASKED(LOG_LCD_TFT, "screen->configure %d %d %f\n", width, height, m_lcd.framerate);
856
857 m_lcd.hpos_min = (hspw + 1) + (hbpd + 1);
858 m_lcd.hpos_max = m_lcd.hpos_min + (hozval + 1) - 1;
859 m_lcd.vpos_min = (vspw + 1) + (vbpd + 1);
860 m_lcd.vpos_max = m_lcd.vpos_min + (lineval + 1) - 1;
861 m_screen->configure(width, height, visarea, HZ_TO_ATTOSECONDS(m_lcd.framerate));
862 return true;
863 }
864
s3c24xx_lcd_configure_stn()865 int S3C24_CLASS_NAME::s3c24xx_lcd_configure_stn()
866 {
867 LOGMASKED(LOG_LCD_STN, "s3c24xx_lcd_configure_stn\n");
868
869 uint32_t pnrmode = BITS( m_lcd.regs.lcdcon1, 6, 5);
870 uint32_t bppmode = BITS( m_lcd.regs.lcdcon1, 4, 1);
871 uint32_t clkval = BITS( m_lcd.regs.lcdcon1, 17, 8);
872 uint32_t lineval = BITS( m_lcd.regs.lcdcon2, 23, 14);
873 uint32_t wdly = BITS( m_lcd.regs.lcdcon3, 20, 19);
874 uint32_t hozval = BITS( m_lcd.regs.lcdcon3, 18, 8);
875 uint32_t lineblank = BITS( m_lcd.regs.lcdcon3, 7, 0);
876 uint32_t wlh = BITS( m_lcd.regs.lcdcon4, 1, 0);
877 uint32_t hclk = s3c24xx_get_hclk();
878 LOGMASKED(LOG_LCD_STN, "LCD - pnrmode %d bppmode %d clkval %d lineval %d wdly %d hozval %d lineblank %d wlh %d hclk %d\n", pnrmode, bppmode, clkval, lineval, wdly, hozval, lineblank, wlh, hclk);
879 if (clkval == 0)
880 {
881 return false;
882 }
883
884 double vclk = (double)(hclk / ((clkval + 0) * 2));
885 LOGMASKED(LOG_LCD_STN, "LCD - vclk %f\n", vclk);
886 double framerate = 1 / (((1 / vclk) * (hozval + 1) + (1 / hclk) * ((1 << (4 + wlh)) + (1 << (4 + wdly)) + (lineblank * 8))) * (lineval + 1));
887 LOGMASKED(LOG_LCD_STN, "LCD - framerate %f\n", framerate);
888 m_lcd.framerate = framerate;
889
890 uint32_t width = 0;
891 switch (pnrmode)
892 {
893 case S3C24XX_PNRMODE_STN_04_SS: width = ((hozval + 1) * 4); break;
894 case S3C24XX_PNRMODE_STN_04_DS: width = ((hozval + 1) * 4); break;
895 case S3C24XX_PNRMODE_STN_08_SS: width = ((hozval + 1) * 8 / 3); break;
896 default: break;
897 }
898
899 uint32_t height = lineval + 1;
900
901 rectangle visarea;
902 visarea.set(0, width - 1, 0, height - 1);
903 LOGMASKED(LOG_LCD_STN, "LCD - visarea min_x %d min_y %d max_x %d max_y %d\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y);
904 LOGMASKED(LOG_LCD_STN, "screen->configure %d %d %f\n", width, height, m_lcd.framerate);
905
906 m_lcd.hpos_min = 0;
907 m_lcd.hpos_max = width - 1;
908 m_lcd.vpos_min = 0;
909 m_lcd.vpos_max = height - 1;
910 m_screen->configure( width, height, visarea, HZ_TO_ATTOSECONDS( m_lcd.framerate));
911 return true;
912 }
913
s3c24xx_lcd_configure()914 int S3C24_CLASS_NAME::s3c24xx_lcd_configure()
915 {
916 LOGMASKED(LOG_LCD_CFG, "s3c24xx_lcd_configure\n");
917 uint32_t bppmode = BITS(m_lcd.regs.lcdcon1, 4, 1);
918 if ((bppmode & (1 << 3)) == 0)
919 {
920 return s3c24xx_lcd_configure_stn();
921 }
922 else
923 {
924 return s3c24xx_lcd_configure_tft();
925 }
926 }
927
s3c24xx_lcd_start()928 void S3C24_CLASS_NAME::s3c24xx_lcd_start()
929 {
930 LOGMASKED(LOG_LCD_CFG, "LCD start\n");
931 if (s3c24xx_lcd_configure())
932 {
933 s3c24xx_lcd_dma_init();
934 m_lcd.timer->adjust(m_screen->time_until_pos(m_lcd.vpos_min, m_lcd.hpos_min));
935 }
936 }
937
s3c24xx_lcd_stop()938 void S3C24_CLASS_NAME::s3c24xx_lcd_stop()
939 {
940 LOGMASKED(LOG_LCD_CFG, "LCD stop\n");
941 m_lcd.timer->adjust(attotime::never);
942 }
943
s3c24xx_lcd_recalc()944 void S3C24_CLASS_NAME::s3c24xx_lcd_recalc()
945 {
946 if (m_lcd.regs.lcdcon1 & (1 << 0))
947 {
948 s3c24xx_lcd_start();
949 }
950 else
951 {
952 s3c24xx_lcd_stop();
953 }
954 }
955
s3c24xx_lcd_w(offs_t offset,uint32_t data,uint32_t mem_mask)956 void S3C24_CLASS_NAME::s3c24xx_lcd_w(offs_t offset, uint32_t data, uint32_t mem_mask)
957 {
958 uint32_t old_value = ((uint32_t*)&m_lcd.regs)[offset];
959 LOGMASKED(LOG_LCD_REGS, "%s: lcd write: %08X = %08X & %08x\n", machine().describe_context(), S3C24XX_BASE_LCD + (offset << 2), data, mem_mask);
960 COMBINE_DATA(&((uint32_t*)&m_lcd.regs)[offset]);
961 switch (offset)
962 {
963 case S3C24XX_LCDCON1 :
964 {
965 if ((old_value & (1 << 0)) != (data & (1 << 0)))
966 {
967 s3c24xx_lcd_recalc();
968 }
969 }
970 break;
971 }
972 }
973
974 /* LCD Palette */
975
s3c24xx_lcd_palette_r(offs_t offset,uint32_t mem_mask)976 uint32_t S3C24_CLASS_NAME::s3c24xx_lcd_palette_r(offs_t offset, uint32_t mem_mask)
977 {
978 uint32_t data = m_lcdpal.regs.data[offset];
979 LOGMASKED(LOG_LCD_REGS, "%s: lcd palette read: %08X = %08X & %08x\n", machine().describe_context(), S3C24XX_BASE_LCDPAL + (offset << 2), data, mem_mask);
980 return data;
981 }
982
s3c24xx_lcd_palette_w(offs_t offset,uint32_t data,uint32_t mem_mask)983 void S3C24_CLASS_NAME::s3c24xx_lcd_palette_w(offs_t offset, uint32_t data, uint32_t mem_mask)
984 {
985 LOGMASKED(LOG_LCD_REGS, "%s: lcd palette write: %08X = %08X & %08x\n", machine().describe_context(), S3C24XX_BASE_LCDPAL + (offset << 2), data, mem_mask);
986 COMBINE_DATA(&m_lcdpal.regs.data[offset]);
987 if (mem_mask != 0xffffffff)
988 {
989 LOGMASKED(LOG_LCD_REGS, "s3c24xx_lcd_palette_w: unknown mask %08x\n", mem_mask);
990 }
991 m_palette->set_pen_color( offset, s3c24xx_get_color_tft_16(data & 0xFFFF));
992 }
993
994 /* Clock & Power Management */
995
s3c24xx_clkpow_reset()996 void S3C24_CLASS_NAME::s3c24xx_clkpow_reset()
997 {
998 memset( &m_clkpow.regs, 0, sizeof(m_clkpow.regs));
999 #if defined(DEVICE_S3C2400)
1000 m_clkpow.regs.locktime = 0x00FFFFFF;
1001 m_clkpow.regs.mpllcon = 0x0005C080;
1002 m_clkpow.regs.upllcon = 0x00028080;
1003 m_clkpow.regs.clkcon = 0x0000FFF8;
1004 #elif defined(DEVICE_S3C2410)
1005 m_clkpow.regs.locktime = 0x00FFFFFF;
1006 m_clkpow.regs.mpllcon = 0x0005C080;
1007 m_clkpow.regs.upllcon = 0x00028080;
1008 m_clkpow.regs.clkcon = 0x0007FFF0;
1009 #elif defined(DEVICE_S3C2440)
1010 m_clkpow.regs.locktime = 0xFFFFFFFF;
1011 m_clkpow.regs.mpllcon = 0x00096030;
1012 m_clkpow.regs.upllcon = 0x0004D030;
1013 m_clkpow.regs.clkcon = 0x00FFFFF0;
1014 #endif
1015 m_clkpow.regs.clkslow = 4;
1016 }
1017
s3c24xx_get_fclk()1018 uint32_t S3C24_CLASS_NAME::s3c24xx_get_fclk()
1019 {
1020 uint32_t mpllcon, clkslow, mdiv, pdiv, sdiv, fclk;
1021 double temp1, temp2;
1022 mpllcon = m_clkpow.regs.mpllcon;
1023 mdiv = BITS( mpllcon, 19, 12);
1024 pdiv = BITS( mpllcon, 9, 4);
1025 sdiv = BITS( mpllcon, 1, 0);
1026 #if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
1027 temp1 = 1 * (mdiv + 8) * (double)clock();
1028 #else
1029 temp1 = 2 * (mdiv + 8) * (double)clock();
1030 #endif
1031 temp2 = (double)((pdiv + 2) * (1 << sdiv));
1032 fclk = (uint32_t)(temp1 / temp2);
1033 clkslow = m_clkpow.regs.clkslow;
1034 if (BIT(clkslow, 4) == 1)
1035 {
1036 uint32_t slow_val = BITS( clkslow, 2, 0);
1037 if (slow_val > 0)
1038 {
1039 fclk = fclk / (2 * slow_val);
1040 }
1041 }
1042 return fclk;
1043 }
1044
s3c24xx_get_hclk()1045 uint32_t S3C24_CLASS_NAME::s3c24xx_get_hclk()
1046 {
1047 #if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
1048 return s3c24xx_get_fclk() / (BIT(m_clkpow.regs.clkdivn, 1) + 1);
1049 #else
1050 switch (BITS(m_clkpow.regs.clkdivn, 2, 1))
1051 {
1052 case 0: return s3c24xx_get_fclk() / 1;
1053 case 1: return s3c24xx_get_fclk() / 2;
1054 case 2: return s3c24xx_get_fclk() / (4 * (BIT(m_clkpow.regs.camdivn, 9) + 1));
1055 case 3: return s3c24xx_get_fclk() / (3 * (BIT(m_clkpow.regs.camdivn, 8) + 1));
1056 }
1057 return 0;
1058 #endif
1059 }
1060
s3c24xx_get_pclk()1061 uint32_t S3C24_CLASS_NAME::s3c24xx_get_pclk()
1062 {
1063 return s3c24xx_get_hclk() / (1 << BIT(m_clkpow.regs.clkdivn, 0));
1064 }
1065
s3c24xx_clkpow_r(offs_t offset,uint32_t mem_mask)1066 uint32_t S3C24_CLASS_NAME::s3c24xx_clkpow_r(offs_t offset, uint32_t mem_mask)
1067 {
1068 uint32_t data = ((uint32_t*)&m_clkpow.regs)[offset];
1069 LOGMASKED(LOG_CLKPOW, "%s: clock/power read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_CLKPOW + (offset << 2), data, mem_mask);
1070 return data;
1071 }
1072
s3c24xx_clkpow_w(offs_t offset,uint32_t data,uint32_t mem_mask)1073 void S3C24_CLASS_NAME::s3c24xx_clkpow_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1074 {
1075 const uint32_t old = ((uint32_t*)&m_clkpow.regs)[offset];
1076 COMBINE_DATA(&((uint32_t*)&m_clkpow.regs)[offset]);
1077 switch (offset)
1078 {
1079 case S3C24XX_MPLLCON:
1080 LOGMASKED(LOG_CLKPOW, "%s: clock/power write: MPLLCON = %08x & %08x - fclk %d hclk %d pclk %d\n", machine().describe_context(), data, mem_mask, s3c24xx_get_fclk(), s3c24xx_get_hclk(), s3c24xx_get_pclk());
1081 m_cpu->set_unscaled_clock(s3c24xx_get_fclk() * CLOCK_MULTIPLIER);
1082 break;
1083 case S3C24XX_CLKSLOW:
1084 LOGMASKED(LOG_CLKPOW, "%s: clock/power write: CLKSLOW = %08x & %08x - fclk %d hclk %d pclk %d\n", machine().describe_context(), data, mem_mask, s3c24xx_get_fclk(), s3c24xx_get_hclk(), s3c24xx_get_pclk());
1085 m_cpu->set_unscaled_clock(s3c24xx_get_fclk() * CLOCK_MULTIPLIER);
1086 break;
1087 case S3C24XX_CLKCON:
1088 LOGMASKED(LOG_CLKPOW, "%s: clock/power write: CLKCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1089 if (BIT(data, 2) && !BIT(old, 2))
1090 {
1091 m_cpu->suspend(SUSPEND_REASON_HALT, 1);
1092 }
1093 break;
1094 default:
1095 LOGMASKED(LOG_CLKPOW, "%s: clock/power write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_CLKPOW + (offset << 2), data, mem_mask);
1096 }
1097 }
1098
1099 /* Interrupt Controller */
1100
s3c24xx_irq_reset()1101 void S3C24_CLASS_NAME::s3c24xx_irq_reset()
1102 {
1103 memset(&m_irq.regs, 0, sizeof(m_irq.regs));
1104 m_irq.line_irq = m_irq.line_fiq = CLEAR_LINE;
1105 m_irq.regs.intmsk = 0xFFFFFFFF;
1106 m_irq.regs.priority = 0x7F;
1107 #if defined(DEVICE_S3C2410)
1108 m_irq.regs.intsubmsk = 0x07FF;
1109 #elif defined(DEVICE_S3C2440)
1110 m_irq.regs.intsubmsk = 0xFFFF;
1111 #endif
1112 }
1113
s3c24xx_check_pending_irq()1114 void S3C24_CLASS_NAME::s3c24xx_check_pending_irq()
1115 {
1116 uint32_t temp;
1117 // normal irq
1118
1119 if ((m_irq.regs.intpnd == 0) && (m_irq.regs.intoffset == 0)) // without this "touryuu" crashes
1120 {
1121 temp = (m_irq.regs.srcpnd & ~m_irq.regs.intmsk) & ~m_irq.regs.intmod;
1122 if (temp != 0)
1123 {
1124 uint32_t int_type = 0;
1125 LOGMASKED(LOG_IRQS, "IRQ: srcpnd %08X intmsk %08X intmod %08X\n", m_irq.regs.srcpnd, m_irq.regs.intmsk, m_irq.regs.intmod);
1126 while ((temp & 1) == 0)
1127 {
1128 int_type++;
1129 temp = temp >> 1;
1130 }
1131 LOGMASKED(LOG_IRQS, "IRQ: intpnd set bit %d\n", int_type);
1132 m_irq.regs.intpnd |= (1 << int_type);
1133 m_irq.regs.intoffset = int_type;
1134 if (m_irq.line_irq != ASSERT_LINE)
1135 {
1136 LOGMASKED(LOG_IRQS, "triggering IRQ line\n");
1137 m_cpu->resume(SUSPEND_REASON_HALT);
1138 m_cpu->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE);
1139 m_irq.line_irq = ASSERT_LINE;
1140 }
1141 }
1142 else
1143 {
1144 if (m_irq.line_irq != CLEAR_LINE)
1145 {
1146 LOGMASKED(LOG_IRQS, "IRQ: srcpnd %08X intmsk %08X intmod %08X\n", m_irq.regs.srcpnd, m_irq.regs.intmsk, m_irq.regs.intmod);
1147 LOGMASKED(LOG_IRQS, "clearing IRQ line\n");
1148 m_cpu->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE);
1149 m_irq.line_irq = CLEAR_LINE;
1150 }
1151 }
1152 }
1153
1154 // fast irq
1155 temp = (m_irq.regs.srcpnd & ~m_irq.regs.intmsk) & m_irq.regs.intmod;
1156 if (temp != 0)
1157 {
1158 uint32_t int_type = 0;
1159 while ((temp & 1) == 0)
1160 {
1161 int_type++;
1162 temp = temp >> 1;
1163 }
1164 if (m_irq.line_fiq != ASSERT_LINE)
1165 {
1166 LOGMASKED(LOG_IRQS, "asserting FIQ line\n");
1167 m_cpu->resume(SUSPEND_REASON_HALT);
1168 m_cpu->set_input_line(ARM7_FIRQ_LINE, ASSERT_LINE);
1169 m_irq.line_fiq = ASSERT_LINE;
1170 }
1171 }
1172 else
1173 {
1174 if (m_irq.line_fiq != CLEAR_LINE)
1175 {
1176 LOGMASKED(LOG_IRQS, "clearing FIQ line\n");
1177 m_cpu->set_input_line(ARM7_FIRQ_LINE, CLEAR_LINE);
1178 m_irq.line_fiq = CLEAR_LINE;
1179 }
1180 }
1181 }
1182
s3c24xx_request_irq(uint32_t int_type)1183 void S3C24_CLASS_NAME::s3c24xx_request_irq(uint32_t int_type)
1184 {
1185 LOGMASKED(LOG_IRQS, "request irq %d\n", int_type);
1186 m_irq.regs.srcpnd |= (1 << int_type);
1187 s3c24xx_check_pending_irq();
1188 }
1189
1190 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1191
s3c24xx_check_pending_subirq()1192 void S3C24_CLASS_NAME::s3c24xx_check_pending_subirq()
1193 {
1194 uint32_t temp = m_irq.regs.subsrcpnd & ~m_irq.regs.intsubmsk;
1195 if (temp != 0)
1196 {
1197 uint32_t int_type = 0;
1198 while ((temp & 1) == 0)
1199 {
1200 int_type++;
1201 temp = temp >> 1;
1202 }
1203 s3c24xx_request_irq( MAP_SUBINT_TO_INT[int_type]);
1204 }
1205 }
1206
s3c24xx_request_subirq(uint32_t int_type)1207 ATTR_UNUSED void S3C24_CLASS_NAME::s3c24xx_request_subirq( uint32_t int_type)
1208 {
1209 LOGMASKED(LOG_IRQS, "request subirq %d\n", int_type);
1210 m_irq.regs.subsrcpnd |= (1 << int_type);
1211 s3c24xx_check_pending_subirq();
1212 }
1213
s3c24xx_check_pending_eint()1214 void S3C24_CLASS_NAME::s3c24xx_check_pending_eint()
1215 {
1216 uint32_t temp = m_gpio.regs.eintpend & ~m_gpio.regs.eintmask;
1217 if (temp != 0)
1218 {
1219 uint32_t int_type = 0;
1220 while ((temp & 1) == 0)
1221 {
1222 int_type++;
1223 temp = temp >> 1;
1224 }
1225 if (int_type < 8)
1226 {
1227 s3c24xx_request_irq(S3C24XX_INT_EINT4_7);
1228 }
1229 else
1230 {
1231 s3c24xx_request_irq(S3C24XX_INT_EINT8_23);
1232 }
1233 }
1234 }
1235
s3c24xx_request_eint(uint32_t number)1236 ATTR_UNUSED void S3C24_CLASS_NAME::s3c24xx_request_eint(uint32_t number)
1237 {
1238 LOGMASKED(LOG_IRQS, "request external interrupt %d\n", number);
1239 if (number < 4)
1240 {
1241 s3c24xx_request_irq( S3C24XX_INT_EINT0 + number);
1242 }
1243 else
1244 {
1245 m_gpio.regs.eintpend |= (1 << number);
1246 s3c24xx_check_pending_eint();
1247 }
1248 }
1249
1250 #endif
1251
s3c24xx_irq_r(offs_t offset,uint32_t mem_mask)1252 uint32_t S3C24_CLASS_NAME::s3c24xx_irq_r(offs_t offset, uint32_t mem_mask)
1253 {
1254 const uint32_t data = ((uint32_t*)&m_irq.regs)[offset];
1255 switch (offset)
1256 {
1257 case S3C24XX_SRCPND:
1258 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: SRCPND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1259 break;
1260 case S3C24XX_INTMOD:
1261 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: INTMOD = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1262 break;
1263 case S3C24XX_INTMSK:
1264 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: INTMSK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1265 break;
1266 case S3C24XX_PRIORITY:
1267 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: PRIORITY = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1268 break;
1269 case S3C24XX_INTPND:
1270 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: INTPND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1271 break;
1272 case S3C24XX_INTOFFSET:
1273 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: INTOFFSET = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1274 break;
1275 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1276 case S3C24XX_SUBSRCPND:
1277 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: SUBSRCPND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1278 break;
1279 case S3C24XX_INTSUBMSK:
1280 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: INTSUBMSK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1281 break;
1282 #endif
1283 default:
1284 LOGMASKED(LOG_IRQ_REGS, "%s: irq read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_INT + (offset << 2), data, mem_mask);
1285 break;
1286 }
1287 return data;
1288 }
1289
s3c24xx_irq_w(offs_t offset,uint32_t data,uint32_t mem_mask)1290 void S3C24_CLASS_NAME::s3c24xx_irq_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1291 {
1292 uint32_t old_value = ((uint32_t*)&m_irq.regs)[offset];
1293 COMBINE_DATA(&((uint32_t*)&m_irq.regs)[offset]);
1294 switch (offset)
1295 {
1296 case S3C24XX_SRCPND:
1297 LOGMASKED(LOG_IRQ_REGS, "%s: irq write: SRCPND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1298 m_irq.regs.srcpnd = (old_value & ~data); // clear only the bit positions of SRCPND corresponding to those set to one in the data
1299 m_irq.regs.intoffset = 0; // "This bit can be cleared automatically by clearing SRCPND and INTPND."
1300 s3c24xx_check_pending_irq();
1301 break;
1302 case S3C24XX_INTMSK:
1303 LOGMASKED(LOG_IRQ_REGS, "%s: irq write: INTMSK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1304 s3c24xx_check_pending_irq();
1305 break;
1306 case S3C24XX_INTPND:
1307 LOGMASKED(LOG_IRQ_REGS, "%s: irq write: INTPND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1308 m_irq.regs.intpnd = (old_value & ~data); // clear only the bit positions of INTPND corresponding to those set to one in the data
1309 m_irq.regs.intoffset = 0; // "This bit can be cleared automatically by clearing SRCPND and INTPND."
1310 s3c24xx_check_pending_irq();
1311 break;
1312 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1313 case S3C24XX_SUBSRCPND:
1314 LOGMASKED(LOG_IRQ_REGS, "%s: irq write: SUBSRCPND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1315 m_irq.regs.subsrcpnd = (old_value & ~data); // clear only the bit positions of SRCPND corresponding to those set to one in the data
1316 s3c24xx_check_pending_subirq();
1317 break;
1318 case S3C24XX_INTSUBMSK:
1319 LOGMASKED(LOG_IRQ_REGS, "%s: irq write: INTSUBMSK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1320 s3c24xx_check_pending_subirq();
1321 break;
1322 #endif
1323 default:
1324 LOGMASKED(LOG_IRQ_REGS, "%s: irq write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_INT + (offset << 2), data, mem_mask);
1325 break;
1326 }
1327 }
1328
1329 /* PWM Timer */
1330
s3c24xx_pwm_r(offs_t offset,uint32_t mem_mask)1331 uint32_t S3C24_CLASS_NAME::s3c24xx_pwm_r(offs_t offset, uint32_t mem_mask)
1332 {
1333 uint32_t data = ((uint32_t*)&m_pwm.regs)[offset];
1334 switch (offset)
1335 {
1336 case pwm_t::TCNTO0:
1337 data = (data & ~0x0000FFFF) | m_pwm.calc_observation(0);
1338 LOGMASKED(LOG_PWM_REGS, "%s: pwm read: TCNTO0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1339 break;
1340 case pwm_t::TCNTO1:
1341 data = (data & ~0x0000FFFF) | m_pwm.calc_observation(1);
1342 LOGMASKED(LOG_PWM_REGS, "%s: pwm read: TCNTO1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1343 break;
1344 case pwm_t::TCNTO2:
1345 data = (data & ~0x0000FFFF) | m_pwm.calc_observation(2);
1346 LOGMASKED(LOG_PWM_REGS, "%s: pwm read: TCNTO2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1347 break;
1348 case pwm_t::TCNTO3:
1349 data = (data & ~0x0000FFFF) | m_pwm.calc_observation(3);
1350 LOGMASKED(LOG_PWM_REGS, "%s: pwm read: TCNTO3 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1351 break;
1352 case pwm_t::TCNTO4:
1353 data = (data & ~0x0000FFFF) | m_pwm.calc_observation(4);
1354 LOGMASKED(LOG_PWM_REGS, "%s: pwm read: TCNTO4 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1355 break;
1356 default:
1357 LOGMASKED(LOG_PWM_REGS, "%s: pwm read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_PWM + (offset << 2), data, mem_mask);
1358 }
1359 return data;
1360 }
1361
s3c24xx_pwm_start(int timer)1362 void S3C24_CLASS_NAME::s3c24xx_pwm_start(int timer)
1363 {
1364 static constexpr int mux_table[] = { 2, 4, 8, 16 };
1365 static constexpr int prescaler_shift[] = { 0, 0, 8, 8, 8 };
1366 static constexpr int mux_shift[] = { 0, 4, 8, 12, 16 };
1367 uint32_t cnt, cmp, auto_reload;
1368 double freq, hz;
1369 LOGMASKED(LOG_PWM, "PWM %d start\n", timer);
1370 uint32_t pclk = s3c24xx_get_pclk();
1371 uint32_t prescaler = (m_pwm.regs.tcfg0 >> prescaler_shift[timer]) & 0xFF;
1372 uint32_t mux = (m_pwm.regs.tcfg1 >> mux_shift[timer]) & 0x0F;
1373 if (mux < 4)
1374 {
1375 freq = (double)pclk / (prescaler + 1) / mux_table[mux];
1376 }
1377 else
1378 {
1379 // todo
1380 freq = (double)pclk / (prescaler + 1) / 1;
1381 }
1382 switch (timer)
1383 {
1384 case 0:
1385 cnt = BITS(m_pwm.regs.tcntb0, 15, 0);
1386 cmp = BITS(m_pwm.regs.tcmpb0, 15, 0);
1387 auto_reload = BIT(m_pwm.regs.tcon, 3);
1388 break;
1389 case 1:
1390 cnt = BITS(m_pwm.regs.tcntb1, 15, 0);
1391 cmp = BITS(m_pwm.regs.tcmpb1, 15, 0);
1392 auto_reload = BIT(m_pwm.regs.tcon, 11);
1393 break;
1394 case 2:
1395 cnt = BITS(m_pwm.regs.tcntb2, 15, 0);
1396 cmp = BITS(m_pwm.regs.tcmpb2, 15, 0);
1397 auto_reload = BIT(m_pwm.regs.tcon, 15);
1398 break;
1399 case 3:
1400 cnt = BITS(m_pwm.regs.tcntb3, 15, 0);
1401 cmp = BITS(m_pwm.regs.tcmpb3, 15, 0);
1402 auto_reload = BIT(m_pwm.regs.tcon, 19);
1403 break;
1404 case 4:
1405 cnt = BITS(m_pwm.regs.tcntb4, 15, 0);
1406 cmp = 0;
1407 auto_reload = BIT(m_pwm.regs.tcon, 22);
1408 break;
1409 default:
1410 cnt = cmp = auto_reload = 0;
1411 break;
1412 }
1413 // hz = freq / (cnt - cmp + 1);
1414 if (cnt < 2)
1415 {
1416 hz = freq;
1417 }
1418 else
1419 {
1420 hz = freq / cnt;
1421 }
1422 LOGMASKED(LOG_PWM, "PWM %d - pclk=%d prescaler=%d div=%d freq=%f cnt=%d cmp=%d auto_reload=%d hz=%f\n", timer, pclk, prescaler, mux_table[mux], freq, cnt, cmp, auto_reload, hz);
1423 m_pwm.cnt[timer] = cnt;
1424 m_pwm.cmp[timer] = cmp;
1425 m_pwm.freq[timer] = freq;
1426 if (auto_reload)
1427 {
1428 m_pwm.timer[timer]->adjust(attotime::from_hz(hz), timer, attotime::from_hz(hz));
1429 }
1430 else
1431 {
1432 m_pwm.timer[timer]->adjust(attotime::from_hz(hz), timer);
1433 }
1434 }
1435
s3c24xx_pwm_stop(int timer)1436 void S3C24_CLASS_NAME::s3c24xx_pwm_stop(int timer)
1437 {
1438 LOGMASKED(LOG_PWM, "PWM %d stop\n", timer);
1439 m_pwm.timer[timer]->adjust(attotime::never);
1440 }
1441
s3c24xx_pwm_recalc(int timer)1442 void S3C24_CLASS_NAME::s3c24xx_pwm_recalc(int timer)
1443 {
1444 static constexpr int tcon_shift[] = { 0, 8, 12, 16, 20 };
1445 if (m_pwm.regs.tcon & (1 << tcon_shift[timer]))
1446 {
1447 s3c24xx_pwm_start(timer);
1448 }
1449 else
1450 {
1451 s3c24xx_pwm_stop(timer);
1452 }
1453 }
1454
s3c24xx_pwm_w(offs_t offset,uint32_t data,uint32_t mem_mask)1455 void S3C24_CLASS_NAME::s3c24xx_pwm_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1456 {
1457 uint32_t const old_value = ((uint32_t*)&m_pwm.regs)[offset];
1458 COMBINE_DATA(&((uint32_t*)&m_pwm.regs)[offset]);
1459 switch (offset)
1460 {
1461 case pwm_t::TCON:
1462 LOGMASKED(LOG_PWM_REGS, "%s: pwm write: TCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1463 if (BIT(data ^ old_value, 0))
1464 {
1465 s3c24xx_pwm_recalc(0);
1466 }
1467 if (BIT(data ^ old_value, 8))
1468 {
1469 s3c24xx_pwm_recalc(1);
1470 }
1471 if (BIT(data ^ old_value, 12))
1472 {
1473 s3c24xx_pwm_recalc(2);
1474 }
1475 if (BIT(data ^ old_value, 16))
1476 {
1477 s3c24xx_pwm_recalc(3);
1478 }
1479 if (BIT(data ^ old_value, 20))
1480 {
1481 s3c24xx_pwm_recalc(4);
1482 }
1483 break;
1484 default:
1485 LOGMASKED(LOG_PWM_REGS, "%s: pwm write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_PWM + (offset << 2), data, mem_mask);
1486 break;
1487 }
1488 }
1489
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_pwm_timer_exp)1490 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_pwm_timer_exp )
1491 {
1492 int ch = param;
1493 static constexpr int ch_int[] = { S3C24XX_INT_TIMER0, S3C24XX_INT_TIMER1, S3C24XX_INT_TIMER2, S3C24XX_INT_TIMER3, S3C24XX_INT_TIMER4 };
1494 LOGMASKED(LOG_PWM, "PWM %d timer callback\n", ch);
1495 if (BITS(m_pwm.regs.tcfg1, 23, 20) == (ch + 1))
1496 {
1497 s3c24xx_dma_request_pwm();
1498 }
1499 else
1500 {
1501 s3c24xx_request_irq(ch_int[ch]);
1502 }
1503 }
1504
1505 /* DMA */
1506
s3c24xx_dma_reset()1507 void S3C24_CLASS_NAME::s3c24xx_dma_reset()
1508 {
1509 for (dma_t &dma : m_dma)
1510 {
1511 memset(&dma.regs, 0, sizeof(dma.regs));
1512 dma.timer->adjust(attotime::never);
1513 }
1514 }
1515
s3c24xx_dma_reload(int ch)1516 void S3C24_CLASS_NAME::s3c24xx_dma_reload(int ch)
1517 {
1518 dma_regs_t *regs = &m_dma[ch].regs;
1519 regs->dstat = S3C24XX_DSTAT_SET_CURR_TC(regs->dstat, S3C24XX_DCON_GET_TC(regs->dcon));
1520 regs->dcsrc = S3C24XX_DCSRC_SET_CURR_SRC(regs->dcsrc, S3C24XX_DISRC_GET_SADDR(regs->disrc));
1521 regs->dcdst = S3C24XX_DCDST_SET_CURR_DST(regs->dcdst, S3C24XX_DIDST_GET_DADDR(regs->didst));
1522 }
1523
s3c24xx_dma_trigger(int ch)1524 void S3C24_CLASS_NAME::s3c24xx_dma_trigger(int ch)
1525 {
1526 dma_regs_t *regs = &m_dma[ch].regs;
1527 uint32_t curr_tc, curr_src, curr_dst;
1528 address_space &space = m_cpu->space(AS_PROGRAM);
1529 int dsz, inc_src, inc_dst, servmode, tsz;
1530 static constexpr uint32_t ch_int[] = { S3C24XX_INT_DMA0, S3C24XX_INT_DMA1, S3C24XX_INT_DMA2, S3C24XX_INT_DMA3 };
1531 LOGMASKED(LOG_DMA, "DMA %d trigger\n", ch);
1532 curr_tc = S3C24XX_DSTAT_GET_CURR_TC(regs->dstat);
1533 dsz = S3C24XX_DCON_GET_DSZ(regs->dcon);
1534 curr_src = S3C24XX_DCSRC_GET_CURR_SRC(regs->dcsrc);
1535 curr_dst = S3C24XX_DCDST_GET_CURR_DST(regs->dcdst);
1536 servmode = S3C24XX_DCON_GET_SERVMODE(regs->dcon);
1537 tsz = S3C24XX_DCON_GET_TSZ(regs->dcon);
1538 #if defined(DEVICE_S3C2400)
1539 inc_src = BIT(regs->disrc, 29);
1540 inc_dst = BIT(regs->didst, 29);
1541 #else
1542 inc_src = BIT( regs->disrcc, 0);
1543 inc_dst = BIT(regs->didstc, 0);
1544 #endif
1545 LOGMASKED(LOG_DMA, "DMA %d - curr_src %08X curr_dst %08X curr_tc %d dsz %d\n", ch, curr_src, curr_dst, curr_tc, dsz);
1546 while (curr_tc > 0)
1547 {
1548 curr_tc--;
1549 for (int i = 0; i < 1 << (tsz << 1); i++)
1550 {
1551 switch (dsz)
1552 {
1553 case 0: space.write_byte(curr_dst, space.read_byte( curr_src)); break;
1554 case 1: space.write_word(curr_dst, space.read_word( curr_src)); break;
1555 case 2: space.write_dword(curr_dst, space.read_dword( curr_src)); break;
1556 }
1557 if (inc_src == 0) curr_src += (1 << dsz);
1558 if (inc_dst == 0) curr_dst += (1 << dsz);
1559 }
1560 if (servmode == 0) break;
1561 }
1562 regs->dcsrc = S3C24XX_DCSRC_SET_CURR_SRC(regs->dcsrc, curr_src);
1563 regs->dcdst = S3C24XX_DCDST_SET_CURR_DST(regs->dcdst, curr_dst);
1564 regs->dstat = S3C24XX_DSTAT_SET_CURR_TC(regs->dstat, curr_tc);
1565 if (curr_tc == 0)
1566 {
1567 if (S3C24XX_DCON_GET_RELOAD(regs->dcon) == 0)
1568 {
1569 s3c24xx_dma_reload(ch);
1570 }
1571 else
1572 {
1573 regs->dmasktrig &= ~(1 << 1); // clear on/off
1574 }
1575 if (S3C24XX_DCON_GET_INT(regs->dcon) != 0)
1576 {
1577 s3c24xx_request_irq(ch_int[ch]);
1578 }
1579 }
1580 }
1581
s3c24xx_dma_request_iis()1582 void S3C24_CLASS_NAME::s3c24xx_dma_request_iis()
1583 {
1584 dma_regs_t *regs = &m_dma[2].regs;
1585 LOGMASKED(LOG_DMA_REQS, "s3c24xx_dma_request_iis\n");
1586 if ((S3C24XX_DMASKTRIG_GET_ON_OFF(regs->dmasktrig) != 0) && (S3C24XX_DCON_GET_SWHWSEL(regs->dcon) != 0) && (S3C24XX_DCON_GET_HWSRCSEL(regs->dcon) == 0))
1587 s3c24xx_dma_trigger(2);
1588 }
1589
s3c24xx_dma_request_pwm()1590 void S3C24_CLASS_NAME::s3c24xx_dma_request_pwm()
1591 {
1592 LOGMASKED(LOG_DMA_REQS, "s3c24xx_dma_request_pwm\n");
1593 for (int i = 0; i < 4; i++)
1594 {
1595 if (i != 1)
1596 {
1597 dma_regs_t *regs = &m_dma[i].regs;
1598 if ((S3C24XX_DMASKTRIG_GET_ON_OFF(regs->dmasktrig) != 0) && (S3C24XX_DCON_GET_SWHWSEL(regs->dcon) != 0) && (S3C24XX_DCON_GET_HWSRCSEL(regs->dcon) == 3))
1599 {
1600 s3c24xx_dma_trigger(i);
1601 }
1602 }
1603 }
1604 }
1605
s3c24xx_dma_start(int ch)1606 void S3C24_CLASS_NAME::s3c24xx_dma_start(int ch)
1607 {
1608 uint32_t addr_src, addr_dst, tc;
1609 dma_regs_t *regs = &m_dma[ch].regs;
1610 uint32_t dsz, tsz, reload;
1611 int inc_src, inc_dst, _int, servmode, swhwsel, hwsrcsel;
1612 LOGMASKED(LOG_DMA, "DMA %d start\n", ch);
1613 addr_src = S3C24XX_DISRC_GET_SADDR(regs->disrc);
1614 addr_dst = S3C24XX_DIDST_GET_DADDR(regs->didst);
1615 tc = S3C24XX_DCON_GET_TC(regs->dcon);
1616 _int = S3C24XX_DCON_GET_INT(regs->dcon);
1617 servmode = S3C24XX_DCON_GET_SERVMODE(regs->dcon);
1618 hwsrcsel = S3C24XX_DCON_GET_HWSRCSEL(regs->dcon);
1619 swhwsel = S3C24XX_DCON_GET_SWHWSEL(regs->dcon);
1620 reload = S3C24XX_DCON_GET_RELOAD(regs->dcon);
1621 dsz = S3C24XX_DCON_GET_DSZ(regs->dcon);
1622 tsz = S3C24XX_DCON_GET_TSZ(regs->dcon);
1623 #if defined(DEVICE_S3C2400)
1624 inc_src = BIT(regs->disrc, 29);
1625 inc_dst = BIT(regs->didst, 29);
1626 #else
1627 inc_src = BIT(regs->disrcc, 0);
1628 inc_dst = BIT(regs->didstc, 0);
1629 #endif
1630 LOGMASKED(LOG_DMA, "DMA %d - addr_src %08X inc_src %d addr_dst %08X inc_dst %d int %d tsz %d servmode %d hwsrcsel %d swhwsel %d reload %d dsz %d tc %d\n", ch, addr_src, inc_src, addr_dst, inc_dst, _int, tsz, servmode, hwsrcsel, swhwsel, reload, dsz, tc);
1631 LOGMASKED(LOG_DMA, "DMA %d - copy %08X bytes from %08X (%s) to %08X (%s)\n", ch, (tc << dsz) << (tsz << 1), addr_src, inc_src ? "fix" : "inc", addr_dst, inc_dst ? "fix" : "inc");
1632 s3c24xx_dma_reload(ch);
1633 if (swhwsel == 0)
1634 s3c24xx_dma_trigger(ch);
1635 }
1636
s3c24xx_dma_stop(int ch)1637 void S3C24_CLASS_NAME::s3c24xx_dma_stop(int ch)
1638 {
1639 LOGMASKED(LOG_DMA, "DMA %d stop\n", ch);
1640 }
1641
s3c24xx_dma_recalc(int ch)1642 void S3C24_CLASS_NAME::s3c24xx_dma_recalc(int ch)
1643 {
1644 if ((m_dma[ch].regs.dmasktrig & (1 << 1)) != 0)
1645 s3c24xx_dma_start(ch);
1646 else
1647 s3c24xx_dma_stop(ch);
1648 }
1649
s3c24xx_dma_r(uint32_t ch,uint32_t offset)1650 uint32_t S3C24_CLASS_NAME::s3c24xx_dma_r(uint32_t ch, uint32_t offset)
1651 {
1652 static const uint32_t s_bases[4] = { S3C24XX_BASE_DMA_0, S3C24XX_BASE_DMA_1, S3C24XX_BASE_DMA_2, S3C24XX_BASE_DMA_3 };
1653 const uint32_t data = ((uint32_t*)&m_dma[ch].regs)[offset];
1654 LOGMASKED(LOG_DMA_REGS, "%s: dma %d read: %08x = %08x\n", machine().describe_context(), ch, s_bases[ch] + (offset << 2), data);
1655 return data;
1656 }
1657
s3c24xx_dma_w(uint32_t ch,uint32_t offset,uint32_t data,uint32_t mem_mask)1658 void S3C24_CLASS_NAME::s3c24xx_dma_w(uint32_t ch, uint32_t offset, uint32_t data, uint32_t mem_mask)
1659 {
1660 static const uint32_t s_bases[4] = { S3C24XX_BASE_DMA_0, S3C24XX_BASE_DMA_1, S3C24XX_BASE_DMA_2, S3C24XX_BASE_DMA_3 };
1661 uint32_t old_value = ((uint32_t*)&m_dma[ch].regs)[offset];
1662 COMBINE_DATA(&((uint32_t*)&m_dma[ch].regs)[offset]);
1663 switch (offset)
1664 {
1665 case S3C24XX_DCON :
1666 #if 0 // is this code necessary ???
1667 if (BIT(data, 22)) // reload
1668 {
1669 dma_regs_t *regs = &m_dma[ch].regs;
1670 regs->dmasktrig &= ~(1 << 1); // clear on/off
1671 }
1672 #endif
1673 LOGMASKED(LOG_DMA_REGS, "%s: dma %d write: DCON = %08x & %08x\n", machine().describe_context(), ch, data, mem_mask);
1674 break;
1675 case S3C24XX_DMASKTRIG :
1676 LOGMASKED(LOG_DMA_REGS, "%s: dma %d write: DMASKTRIG = %08x & %08x\n", machine().describe_context(), ch, data, mem_mask);
1677 if (BIT(data ^ old_value, 1))
1678 s3c24xx_dma_recalc(ch);
1679 break;
1680 default:
1681 LOGMASKED(LOG_DMA_REGS, "%s: dma %d write: %08x = %08x & %08x\n", machine().describe_context(), ch, s_bases[ch] + (offset << 2), data, mem_mask);
1682 break;
1683 }
1684 }
1685
s3c24xx_dma_0_r(offs_t offset,uint32_t mem_mask)1686 uint32_t S3C24_CLASS_NAME::s3c24xx_dma_0_r(offs_t offset, uint32_t mem_mask)
1687 {
1688 return s3c24xx_dma_r(0, offset);
1689 }
1690
s3c24xx_dma_1_r(offs_t offset,uint32_t mem_mask)1691 uint32_t S3C24_CLASS_NAME::s3c24xx_dma_1_r(offs_t offset, uint32_t mem_mask)
1692 {
1693 return s3c24xx_dma_r(1, offset);
1694 }
1695
s3c24xx_dma_2_r(offs_t offset,uint32_t mem_mask)1696 uint32_t S3C24_CLASS_NAME::s3c24xx_dma_2_r(offs_t offset, uint32_t mem_mask)
1697 {
1698 return s3c24xx_dma_r(2, offset);
1699 }
1700
s3c24xx_dma_3_r(offs_t offset,uint32_t mem_mask)1701 uint32_t S3C24_CLASS_NAME::s3c24xx_dma_3_r(offs_t offset, uint32_t mem_mask)
1702 {
1703 return s3c24xx_dma_r(3, offset);
1704 }
1705
s3c24xx_dma_0_w(offs_t offset,uint32_t data,uint32_t mem_mask)1706 void S3C24_CLASS_NAME::s3c24xx_dma_0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1707 {
1708 s3c24xx_dma_w(0, offset, data, mem_mask);
1709 }
1710
s3c24xx_dma_1_w(offs_t offset,uint32_t data,uint32_t mem_mask)1711 void S3C24_CLASS_NAME::s3c24xx_dma_1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1712 {
1713 s3c24xx_dma_w(1, offset, data, mem_mask);
1714 }
1715
s3c24xx_dma_2_w(offs_t offset,uint32_t data,uint32_t mem_mask)1716 void S3C24_CLASS_NAME::s3c24xx_dma_2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1717 {
1718 s3c24xx_dma_w(2, offset, data, mem_mask);
1719 }
1720
s3c24xx_dma_3_w(offs_t offset,uint32_t data,uint32_t mem_mask)1721 void S3C24_CLASS_NAME::s3c24xx_dma_3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1722 {
1723 s3c24xx_dma_w(3, offset, data, mem_mask);
1724 }
1725
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_dma_timer_exp)1726 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_dma_timer_exp )
1727 {
1728 int ch = param;
1729 LOGMASKED(LOG_DMA_TIMERS, "DMA %d timer callback\n", ch);
1730 }
1731
1732 /* I/O Port */
1733
s3c24xx_gpio_reset()1734 void S3C24_CLASS_NAME::s3c24xx_gpio_reset()
1735 {
1736 memset(&m_gpio.regs, 0, sizeof(m_gpio.regs));
1737 #if defined(DEVICE_S3C2400)
1738 m_gpio.regs.gpacon = 0x0003FFFF;
1739 m_gpio.regs.gpbcon = 0xAAAAAAAA;
1740 m_gpio.regs.gpdup = 0x0620;
1741 m_gpio.regs.gpeup = 0x0003;
1742 #elif defined(DEVICE_S3C2410)
1743 m_gpio.regs.gpacon = 0x007FFFFF;
1744 m_gpio.regs.gpgup = 0xF800;
1745 m_gpio.regs.misccr = 0x00010330;
1746 m_gpio.regs.eintmask = 0x00FFFFF0;
1747 m_gpio.regs.gstatus1 = 0x32410002;
1748 #elif defined(DEVICE_S3C2440)
1749 m_gpio.regs.gpacon = 0x00FFFFFF;
1750 m_gpio.regs.gpgup = 0xFC00;
1751 m_gpio.regs.misccr = 0x00010020;
1752 m_gpio.regs.eintmask = 0x000FFFFF;
1753 m_gpio.regs.gstatus1 = 0x32440001;
1754 #endif
1755 m_gpio.regs.gpdup = 0xF000;
1756 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1757 m_gpio.regs.gstatus2 = 1 << 0; // Boot is caused by power on reset
1758 #endif
1759 }
1760
iface_gpio_port_r(int port,uint32_t mask)1761 uint32_t S3C24_CLASS_NAME::iface_gpio_port_r(int port, uint32_t mask)
1762 {
1763 if (!m_port_r_cb.isnull())
1764 {
1765 // TO CHECK : masking is not done in any of handlers
1766 // devcb do it automatically so guess is masks are not proper right now
1767 // without masking works fine
1768 return (m_port_r_cb)( port ); //, mask);
1769 }
1770 else
1771 {
1772 return 0;
1773 }
1774 }
1775
iface_gpio_port_w(int port,uint32_t mask,uint32_t data)1776 void S3C24_CLASS_NAME::iface_gpio_port_w(int port, uint32_t mask, uint32_t data)
1777 {
1778 if (!m_port_w_cb.isnull())
1779 {
1780 (m_port_w_cb)( port, data, mask );
1781 }
1782 }
1783
s3c24xx_gpio_get_mask(uint32_t con,int val)1784 uint16_t S3C24_CLASS_NAME::s3c24xx_gpio_get_mask( uint32_t con, int val)
1785 {
1786 uint16_t mask = 0;
1787 for (int i = 0; i < 16; i++)
1788 {
1789 if (((con >> (i << 1)) & 3) == val)
1790 mask = mask | (1 << i);
1791 }
1792 return mask;
1793 }
1794
s3c24xx_gpio_r(offs_t offset,uint32_t mem_mask)1795 uint32_t S3C24_CLASS_NAME::s3c24xx_gpio_r(offs_t offset, uint32_t mem_mask)
1796 {
1797 uint32_t data = ((uint32_t*)&m_gpio.regs)[offset];
1798 switch (offset)
1799 {
1800 case S3C24XX_GPADAT :
1801 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_A, 0) & S3C24XX_GPADAT_MASK;
1802 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPADAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1803 break;
1804 case S3C24XX_GPBDAT :
1805 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_B, s3c24xx_gpio_get_mask(m_gpio.regs.gpbcon, 0) & S3C24XX_GPBDAT_MASK) & S3C24XX_GPBDAT_MASK;
1806 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPBDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1807 break;
1808 case S3C24XX_GPCDAT :
1809 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_C, s3c24xx_gpio_get_mask(m_gpio.regs.gpccon, 0) & S3C24XX_GPCDAT_MASK) & S3C24XX_GPCDAT_MASK;
1810 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPCDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1811 break;
1812 case S3C24XX_GPDDAT:
1813 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_D, s3c24xx_gpio_get_mask(m_gpio.regs.gpdcon, 0) & S3C24XX_GPDDAT_MASK) & S3C24XX_GPDDAT_MASK;
1814 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPDDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1815 break;
1816 case S3C24XX_GPEDAT:
1817 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_E, s3c24xx_gpio_get_mask(m_gpio.regs.gpecon, 0) & S3C24XX_GPEDAT_MASK) & S3C24XX_GPEDAT_MASK;
1818 //LOGMASKED(LOG_GPIO, "%s: GPIO read: GPEDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1819 break;
1820 case S3C24XX_GPFDAT:
1821 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_F, s3c24xx_gpio_get_mask(m_gpio.regs.gpfcon, 0) & S3C24XX_GPFDAT_MASK) & S3C24XX_GPFDAT_MASK;
1822 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPFDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1823 break;
1824 case S3C24XX_GPGDAT:
1825 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_G, s3c24xx_gpio_get_mask(m_gpio.regs.gpgcon, 0) & S3C24XX_GPGDAT_MASK) & S3C24XX_GPGDAT_MASK;
1826 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPGDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1827 break;
1828 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1829 case S3C24XX_GPHDAT:
1830 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_H, s3c24xx_gpio_get_mask(m_gpio.regs.gphcon, 0) & S3C24XX_GPHDAT_MASK) & S3C24XX_GPHDAT_MASK;
1831 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPHDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1832 break;
1833 #endif
1834 #if defined(DEVICE_S3C2440)
1835 case S3C24XX_GPJDAT:
1836 data = iface_gpio_port_r( S3C24XX_GPIO_PORT_J, s3c24xx_gpio_get_mask(m_gpio.regs.gpjcon, 0) & S3C24XX_GPJDAT_MASK) & S3C24XX_GPJDAT_MASK;
1837 LOGMASKED(LOG_GPIO, "%s: GPIO read: GPJDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1838 break;
1839 #endif
1840 default:
1841 LOGMASKED(LOG_GPIO, "%s: GPIO read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_GPIO + (offset << 2), data, mem_mask);
1842 break;
1843 }
1844 return data;
1845 }
1846
s3c24xx_gpio_w(offs_t offset,uint32_t data,uint32_t mem_mask)1847 void S3C24_CLASS_NAME::s3c24xx_gpio_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1848 {
1849 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1850 uint32_t old_value = ((uint32_t*)&m_gpio.regs)[offset];
1851 #endif
1852 COMBINE_DATA(&((uint32_t*)&m_gpio.regs)[offset]);
1853 switch (offset)
1854 {
1855 case S3C24XX_GPADAT:
1856 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPADAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1857 iface_gpio_port_w(S3C24XX_GPIO_PORT_A, m_gpio.regs.gpacon ^ 0xFFFFFFFF, data & S3C24XX_GPADAT_MASK);
1858 break;
1859 case S3C24XX_GPBDAT:
1860 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPBDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1861 iface_gpio_port_w(S3C24XX_GPIO_PORT_B, s3c24xx_gpio_get_mask(m_gpio.regs.gpbcon, 1) & S3C24XX_GPBDAT_MASK, data & S3C24XX_GPBDAT_MASK);
1862 break;
1863 case S3C24XX_GPCDAT:
1864 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPCDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1865 iface_gpio_port_w(S3C24XX_GPIO_PORT_C, s3c24xx_gpio_get_mask(m_gpio.regs.gpccon, 1) & S3C24XX_GPCDAT_MASK, data & S3C24XX_GPCDAT_MASK);
1866 break;
1867 case S3C24XX_GPDDAT:
1868 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPDDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1869 iface_gpio_port_w(S3C24XX_GPIO_PORT_D, s3c24xx_gpio_get_mask(m_gpio.regs.gpdcon, 1) & S3C24XX_GPDDAT_MASK, data & S3C24XX_GPDDAT_MASK);
1870 break;
1871 case S3C24XX_GPEDAT:
1872 //LOGMASKED(LOG_GPIO, "%s: GPIO write: GPEDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1873 iface_gpio_port_w(S3C24XX_GPIO_PORT_E, s3c24xx_gpio_get_mask(m_gpio.regs.gpecon, 1) & S3C24XX_GPEDAT_MASK, data & S3C24XX_GPEDAT_MASK);
1874 break;
1875 case S3C24XX_GPFDAT:
1876 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPFDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1877 iface_gpio_port_w(S3C24XX_GPIO_PORT_F, s3c24xx_gpio_get_mask(m_gpio.regs.gpfcon, 1) & S3C24XX_GPFDAT_MASK, data & S3C24XX_GPFDAT_MASK);
1878 break;
1879 case S3C24XX_GPGDAT:
1880 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPGDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1881 iface_gpio_port_w(S3C24XX_GPIO_PORT_G, s3c24xx_gpio_get_mask(m_gpio.regs.gpgcon, 1) & S3C24XX_GPGDAT_MASK, data & S3C24XX_GPGDAT_MASK);
1882 break;
1883 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
1884 case S3C24XX_GPHDAT:
1885 LOGMASKED(LOG_GPIO, "%s: GPIO write: GPHDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1886 iface_gpio_port_w(S3C24XX_GPIO_PORT_H, s3c24xx_gpio_get_mask(m_gpio.regs.gphcon, 1) & S3C24XX_GPHDAT_MASK, data & S3C24XX_GPHDAT_MASK);
1887 break;
1888 case S3C24XX_EINTPEND:
1889 LOGMASKED(LOG_GPIO, "%s: GPIO write: EINTPEND = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1890 m_gpio.regs.eintpend = (old_value & ~data);
1891 s3c24xx_check_pending_eint();
1892 break;
1893 case S3C24XX_EINTMASK:
1894 LOGMASKED(LOG_GPIO, "%s: GPIO write: EINTMASK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1895 s3c24xx_check_pending_eint();
1896 break;
1897 case S3C24XX_GSTATUS2:
1898 LOGMASKED(LOG_GPIO, "%s: GPIO write: GSTATUS2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1899 m_gpio.regs.gstatus2 = (old_value & ~data) & 7; // "The setting is cleared by writing '1' to this bit"
1900 break;
1901 #endif
1902 #if defined(DEVICE_S3C2440)
1903 case S3C24XX_GPJCON:
1904 case S3C24XX_GPJUP:
1905 // Don't log anything, it's really chatty
1906 break;
1907 case S3C24XX_GPJDAT:
1908 //LOGMASKED(LOG_GPIO, "%s: GPIO write: GPJDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1909 iface_gpio_port_w(S3C24XX_GPIO_PORT_J, s3c24xx_gpio_get_mask(m_gpio.regs.gpjcon, 1) & S3C24XX_GPJDAT_MASK, data & S3C24XX_GPJDAT_MASK);
1910 break;
1911 #endif
1912 default:
1913 LOGMASKED(LOG_GPIO, "%s: GPIO write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_GPIO + (offset << 2), data, mem_mask);
1914 break;
1915 }
1916 }
1917
1918 /* Memory Controller */
1919
s3c24xx_memcon_r(offs_t offset,uint32_t mem_mask)1920 uint32_t S3C24_CLASS_NAME::s3c24xx_memcon_r(offs_t offset, uint32_t mem_mask)
1921 {
1922 assert(offset < ARRAY_LENGTH(m_memcon.regs.data));
1923 uint32_t data = m_memcon.regs.data[offset];
1924 LOGMASKED(LOG_MEMCON, "%s: memcon read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_MEMCON + (offset << 2), data, mem_mask);
1925 return data;
1926 }
1927
s3c24xx_memcon_w(offs_t offset,uint32_t data,uint32_t mem_mask)1928 void S3C24_CLASS_NAME::s3c24xx_memcon_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1929 {
1930 LOGMASKED(LOG_MEMCON, "%s: memcon write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_MEMCON + (offset << 2), data, mem_mask);
1931 COMBINE_DATA(&m_memcon.regs.data[offset]);
1932 }
1933
1934 /* USB Host Controller */
1935
s3c24xx_usb_host_r(offs_t offset,uint32_t mem_mask)1936 uint32_t S3C24_CLASS_NAME::s3c24xx_usb_host_r(offs_t offset, uint32_t mem_mask)
1937 {
1938 uint32_t data = m_usbhost.regs.data[offset];
1939 switch (offset)
1940 {
1941 // HcCommandStatus
1942 case 0x08 / 4:
1943 data = data & ~(1 << 0); // [bit 0] HostControllerReset
1944 LOGMASKED(LOG_USBHOST, "%s: USB host read: HcCommandStatus = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1945 break;
1946 // HcPeriodStart
1947 case 0x40 / 4:
1948 // "After a hardware reset, this field is cleared. This is then set by"
1949 // "HCD during the HC initialization. The value is calculated"
1950 // "roughly as 10% off from HcFmInterval.. A typical value will be 3E67h."
1951 data = (data & ~0x00003FFF) | 0x3E67;
1952 LOGMASKED(LOG_USBHOST, "%s: USB host read: HcPeriodStart = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1953 break;
1954 // HcRhDescriptorA
1955 case 0x48 / 4:
1956 data = (data & ~0xFF) | 2; // number of ports
1957 LOGMASKED(LOG_USBHOST, "%s: USB host read: HcRhDescriptorA = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1958 break;
1959 // HcRhStatus
1960 case 0x50 / 4:
1961 data = data & ~(1 << 16); // "The Root Hub does not support the local power status feature; thus, this bit is always read as ?0?."
1962 LOGMASKED(LOG_USBHOST, "%s: USB host read: HcRhStatus = %08x & %08x\n", machine().describe_context(), data, mem_mask);
1963 break;
1964 default:
1965 LOGMASKED(LOG_USBHOST, "%s: USB host read: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
1966 break;
1967 }
1968 return data;
1969 }
1970
s3c24xx_usb_host_w(offs_t offset,uint32_t data,uint32_t mem_mask)1971 void S3C24_CLASS_NAME::s3c24xx_usb_host_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1972 {
1973 LOGMASKED(LOG_USBHOST, "%s: USB host write: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
1974 COMBINE_DATA(&m_usbhost.regs.data[offset]);
1975 }
1976
1977 /* UART */
1978
s3c24xx_uart_r(uint32_t ch,uint32_t offset)1979 uint32_t S3C24_CLASS_NAME::s3c24xx_uart_r(uint32_t ch, uint32_t offset)
1980 {
1981 uint32_t data = ((uint32_t*)&m_uart[ch].regs)[offset];
1982 switch (offset)
1983 {
1984 case uart_t::UTRSTAT:
1985 data = (data & ~0x00000006) | 0x00000004 | 0x00000002; // [bit 2] Transmitter empty / [bit 1] Transmit buffer empty
1986 LOGMASKED(LOG_UART, "%s: UART %d read: UTRSTAT = %08x\n", machine().describe_context(), ch, data);
1987 break;
1988 case uart_t::URXH:
1989 {
1990 uint8_t rxdata = data & 0xFF;
1991 m_uart[ch].regs.utrstat &= ~1; // [bit 0] Receive buffer data ready
1992 LOGMASKED(LOG_UART, "%s: UART %d read: URXH = %08x (%c)\n", machine().describe_context(), ch, data, ((rxdata >= 0x20 && rxdata < 0x7f) ? (char)rxdata : '?'));
1993 }
1994 break;
1995 default:
1996 LOGMASKED(LOG_UART, "%s: UART %d read: %08x = %08x\n", machine().describe_context(), ch, offset << 2, data);
1997 break;
1998 }
1999 return data;
2000 }
2001
s3c24xx_uart_w(uint32_t ch,uint32_t offset,uint32_t data,uint32_t mem_mask)2002 void S3C24_CLASS_NAME::s3c24xx_uart_w(uint32_t ch, uint32_t offset, uint32_t data, uint32_t mem_mask)
2003 {
2004 COMBINE_DATA(&((uint32_t*)&m_uart[ch].regs)[offset]);
2005 switch (offset)
2006 {
2007 case uart_t::UFCON :
2008 m_uart[ch].regs.ufcon &= ~((1 << 2) | (1 << 1)); // bits 1 and 2 are auto-cleared after resetting FIFO
2009 LOGMASKED(LOG_UART, "%s: UART %d write: UFCON = %08x & %08x\n", machine().describe_context(), ch, data, mem_mask);
2010 break;
2011 case uart_t::UTXH :
2012 {
2013 uint8_t txdata = data & 0xFF;
2014 #ifdef UART_PRINTF
2015 printf("%c", (txdata >= 32 && txdata < 128) ? (char)txdata : '?');
2016 #endif
2017 LOGMASKED(LOG_UART, "%s: UART %d write: UTXH = %08x & %08x (%c)\n", machine().describe_context(), ch, data, mem_mask, ((txdata >= 32 && txdata < 128) ? (char)txdata : '?'));
2018 }
2019 break;
2020 default:
2021 LOGMASKED(LOG_UART, "%s: UART %d write: %08x = %08x & %08x\n", machine().describe_context(), ch, offset << 2, data, mem_mask);
2022 break;
2023 }
2024 }
2025
s3c24xx_uart_0_r(offs_t offset,uint32_t mem_mask)2026 uint32_t S3C24_CLASS_NAME::s3c24xx_uart_0_r(offs_t offset, uint32_t mem_mask)
2027 {
2028 return s3c24xx_uart_r(0, offset);
2029 }
2030
s3c24xx_uart_1_r(offs_t offset,uint32_t mem_mask)2031 uint32_t S3C24_CLASS_NAME::s3c24xx_uart_1_r(offs_t offset, uint32_t mem_mask)
2032 {
2033 return s3c24xx_uart_r(1, offset);
2034 }
2035
2036 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2037
s3c24xx_uart_2_r(offs_t offset,uint32_t mem_mask)2038 uint32_t S3C24_CLASS_NAME::s3c24xx_uart_2_r(offs_t offset, uint32_t mem_mask)
2039 {
2040 return s3c24xx_uart_r(2, offset);
2041 }
2042
2043 #endif
2044
s3c24xx_uart_0_w(offs_t offset,uint32_t data,uint32_t mem_mask)2045 void S3C24_CLASS_NAME::s3c24xx_uart_0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2046 {
2047 s3c24xx_uart_w(0, offset, data, mem_mask);
2048 }
2049
s3c24xx_uart_1_w(offs_t offset,uint32_t data,uint32_t mem_mask)2050 void S3C24_CLASS_NAME::s3c24xx_uart_1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2051 {
2052 s3c24xx_uart_w(1, offset, data, mem_mask);
2053 }
2054
2055 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2056
s3c24xx_uart_2_w(offs_t offset,uint32_t data,uint32_t mem_mask)2057 void S3C24_CLASS_NAME::s3c24xx_uart_2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2058 {
2059 s3c24xx_uart_w(2, offset, data, mem_mask);
2060 }
2061
2062 #endif
2063
s3c24xx_uart_fifo_w(int uart,uint8_t data)2064 void S3C24_CLASS_NAME::s3c24xx_uart_fifo_w(int uart, uint8_t data)
2065 {
2066 #if defined(DEVICE_S3C2400)
2067 static const uint32_t s_int_bits[2] = { S3C24XX_INT_URXD0, S3C24XX_INT_URXD1 };
2068 #else
2069 static const uint32_t s_int_bits[3] = { S3C24XX_SUBINT_RXD0, S3C24XX_SUBINT_RXD1, S3C24XX_SUBINT_RXD2 };
2070 #endif
2071
2072 m_uart[uart].regs.urxh = data;
2073 m_uart[uart].regs.utrstat |= 1; // [bit 0] Receive buffer data ready
2074
2075 bool request_irq = true;
2076 if (BIT(m_uart[uart].regs.ufcon, 0))
2077 {
2078 request_irq = false;
2079 }
2080
2081 if (request_irq)
2082 {
2083 #if defined(DEVICE_S3C2400)
2084 s3c24xx_request_irq(s_int_bits[uart]);
2085 #else
2086 s3c24xx_request_subirq(s_int_bits[uart]);
2087 #endif
2088 }
2089 }
2090
2091 /* USB Device */
2092
s3c24xx_usb_device_reset()2093 void S3C24_CLASS_NAME::s3c24xx_usb_device_reset()
2094 {
2095 memset(&m_usbdev.regs, 0, sizeof(m_usbdev.regs));
2096 #if defined(DEVICE_S3C2400)
2097 m_usbdev.regs.data[0x0C/4] = 0x033F;
2098 m_usbdev.regs.data[0x14/4] = 0x000A;
2099 m_usbdev.regs.data[0x24/4] = 0x0001;
2100 m_usbdev.regs.data[0x44/4] = 0x0001;
2101 m_usbdev.regs.data[0x54/4] = 0x0001;
2102 m_usbdev.regs.data[0x64/4] = 0x0001;
2103 m_usbdev.regs.data[0x74/4] = 0x0001;
2104 m_usbdev.regs.data[0xB8/4] = 0x00FF;
2105 #elif defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2106 m_usbdev.regs.data[0x1C/4] = 0xFF;
2107 m_usbdev.regs.data[0x2C/4] = 0x04;
2108 m_usbdev.regs.data[0x40/4] = 0x01;
2109 m_usbdev.regs.data[0x48/4] = 0x20;
2110 #endif
2111 }
2112
s3c24xx_usb_device_r(offs_t offset,uint32_t mem_mask)2113 uint32_t S3C24_CLASS_NAME::s3c24xx_usb_device_r(offs_t offset, uint32_t mem_mask)
2114 {
2115 const uint32_t data = m_usbdev.regs.data[offset];
2116 LOGMASKED(LOG_USB, "%s: USB read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_USBDEV + (offset << 2), data, mem_mask);
2117 return data;
2118 }
2119
s3c24xx_usb_device_w(offs_t offset,uint32_t data,uint32_t mem_mask)2120 void S3C24_CLASS_NAME::s3c24xx_usb_device_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2121 {
2122 LOGMASKED(LOG_USB, "%s: USB read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_USBDEV + (offset << 2), data, mem_mask);
2123 COMBINE_DATA(&m_usbdev.regs.data[offset]);
2124 }
2125
2126 /* Watchdog Timer */
2127
s3c24xx_wdt_r(offs_t offset,uint32_t mem_mask)2128 uint32_t S3C24_CLASS_NAME::s3c24xx_wdt_r(offs_t offset, uint32_t mem_mask)
2129 {
2130 uint32_t data = ((uint32_t*)&m_wdt.regs)[offset];
2131 switch (offset)
2132 {
2133 case wdt_t::WTCNT:
2134 // is wdt active?
2135 if (BIT(m_wdt.regs.wtcon, 5))
2136 {
2137 #if defined(DEVICE_S3C2410)
2138 data = m_wdt.calc_current_count();
2139 #else
2140 data = 0;
2141 #endif
2142 }
2143 LOGMASKED(LOG_WDT, "%s: watchdog read: WTCNT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2144 break;
2145 default:
2146 LOGMASKED(LOG_WDT, "%s: watchdog read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_WDT + (offset << 2), data, mem_mask);
2147 break;
2148 }
2149 return data;
2150 }
2151
s3c24xx_wdt_start()2152 void S3C24_CLASS_NAME::s3c24xx_wdt_start()
2153 {
2154 uint32_t pclk, prescaler, clock;
2155 double freq, hz;
2156 LOGMASKED(LOG_WDT, "WDT start\n");
2157 pclk = s3c24xx_get_pclk();
2158 prescaler = BITS(m_wdt.regs.wtcon, 15, 8);
2159 clock = 16 << BITS(m_wdt.regs.wtcon, 4, 3);
2160 freq = (double)pclk / (prescaler + 1) / clock;
2161 hz = freq / m_wdt.regs.wtcnt;
2162 LOGMASKED(LOG_WDT, "watchdog start: pclk %d prescaler %d clock %d freq %f hz %f\n", pclk, prescaler, clock, freq, hz);
2163 m_wdt.timer->adjust( attotime::from_hz( hz), 0, attotime::from_hz( hz));
2164 #if defined(DEVICE_S3C2410)
2165 m_wdt.freq = freq;
2166 m_wdt.cnt = m_wdt.regs.wtcnt;
2167 #endif
2168 }
2169
s3c24xx_wdt_stop()2170 void S3C24_CLASS_NAME::s3c24xx_wdt_stop()
2171 {
2172 LOGMASKED(LOG_WDT, "watchdog stop\n");
2173 #if defined(DEVICE_S3C2410)
2174 m_wdt.regs.wtcnt = m_wdt.calc_current_count();
2175 #else
2176 m_wdt.regs.wtcnt = 0;
2177 #endif
2178 m_wdt.timer->adjust(attotime::never);
2179 }
2180
s3c24xx_wdt_recalc()2181 void S3C24_CLASS_NAME::s3c24xx_wdt_recalc()
2182 {
2183 if (BIT(m_wdt.regs.wtcon, 5))
2184 s3c24xx_wdt_start();
2185 else
2186 s3c24xx_wdt_stop();
2187 }
2188
s3c24xx_wdt_w(offs_t offset,uint32_t data,uint32_t mem_mask)2189 void S3C24_CLASS_NAME::s3c24xx_wdt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2190 {
2191 uint32_t old_value = ((uint32_t*)&m_wdt.regs)[offset];
2192 COMBINE_DATA(&((uint32_t*)&m_wdt.regs)[offset]);
2193 switch (offset)
2194 {
2195 case wdt_t::WTCON:
2196 LOGMASKED(LOG_WDT, "%s: watchdog write: WTCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2197 if (BIT(data ^ old_value, 5))
2198 s3c24xx_wdt_recalc();
2199 break;
2200 default:
2201 LOGMASKED(LOG_WDT, "%s: watchdog write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_WDT + (offset << 2), data, mem_mask);
2202 break;
2203 }
2204 }
2205
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_wdt_timer_exp)2206 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_wdt_timer_exp )
2207 {
2208 LOGMASKED(LOG_WDT, "WDT timer callback\n");
2209 if (BIT(m_wdt.regs.wtcon, 2))
2210 {
2211 #if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
2212 s3c24xx_request_irq(S3C24XX_INT_WDT);
2213 #else
2214 s3c24xx_request_subirq(S3C24XX_SUBINT_WDT);
2215 #endif
2216 }
2217 if (BIT(m_wdt.regs.wtcon, 0))
2218 {
2219 s3c24xx_reset();
2220 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2221 m_gpio.regs.gstatus2 = 1 << 2; // Watchdog reset
2222 #endif
2223 }
2224 }
2225
2226 /* IIC */
2227
s3c24xx_iic_reset()2228 void S3C24_CLASS_NAME::s3c24xx_iic_reset()
2229 {
2230 memset(&m_iic.regs, 0, sizeof(m_iic.regs));
2231 m_iic.count = 0;
2232 m_iic.timer->adjust(attotime::never);
2233 }
2234
iface_i2c_scl_w(int state)2235 void S3C24_CLASS_NAME::iface_i2c_scl_w( int state)
2236 {
2237 if (!m_scl_w_cb.isnull())
2238 m_scl_w_cb(state);
2239 }
2240
iface_i2c_sda_w(int state)2241 void S3C24_CLASS_NAME::iface_i2c_sda_w(int state)
2242 {
2243 if (!m_sda_w_cb.isnull())
2244 m_sda_w_cb(state);
2245 }
2246
iface_i2c_sda_r()2247 int S3C24_CLASS_NAME::iface_i2c_sda_r()
2248 {
2249 if (!m_sda_r_cb.isnull())
2250 return m_sda_r_cb();
2251 else
2252 return 1;
2253 }
2254
i2c_send_start()2255 void S3C24_CLASS_NAME::i2c_send_start()
2256 {
2257 // FIXME: this needs to sense busy condition and use realistic timing
2258 LOGMASKED(LOG_I2C, "i2c_send_start\n");
2259 iface_i2c_sda_w(1);
2260 iface_i2c_scl_w(1);
2261 iface_i2c_sda_w(0);
2262 iface_i2c_scl_w(0);
2263 }
2264
i2c_send_stop()2265 void S3C24_CLASS_NAME::i2c_send_stop()
2266 {
2267 // FIXME: this needs realistic timing
2268 LOGMASKED(LOG_I2C, "i2c_send_stop\n");
2269 iface_i2c_sda_w(0);
2270 iface_i2c_scl_w(1);
2271 iface_i2c_sda_w(1);
2272 iface_i2c_scl_w(0);
2273 }
2274
i2c_receive_byte(int ack)2275 uint8_t S3C24_CLASS_NAME::i2c_receive_byte(int ack)
2276 {
2277 uint8_t data = 0;
2278 LOGMASKED(LOG_I2C, "i2c_receive_byte ...\n");
2279 iface_i2c_sda_w(1);
2280 for (int i = 0; i < 8; i++)
2281 {
2282 iface_i2c_scl_w( 1);
2283 data = (data << 1) + (iface_i2c_sda_r() ? 1 : 0);
2284 iface_i2c_scl_w( 0);
2285 }
2286 LOGMASKED(LOG_I2C, "recv data %02X\n", data);
2287 LOGMASKED(LOG_I2C, "send ack %d\n", ack);
2288 iface_i2c_sda_w(ack ? 0 : 1);
2289 iface_i2c_scl_w(1);
2290 iface_i2c_scl_w(0);
2291 return data;
2292 }
2293
i2c_send_byte(uint8_t data)2294 int S3C24_CLASS_NAME::i2c_send_byte(uint8_t data)
2295 {
2296 int ack;
2297 LOGMASKED(LOG_I2C, "i2c_send_byte ...\n");
2298 LOGMASKED(LOG_I2C, "send data %02X\n", data);
2299 for (int i = 0; i < 8; i++)
2300 {
2301 iface_i2c_sda_w((data & 0x80) ? 1 : 0);
2302 data = data << 1;
2303 iface_i2c_scl_w(1);
2304 iface_i2c_scl_w(0);
2305 }
2306 iface_i2c_sda_w(1); // ack bit
2307 iface_i2c_scl_w(1);
2308 ack = iface_i2c_sda_r();
2309 LOGMASKED(LOG_I2C, "recv ack %d\n", ack);
2310 iface_i2c_scl_w(0);
2311 return ack;
2312 }
2313
iic_start()2314 void S3C24_CLASS_NAME::iic_start()
2315 {
2316 LOGMASKED(LOG_I2C, "I2C start\n");
2317 i2c_send_start();
2318 int mode_selection = BITS(m_iic.regs.iicstat, 7, 6);
2319 switch (mode_selection)
2320 {
2321 case 2: i2c_send_byte(m_iic.regs.iicds | 0x01); break;
2322 case 3: i2c_send_byte(m_iic.regs.iicds & 0xFE); break;
2323 }
2324 m_iic.timer->adjust( attotime::from_usec( 1));
2325 }
2326
iic_stop()2327 void S3C24_CLASS_NAME::iic_stop()
2328 {
2329 LOGMASKED(LOG_I2C, "IIC stop\n");
2330 i2c_send_stop();
2331 m_iic.timer->adjust(attotime::never);
2332 }
2333
iic_resume()2334 void S3C24_CLASS_NAME::iic_resume()
2335 {
2336 LOGMASKED(LOG_I2C, "IIC resume\n");
2337 int mode_selection = BITS(m_iic.regs.iicstat, 7, 6);
2338 switch (mode_selection)
2339 {
2340 case 2: m_iic.regs.iicds = i2c_receive_byte(BIT(m_iic.regs.iiccon, 7)); break;
2341 case 3: i2c_send_byte(m_iic.regs.iicds & 0xFF); break;
2342 }
2343 m_iic.timer->adjust(attotime::from_usec(1));
2344 }
2345
s3c24xx_iic_r(offs_t offset,uint32_t mem_mask)2346 uint32_t S3C24_CLASS_NAME::s3c24xx_iic_r(offs_t offset, uint32_t mem_mask)
2347 {
2348 uint32_t data = ((uint32_t*)&m_iic.regs)[offset];
2349 switch (offset)
2350 {
2351 case S3C24XX_IICSTAT:
2352 data = data & ~0x0000000F;
2353 LOGMASKED(LOG_I2C, "%s: i2c read: IICSTAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2354 break;
2355 default:
2356 LOGMASKED(LOG_I2C, "%s: i2c read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_IIC + (offset << 2), data, mem_mask);
2357 break;
2358 }
2359 return data;
2360 }
2361
s3c24xx_iic_w(offs_t offset,uint32_t data,uint32_t mem_mask)2362 void S3C24_CLASS_NAME::s3c24xx_iic_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2363 {
2364 uint32_t old_value = ((uint32_t*)&m_iic.regs)[offset];
2365 COMBINE_DATA(&((uint32_t*)&m_iic.regs)[offset]);
2366 switch (offset)
2367 {
2368 case S3C24XX_IICCON:
2369 {
2370 LOGMASKED(LOG_I2C, "%s: i2c write: IICCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2371 #if 0
2372 static constexpr int div_table[] = { 16, 512 };
2373 int transmit_clock_value = (data >> 0) & 0xF;
2374 int tx_clock_source_selection = (data >> 6) & 1;
2375 int enable_interrupt = (data >> 5) & 1;
2376 double clock = (double)s3c24xx_get_pclk() / div_table[tx_clock_source_selection] / (transmit_clock_value + 1);
2377 #endif
2378 int interrupt_pending_flag = BIT(old_value, 4);
2379 if (interrupt_pending_flag != 0)
2380 {
2381 interrupt_pending_flag = BIT(data, 4);
2382 if (interrupt_pending_flag == 0)
2383 {
2384 int start_stop_condition;
2385 start_stop_condition = BIT(m_iic.regs.iicstat, 5);
2386 if (start_stop_condition != 0)
2387 {
2388 if (m_iic.count == 0)
2389 {
2390 iic_start();
2391
2392 }
2393 else
2394 {
2395 iic_resume();
2396 }
2397 }
2398 else
2399 {
2400 iic_stop();
2401 }
2402 }
2403 }
2404 }
2405 break;
2406 case S3C24XX_IICSTAT:
2407 {
2408 LOGMASKED(LOG_I2C, "%s: i2c write: IICSTAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2409 m_iic.count = 0;
2410 int interrupt_pending_flag = BIT(m_iic.regs.iiccon, 4);
2411 if (interrupt_pending_flag == 0)
2412 {
2413 int start_stop_condition = BIT(data, 5);
2414 if (start_stop_condition != 0)
2415 {
2416 if (m_iic.count == 0)
2417 {
2418 iic_start();
2419
2420 }
2421 else
2422 {
2423 iic_resume();
2424 }
2425 }
2426 else
2427 {
2428 iic_stop();
2429 }
2430 }
2431 }
2432 break;
2433 default:
2434 LOGMASKED(LOG_I2C, "%s: i2c write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_IIC + (offset << 2), data, mem_mask);
2435 break;
2436 }
2437 }
2438
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_iic_timer_exp)2439 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_iic_timer_exp )
2440 {
2441 int enable_interrupt;
2442 LOGMASKED(LOG_I2C, "I2C timer callback\n");
2443 m_iic.count++;
2444 enable_interrupt = BIT(m_iic.regs.iiccon, 5);
2445 if (enable_interrupt)
2446 {
2447 m_iic.regs.iiccon |= (1 << 4); // [bit 4] interrupt is pending
2448 s3c24xx_request_irq(S3C24XX_INT_IIC);
2449 }
2450 }
2451
2452 /* IIS */
2453
iface_i2s_data_w(int ch,uint16_t data)2454 void S3C24_CLASS_NAME::iface_i2s_data_w(int ch, uint16_t data)
2455 {
2456 if (!m_data_w_cb.isnull())
2457 (m_data_w_cb)(ch, data, 0);
2458 }
2459
s3c24xx_iis_start()2460 void S3C24_CLASS_NAME::s3c24xx_iis_start()
2461 {
2462 const uint32_t codeclk_table[] = { 256, 384};
2463 LOGMASKED(LOG_I2S, "IIS start\n");
2464 int prescaler_enable = BIT(m_iis.regs.iiscon, 1);
2465 int prescaler_control_a = BITS(m_iis.regs.iispsr, 9, 5);
2466 int prescaler_control_b = BITS(m_iis.regs.iispsr, 4, 0);
2467 int codeclk = BIT(m_iis.regs.iismod, 2);
2468 int pclk = s3c24xx_get_pclk();
2469 double freq = ((double)pclk / (prescaler_control_a + 1) / codeclk_table[codeclk]) * 2; // why do I have to multiply by two?
2470 LOGMASKED(LOG_I2S, "IIS - pclk %d psc_enable %d psc_a %d psc_b %d codeclk %d freq %f\n", pclk, prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk_table[codeclk], freq);
2471 m_iis.timer->adjust( attotime::from_hz( freq), 0, attotime::from_hz( freq));
2472 }
2473
s3c24xx_iis_stop()2474 void S3C24_CLASS_NAME::s3c24xx_iis_stop()
2475 {
2476 LOGMASKED(LOG_I2S, "IIS stop\n");
2477 m_iis.timer->adjust(attotime::never);
2478 }
2479
s3c24xx_iis_recalc()2480 void S3C24_CLASS_NAME::s3c24xx_iis_recalc()
2481 {
2482 if (BIT(m_iis.regs.iiscon, 0))
2483 s3c24xx_iis_start();
2484 else
2485 s3c24xx_iis_stop();
2486 }
2487
s3c24xx_iis_r(offs_t offset,uint32_t mem_mask)2488 uint32_t S3C24_CLASS_NAME::s3c24xx_iis_r(offs_t offset, uint32_t mem_mask)
2489 {
2490 uint32_t data = ((uint32_t*)&m_iis.regs)[offset];
2491 #if 0
2492 switch (offset)
2493 {
2494 case iis_t::IISCON:
2495 data = data & ~1; // hack for mp3 player
2496 LOGMASKED(LOG_I2S, "%s: i2s read: IISCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2497 break;
2498 }
2499 #endif
2500 LOGMASKED(LOG_I2S, "%s: i2s read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_IIS + (offset << 2), data, mem_mask);
2501 return data;
2502 }
2503
s3c24xx_iis_w(offs_t offset,uint32_t data,uint32_t mem_mask)2504 void S3C24_CLASS_NAME::s3c24xx_iis_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2505 {
2506 uint32_t old_value = ((uint32_t*)&m_iis.regs)[offset];
2507 COMBINE_DATA(&((uint32_t*)&m_iis.regs)[offset]);
2508 switch (offset)
2509 {
2510 case iis_t::IISCON:
2511 LOGMASKED(LOG_I2S, "%s: i2s write: IISCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2512 if (BIT(data ^ old_value, 0))
2513 s3c24xx_iis_recalc();
2514 break;
2515 case iis_t::IISFIFO:
2516 LOGMASKED(LOG_I2S, "%s: i2s write: IISFIFO = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2517 if (ACCESSING_BITS_16_31)
2518 {
2519 m_iis.fifo[m_iis.fifo_index++] = BITS(data, 31, 16);
2520 }
2521 if (ACCESSING_BITS_0_15)
2522 {
2523 m_iis.fifo[m_iis.fifo_index++] = BITS(data, 15, 0);
2524 }
2525 if (m_iis.fifo_index == 2)
2526 {
2527 m_iis.fifo_index = 0;
2528 iface_i2s_data_w(0, m_iis.fifo[0]);
2529 iface_i2s_data_w(1, m_iis.fifo[1]);
2530 }
2531 break;
2532 default:
2533 LOGMASKED(LOG_I2S, "%s: i2s write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_IIS + (offset << 2), data, mem_mask);
2534 break;
2535 }
2536 }
2537
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_iis_timer_exp)2538 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_iis_timer_exp )
2539 {
2540 LOGMASKED(LOG_I2S, "IIS timer callback\n");
2541 s3c24xx_dma_request_iis();
2542 }
2543
2544 /* RTC */
2545
s3c24xx_rtc_r(offs_t offset,uint32_t mem_mask)2546 uint32_t S3C24_CLASS_NAME::s3c24xx_rtc_r(offs_t offset, uint32_t mem_mask)
2547 {
2548 uint32_t data = ((uint32_t*)&m_rtc.regs)[offset];
2549 LOGMASKED(LOG_RTC, "%s: rtc read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_RTC + (offset << 2), data, mem_mask);
2550 return data;
2551 }
2552
s3c24xx_rtc_w(offs_t offset,uint32_t data,uint32_t mem_mask)2553 void S3C24_CLASS_NAME::s3c24xx_rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2554 {
2555 COMBINE_DATA(&((uint32_t*)&m_rtc.regs)[offset]);
2556 switch (offset)
2557 {
2558 case rtc_t::TICNT:
2559 LOGMASKED(LOG_RTC, "%s: rtc write: TICNT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2560 m_rtc.recalc();
2561 break;
2562 default:
2563 LOGMASKED(LOG_RTC, "%s: rtc write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_RTC + (offset << 2), data, mem_mask);
2564 break;
2565 }
2566 }
2567
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_rtc_timer_tick_count_exp)2568 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_rtc_timer_tick_count_exp )
2569 {
2570 LOGMASKED(LOG_RTC, "RTC timer callback (tick count)\n");
2571 s3c24xx_request_irq(S3C24XX_INT_TICK);
2572 }
2573
s3c24xx_rtc_update()2574 void S3C24_CLASS_NAME::s3c24xx_rtc_update()
2575 {
2576 m_rtc.update();
2577 LOGMASKED(LOG_RTC, "RTC - %04d/%02d/%02d %02d:%02d:%02d\n", bcd_2_dec( m_rtc.regs.bcdyear) + 2000, bcd_2_dec( m_rtc.regs.bcdmon), bcd_2_dec( m_rtc.regs.bcdday), bcd_2_dec( m_rtc.regs.bcdhour), bcd_2_dec( m_rtc.regs.bcdmin), bcd_2_dec( m_rtc.regs.bcdsec));
2578 }
2579
s3c24xx_rtc_check_alarm()2580 void S3C24_CLASS_NAME::s3c24xx_rtc_check_alarm()
2581 {
2582 if (m_rtc.check_alarm())
2583 s3c24xx_request_irq(S3C24XX_INT_RTC);
2584 }
2585
TIMER_CALLBACK_MEMBER(S3C24_CLASS_NAME::s3c24xx_rtc_timer_update_exp)2586 TIMER_CALLBACK_MEMBER( S3C24_CLASS_NAME::s3c24xx_rtc_timer_update_exp )
2587 {
2588 LOGMASKED(LOG_RTC, "RTC timer callback (update)\n");
2589 s3c24xx_rtc_update();
2590 s3c24xx_rtc_check_alarm();
2591 }
2592
2593 /* A/D Converter */
2594
s3c24xx_adc_reset()2595 void S3C24_CLASS_NAME::s3c24xx_adc_reset()
2596 {
2597 memset(&m_adc.regs, 0, sizeof(m_adc.regs));
2598 m_adc.regs.adccon = 0x3FC4;
2599 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2600 m_adc.regs.adctsc = 0x58;
2601 m_adc.regs.adcdly = 0xFF;
2602 #endif
2603 }
2604
iface_adc_data_r(int ch)2605 uint32_t S3C24_CLASS_NAME::iface_adc_data_r(int ch)
2606 {
2607 if (!m_data_r_cb.isnull())
2608 {
2609 int offs = ch;
2610 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2611 if (BIT(m_adc.regs.adctsc, 2) != 0)
2612 {
2613 offs += 2;
2614 }
2615 #endif
2616 return m_data_r_cb(offs, 0);
2617 }
2618 else
2619 {
2620 return 0;
2621 }
2622 }
2623
s3c24xx_adc_r(offs_t offset,uint32_t mem_mask)2624 uint32_t S3C24_CLASS_NAME::s3c24xx_adc_r(offs_t offset, uint32_t mem_mask)
2625 {
2626 uint32_t data = ((uint32_t*)&m_adc.regs)[offset];
2627 switch (offset)
2628 {
2629 #if defined(DEVICE_S3C2400)
2630 case S3C24XX_ADCDAT:
2631 data = (data & ~0x3FF) | (iface_adc_data_r(0) & 0x3FF);
2632 LOGMASKED(LOG_ADC, "%s: ADC read: ADCDAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2633 break;
2634 #else
2635 case S3C24XX_ADCDAT0:
2636 data = (data & ~0x3FF) | (iface_adc_data_r(0) & 0x3FF);
2637 LOGMASKED(LOG_ADC, "%s: ADC read: ADCDAT0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2638 break;
2639 case S3C24XX_ADCDAT1:
2640 data = (data & ~0x3FF) | (iface_adc_data_r(1) & 0x3FF);
2641 LOGMASKED(LOG_ADC, "%s: ADC read: ADCDAT1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2642 break;
2643 #endif
2644 default:
2645 LOGMASKED(LOG_ADC, "%s: ADC read: %08x = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2646 break;
2647 }
2648 return data;
2649 }
2650
s3c24xx_adc_start()2651 void S3C24_CLASS_NAME::s3c24xx_adc_start()
2652 {
2653 LOGMASKED(LOG_ADC, "ADC start\n");
2654 m_adc.regs.adccon &= ~(1 << 0); // A/D conversion is completed
2655 m_adc.regs.adccon |= (1 << 15); // End of A/D conversion
2656 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2657 s3c24xx_request_subirq(S3C24XX_SUBINT_ADC);
2658 #endif
2659 }
2660
s3c24xx_adc_w(offs_t offset,uint32_t data,uint32_t mem_mask)2661 void S3C24_CLASS_NAME::s3c24xx_adc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2662 {
2663 uint32_t old_value = ((uint32_t*)&m_adc.regs)[offset];
2664 COMBINE_DATA(&((uint32_t*)&m_adc.regs)[offset]);
2665 switch (offset)
2666 {
2667 case S3C24XX_ADCCON:
2668 if (((old_value & (1 << 0)) == 0) && ((data & (1 << 0)) != 0))
2669 {
2670 s3c24xx_adc_start();
2671 }
2672 LOGMASKED(LOG_ADC, "%s: ADC write: ADCCON = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2673 break;
2674 default:
2675 LOGMASKED(LOG_ADC, "%s: ADC write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_ADC + (offset << 2), data, mem_mask);
2676 break;
2677 }
2678 }
2679
2680 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2681
s3c24xx_touch_screen(int state)2682 void S3C24_CLASS_NAME::s3c24xx_touch_screen(int state)
2683 {
2684 m_adc.regs.adcdat0 = ((state ? 0 : 1) << 15);
2685 m_adc.regs.adcdat1 = ((state ? 0 : 1) << 15);
2686 s3c24xx_request_subirq(S3C24XX_SUBINT_TC);
2687 }
2688
2689 #endif
2690
2691 /* SPI */
2692
s3c24xx_spi_reset()2693 void S3C24_CLASS_NAME::s3c24xx_spi_reset()
2694 {
2695 for (spi_t &spi : m_spi)
2696 {
2697 memset(&spi.regs, 0, sizeof(spi.regs));
2698 spi.regs.spsta = 1;
2699 #if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
2700 spi.regs.sppin = 2;
2701 #endif
2702 }
2703 }
2704
s3c24xx_spi_r(uint32_t ch,uint32_t offset)2705 uint32_t S3C24_CLASS_NAME::s3c24xx_spi_r(uint32_t ch, uint32_t offset)
2706 {
2707 uint32_t data = ((uint32_t*)&m_spi[ch].regs)[offset];
2708 switch (offset)
2709 {
2710 case spi_t::SPSTA :
2711 data = data | (1 << 0); // [bit 0] Transfer Ready Flag
2712 break;
2713 }
2714 return data;
2715 }
2716
s3c24xx_spi_w(uint32_t ch,uint32_t offset,uint32_t data,uint32_t mem_mask)2717 void S3C24_CLASS_NAME::s3c24xx_spi_w(uint32_t ch, uint32_t offset, uint32_t data, uint32_t mem_mask)
2718 {
2719 COMBINE_DATA(&((uint32_t*)&m_spi[ch].regs)[offset]);
2720 }
2721
s3c24xx_spi_0_r(offs_t offset,uint32_t mem_mask)2722 uint32_t S3C24_CLASS_NAME::s3c24xx_spi_0_r(offs_t offset, uint32_t mem_mask)
2723 {
2724 const uint32_t data = s3c24xx_spi_r(0, offset);
2725 LOGMASKED(LOG_SPI, "%s: SPI 0 read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_SPI_0 + (offset << 2), data, mem_mask);
2726 return data;
2727 }
2728
2729 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2730
s3c24xx_spi_1_r(offs_t offset,uint32_t mem_mask)2731 uint32_t S3C24_CLASS_NAME::s3c24xx_spi_1_r(offs_t offset, uint32_t mem_mask)
2732 {
2733 const uint32_t data = s3c24xx_spi_r(1, offset);
2734 LOGMASKED(LOG_SPI, "%s: SPI 0 read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_SPI_0 + (offset << 2), data, mem_mask);
2735 return data;
2736 }
2737
2738 #endif
2739
s3c24xx_spi_0_w(offs_t offset,uint32_t data,uint32_t mem_mask)2740 void S3C24_CLASS_NAME::s3c24xx_spi_0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2741 {
2742 LOGMASKED(LOG_SPI, "%s: SPI 0 write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_SPI_0 + (offset << 2), data, mem_mask);
2743 s3c24xx_spi_w( 0, offset, data, mem_mask);
2744 }
2745
2746 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2747
s3c24xx_spi_1_w(offs_t offset,uint32_t data,uint32_t mem_mask)2748 void S3C24_CLASS_NAME::s3c24xx_spi_1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2749 {
2750 LOGMASKED(LOG_SPI, "%s: SPI 1 write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_SPI_0 + (offset << 2), data, mem_mask);
2751 s3c24xx_spi_w( 1, offset, data, mem_mask);
2752 }
2753
2754 #endif
2755
2756 /* MMC Interface */
2757
2758 #if defined(DEVICE_S3C2400)
2759
s3c24xx_mmc_r(offs_t offset,uint32_t mem_mask)2760 uint32_t S3C24_CLASS_NAME::s3c24xx_mmc_r(offs_t offset, uint32_t mem_mask)
2761 {
2762 const uint32_t data = m_mmc.regs.data[offset];
2763 LOGMASKED(LOG_MMC, "%s: MMC read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_MMC + (offset << 2), data, mem_mask);
2764 return data;
2765 }
2766
s3c24xx_mmc_w(offs_t offset,uint32_t data,uint32_t mem_mask)2767 void S3C24_CLASS_NAME::s3c24xx_mmc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2768 {
2769 LOGMASKED(LOG_MMC, "%s: MMC write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_MMC + (offset << 2), data, mem_mask);
2770 COMBINE_DATA(&m_mmc.regs.data[offset]);
2771 }
2772
2773 #endif
2774
2775 /* SD Interface */
2776
2777 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2778
s3c24xx_sdi_reset()2779 void S3C24_CLASS_NAME::s3c24xx_sdi_reset()
2780 {
2781 memset(&m_sdi.regs, 0, sizeof(m_sdi.regs));
2782 #if defined(DEVICE_S3C2410)
2783 m_sdi.regs.data[0x24/4] = 0x2000;
2784 #elif defined(DEVICE_S3C2440)
2785 m_sdi.regs.data[0x04/4] = 1;
2786 m_sdi.regs.data[0x24/4] = 0x10000;
2787 #endif
2788 }
2789
s3c24xx_sdi_r(offs_t offset,uint32_t mem_mask)2790 uint32_t S3C24_CLASS_NAME::s3c24xx_sdi_r(offs_t offset, uint32_t mem_mask)
2791 {
2792 uint32_t data = m_sdi.regs.data[offset];
2793 LOGMASKED(LOG_SDI, "%s: SDI read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_SDI + (offset << 2), data, mem_mask);
2794 return data;
2795 }
2796
s3c24xx_sdi_w(offs_t offset,uint32_t data,uint32_t mem_mask)2797 void S3C24_CLASS_NAME::s3c24xx_sdi_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2798 {
2799 LOGMASKED(LOG_SDI, "%s: SDI write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_SDI + (offset << 2), data, mem_mask);
2800 COMBINE_DATA(&m_sdi.regs.data[offset]);
2801 }
2802
2803 #endif
2804
2805 /* NAND Flash */
2806
2807 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
2808
s3c24xx_nand_reset()2809 void S3C24_CLASS_NAME::s3c24xx_nand_reset()
2810 {
2811 memset(&m_nand.regs, 0, sizeof(m_nand.regs));
2812 #if defined(DEVICE_S3C2440)
2813 m_nand.regs.nfconf = 0x1000;
2814 m_nand.regs.nfcont = 0x0384;
2815 #endif
2816 }
2817
iface_nand_command_w(uint8_t data)2818 void S3C24_CLASS_NAME::iface_nand_command_w(uint8_t data)
2819 {
2820 if (!m_command_w_cb.isnull())
2821 {
2822 m_command_w_cb(0, data, 0xff);
2823 }
2824 }
2825
iface_nand_address_w(uint8_t data)2826 void S3C24_CLASS_NAME::iface_nand_address_w(uint8_t data)
2827 {
2828 if (!m_address_w_cb.isnull())
2829 {
2830 m_address_w_cb(0, data, 0xff);
2831 }
2832 }
2833
iface_nand_data_r()2834 uint8_t S3C24_CLASS_NAME::iface_nand_data_r()
2835 {
2836 if (!m_nand_data_r_cb.isnull())
2837 return m_nand_data_r_cb(0, 0xff);
2838 else
2839 return 0;
2840 }
2841
iface_nand_data_w(uint8_t data)2842 void S3C24_CLASS_NAME::iface_nand_data_w(uint8_t data)
2843 {
2844 if (!m_nand_data_w_cb.isnull())
2845 m_nand_data_w_cb(0, data, 0xff);
2846 }
2847
nand_update_mecc(uint8_t * ecc,int pos,uint8_t data)2848 void S3C24_CLASS_NAME::nand_update_mecc(uint8_t *ecc, int pos, uint8_t data)
2849 {
2850 int bit[8];
2851 uint8_t temp;
2852 bit[0] = (data >> 0) & 1;
2853 bit[1] = (data >> 1) & 1;
2854 bit[2] = (data >> 2) & 1;
2855 bit[3] = (data >> 3) & 1;
2856 bit[4] = (data >> 4) & 1;
2857 bit[5] = (data >> 5) & 1;
2858 bit[6] = (data >> 6) & 1;
2859 bit[7] = (data >> 7) & 1;
2860 // column parity
2861 ecc[2] ^= ((bit[6] ^ bit[4] ^ bit[2] ^ bit[0]) << 2);
2862 ecc[2] ^= ((bit[7] ^ bit[5] ^ bit[3] ^ bit[1]) << 3);
2863 ecc[2] ^= ((bit[5] ^ bit[4] ^ bit[1] ^ bit[0]) << 4);
2864 ecc[2] ^= ((bit[7] ^ bit[6] ^ bit[3] ^ bit[2]) << 5);
2865 ecc[2] ^= ((bit[3] ^ bit[2] ^ bit[1] ^ bit[0]) << 6);
2866 ecc[2] ^= ((bit[7] ^ bit[6] ^ bit[5] ^ bit[4]) << 7);
2867 // line parity
2868 temp = bit[7] ^ bit[6] ^ bit[5] ^ bit[4] ^ bit[3] ^ bit[2] ^ bit[1] ^ bit[0];
2869 if (pos & 0x001) ecc[0] ^= (temp << 1); else ecc[0] ^= (temp << 0);
2870 if (pos & 0x002) ecc[0] ^= (temp << 3); else ecc[0] ^= (temp << 2);
2871 if (pos & 0x004) ecc[0] ^= (temp << 5); else ecc[0] ^= (temp << 4);
2872 if (pos & 0x008) ecc[0] ^= (temp << 7); else ecc[0] ^= (temp << 6);
2873 if (pos & 0x010) ecc[1] ^= (temp << 1); else ecc[1] ^= (temp << 0);
2874 if (pos & 0x020) ecc[1] ^= (temp << 3); else ecc[1] ^= (temp << 2);
2875 if (pos & 0x040) ecc[1] ^= (temp << 5); else ecc[1] ^= (temp << 4);
2876 if (pos & 0x080) ecc[1] ^= (temp << 7); else ecc[1] ^= (temp << 6);
2877 if (pos & 0x100) ecc[2] ^= (temp << 1); else ecc[2] ^= (temp << 0);
2878 if (pos & 0x200) ecc[3] ^= (temp << 5); else ecc[3] ^= (temp << 4);
2879 if (pos & 0x400) ecc[3] ^= (temp << 7); else ecc[3] ^= (temp << 6);
2880 }
2881
2882 #if defined(DEVICE_S3C2440)
2883
nand_update_secc(uint8_t * ecc,int pos,uint8_t data)2884 void S3C24_CLASS_NAME::nand_update_secc( uint8_t *ecc, int pos, uint8_t data)
2885 {
2886 int bit[8];
2887 uint8_t temp;
2888 bit[0] = (data >> 0) & 1;
2889 bit[1] = (data >> 1) & 1;
2890 bit[2] = (data >> 2) & 1;
2891 bit[3] = (data >> 3) & 1;
2892 bit[4] = (data >> 4) & 1;
2893 bit[5] = (data >> 5) & 1;
2894 bit[6] = (data >> 6) & 1;
2895 bit[7] = (data >> 7) & 1;
2896 // column parity
2897 ecc[1] ^= ((bit[6] ^ bit[4] ^ bit[2] ^ bit[0]) << 6);
2898 ecc[1] ^= ((bit[7] ^ bit[5] ^ bit[3] ^ bit[1]) << 7);
2899 ecc[0] ^= ((bit[5] ^ bit[4] ^ bit[1] ^ bit[0]) << 0);
2900 ecc[0] ^= ((bit[7] ^ bit[6] ^ bit[3] ^ bit[2]) << 1);
2901 ecc[0] ^= ((bit[3] ^ bit[2] ^ bit[1] ^ bit[0]) << 2);
2902 ecc[0] ^= ((bit[7] ^ bit[6] ^ bit[5] ^ bit[4]) << 3);
2903 // line parity
2904 temp = bit[7] ^ bit[6] ^ bit[5] ^ bit[4] ^ bit[3] ^ bit[2] ^ bit[1] ^ bit[0];
2905 if (pos & 0x001) ecc[0] ^= (temp << 5); else ecc[0] ^= (temp << 4);
2906 if (pos & 0x002) ecc[0] ^= (temp << 7); else ecc[0] ^= (temp << 6);
2907 if (pos & 0x004) ecc[1] ^= (temp << 3); else ecc[1] ^= (temp << 2);
2908 if (pos & 0x008) ecc[1] ^= (temp << 5); else ecc[1] ^= (temp << 4);
2909 }
2910
2911 #endif
2912
s3c24xx_nand_update_ecc(uint8_t data)2913 void S3C24_CLASS_NAME::s3c24xx_nand_update_ecc(uint8_t data)
2914 {
2915 uint8_t temp[4];
2916 #if defined(DEVICE_S3C2410)
2917 temp[0] = m_nand.mecc[0];
2918 temp[1] = m_nand.mecc[1];
2919 temp[2] = m_nand.mecc[2];
2920 nand_update_mecc(m_nand.mecc, m_nand.ecc_pos++, data);
2921 LOGMASKED(LOG_FLASH, "%s: NAND - MECC %03X - %02X %02X %02X -> %02X %02X %02X\n", machine().describe_context(), m_nand.ecc_pos - 1, temp[0], temp[1], temp[2], m_nand.mecc[0], m_nand.mecc[1], m_nand.mecc[2]);
2922 if (m_nand.ecc_pos == 512)
2923 m_nand.ecc_pos = 0;
2924 #else
2925 if (!BIT(m_nand.regs.nfcont, 5))
2926 {
2927 temp[0] = m_nand.mecc[0];
2928 temp[1] = m_nand.mecc[1];
2929 temp[2] = m_nand.mecc[2];
2930 temp[3] = m_nand.mecc[3];
2931 nand_update_mecc( m_nand.mecc, m_nand.ecc_pos++, data);
2932 LOGMASKED(LOG_FLASH, "%s: NAND - MECC %03X - %02X %02X %02X %02X -> %02X %02X %02X %02X\n", machine().describe_context(), m_nand.ecc_pos - 1, temp[0], temp[1], temp[2], temp[3], m_nand.mecc[0], m_nand.mecc[1], m_nand.mecc[2], m_nand.mecc[3]);
2933 if (m_nand.ecc_pos == 2048) m_nand.ecc_pos = 0;
2934 }
2935 if (!BIT(m_nand.regs.nfcont, 6))
2936 {
2937 temp[0] = m_nand.secc[0];
2938 temp[1] = m_nand.secc[1];
2939 nand_update_secc(m_nand.secc, m_nand.ecc_pos++, data);
2940 LOGMASKED(LOG_FLASH, "%s: NAND - SECC %02X - %02X %02X -> %02X %02X\n", machine().describe_context(), m_nand.ecc_pos - 1, temp[0], temp[1], m_nand.secc[0], m_nand.secc[1]);
2941 if (m_nand.ecc_pos == 16)
2942 m_nand.ecc_pos = 0;
2943 }
2944 #endif
2945 }
2946
s3c24xx_nand_command_w(uint8_t data)2947 void S3C24_CLASS_NAME::s3c24xx_nand_command_w(uint8_t data)
2948 {
2949 LOGMASKED(LOG_FLASH, "%s: NAND write command %02X\n", machine().describe_context(), data);
2950 m_nand.data_count = 0;
2951 iface_nand_command_w(data);
2952 }
2953
s3c24xx_nand_address_w(uint8_t data)2954 void S3C24_CLASS_NAME::s3c24xx_nand_address_w(uint8_t data)
2955 {
2956 LOGMASKED(LOG_FLASH, "%s: NAND write address %02X\n", machine().describe_context(), data);
2957 m_nand.data_count = 0;
2958 iface_nand_address_w(data);
2959 }
2960
s3c24xx_nand_data_r()2961 uint8_t S3C24_CLASS_NAME::s3c24xx_nand_data_r()
2962 {
2963 uint8_t data = iface_nand_data_r();
2964 LOGMASKED(LOG_FLASH, "%s: NAND read data %02X [%04X]\n", machine().describe_context(), data, m_nand.data_count++);
2965 s3c24xx_nand_update_ecc(data);
2966 return data;
2967 }
2968
s3c24xx_nand_data_w(uint8_t data)2969 void S3C24_CLASS_NAME::s3c24xx_nand_data_w(uint8_t data)
2970 {
2971 LOGMASKED(LOG_FLASH, "%s: NAND write data %02X [%04X]\n", machine().describe_context(), data, m_nand.data_count++);
2972 iface_nand_data_w(data);
2973 s3c24xx_nand_update_ecc(data);
2974 }
2975
s3c24xx_nand_r(offs_t offset,uint32_t mem_mask)2976 uint32_t S3C24_CLASS_NAME::s3c24xx_nand_r(offs_t offset, uint32_t mem_mask)
2977 {
2978 uint32_t data = ((uint32_t*)&m_nand.regs)[offset];
2979 switch (offset)
2980 {
2981 case S3C24XX_NFDATA:
2982 data = 0;
2983 #if defined(DEVICE_S3C2410)
2984 data = data | s3c24xx_nand_data_r();
2985 #elif defined(DEVICE_S3C2440)
2986 if ((mem_mask & 0x000000FF) != 0) data = data | (s3c24xx_nand_data_r() << 0);
2987 if ((mem_mask & 0x0000FF00) != 0) data = data | (s3c24xx_nand_data_r() << 8);
2988 if ((mem_mask & 0x00FF0000) != 0) data = data | (s3c24xx_nand_data_r() << 16);
2989 if ((mem_mask & 0xFF000000) != 0) data = data | (s3c24xx_nand_data_r() << 24);
2990 #endif
2991 break;
2992 #if defined(DEVICE_S3C2410)
2993 case S3C24XX_NFECC :
2994 data = ((m_nand.mecc[2] << 16) | (m_nand.mecc[1] << 8) | (m_nand.mecc[0] << 0));
2995 LOGMASKED(LOG_FLASH, "%s: NAND read: NFECC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
2996 break;
2997 #endif
2998 #if defined(DEVICE_S3C2440)
2999 case S3C24XX_NFMECC0 :
3000 data = (m_nand.mecc[3] << 24) | (m_nand.mecc[2] << 16) | (m_nand.mecc[1] << 8) | (m_nand.mecc[0] << 0);
3001 LOGMASKED(LOG_FLASH, "%s: NAND read: NFMECC0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3002 break;
3003 case S3C24XX_NFSECC :
3004 data = (m_nand.secc[1] << 8) | (m_nand.secc[0] << 0);
3005 LOGMASKED(LOG_FLASH, "%s: NAND read: NFSECC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3006 break;
3007 case S3C24XX_NFESTAT0 :
3008 data &= ~0x000000F; // no main/spare ECC errors
3009 LOGMASKED(LOG_FLASH, "%s: NAND read: NFESTAT0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3010 break;
3011 case S3C24XX_NFESTAT1 :
3012 data &= ~0x000000F; // no main/spare ECC errors
3013 LOGMASKED(LOG_FLASH, "%s: NAND read: NFESTAT1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3014 break;
3015 #endif
3016 default:
3017 LOGMASKED(LOG_FLASH, "%s: NAND read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_NAND + (offset << 2), data, mem_mask);
3018 break;
3019 }
3020 return data;
3021 }
3022
s3c24xx_nand_init_ecc()3023 void S3C24_CLASS_NAME::s3c24xx_nand_init_ecc()
3024 {
3025 LOGMASKED(LOG_FLASH, "NAND - init ecc\n");
3026 m_nand.mecc[0] = 0xFF;
3027 m_nand.mecc[1] = 0xFF;
3028 m_nand.mecc[2] = 0xFF;
3029 #if defined(DEVICE_S3C2440)
3030 m_nand.mecc[3] = 0xFF;
3031 m_nand.secc[0] = 0;
3032 m_nand.secc[1] = 0;
3033 #endif
3034 m_nand.ecc_pos = 0;
3035 }
3036
s3c24xx_nand_w(offs_t offset,uint32_t data,uint32_t mem_mask)3037 void S3C24_CLASS_NAME::s3c24xx_nand_w(offs_t offset, uint32_t data, uint32_t mem_mask)
3038 {
3039 uint32_t old_value = ((uint32_t*)&m_nand.regs)[offset];
3040 COMBINE_DATA(&((uint32_t*)&m_nand.regs)[offset]);
3041 switch (offset)
3042 {
3043 #if defined(DEVICE_S3C2410)
3044 case S3C24XX_NFCONF:
3045 LOGMASKED(LOG_FLASH, "%s: NAND write: NFCONF = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3046 if ((data & (1 << 12)) != 0)
3047 s3c24xx_nand_init_ecc();
3048 break;
3049 #endif
3050 #if defined(DEVICE_S3C2440)
3051 case S3C24XX_NFCONT:
3052 LOGMASKED(LOG_FLASH, "%s: NAND write: NFCONT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3053 if ((data & (1 << 4)) != 0)
3054 s3c24xx_nand_init_ecc();
3055 break;
3056 #endif
3057 case S3C24XX_NFSTAT:
3058 LOGMASKED(LOG_FLASH, "%s: NAND write: NFSTAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3059 m_nand.regs.nfstat = (m_nand.regs.nfstat & ~0x03) | (old_value & 0x03); // read-only
3060 #if defined(DEVICE_S3C2440)
3061 if ((data & (1 << 2)) != 0)
3062 m_nand.regs.nfstat &= ~(1 << 2); // "RnB_TransDetect, to clear this value write 1"
3063 #endif
3064 break;
3065 case S3C24XX_NFCMD:
3066 LOGMASKED(LOG_FLASH, "%s: NAND write: NFCMD = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3067 s3c24xx_nand_command_w(data);
3068 break;
3069 case S3C24XX_NFADDR:
3070 LOGMASKED(LOG_FLASH, "%s: NAND write: NFADDR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
3071 s3c24xx_nand_address_w(data);
3072 break;
3073 case S3C24XX_NFDATA:
3074 #if defined(DEVICE_S3C2410)
3075 s3c24xx_nand_data_w(data & 0xFF);
3076 #elif defined(DEVICE_S3C2440)
3077 if ((mem_mask & 0x000000FF) != 0) s3c24xx_nand_data_w((data >> 0) & 0xFF);
3078 if ((mem_mask & 0x0000FF00) != 0) s3c24xx_nand_data_w((data >> 8) & 0xFF);
3079 if ((mem_mask & 0x00FF0000) != 0) s3c24xx_nand_data_w((data >> 16) & 0xFF);
3080 if ((mem_mask & 0xFF000000) != 0) s3c24xx_nand_data_w((data >> 24) & 0xFF);
3081 #endif
3082 break;
3083 default:
3084 LOGMASKED(LOG_FLASH, "%s: NAND write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_NAND + (offset << 2), data, mem_mask);
3085 break;
3086 }
3087 }
3088
WRITE_LINE_MEMBER(S3C24_CLASS_NAME::s3c24xx_pin_frnb_w)3089 ATTR_UNUSED WRITE_LINE_MEMBER( S3C24_CLASS_NAME::s3c24xx_pin_frnb_w )
3090 {
3091 LOGMASKED(LOG_FLASH, "s3c24xx_pin_frnb_w (%d)\n", state);
3092 #if defined(DEVICE_S3C2440)
3093 if ((BIT( m_nand.regs.nfstat, 0) == 0) && (state != 0))
3094 {
3095 m_nand.regs.nfstat |= (1 << 2);
3096 if (BIT( m_nand.regs.nfcont, 9) != 0)
3097 s3c24xx_request_irq( S3C24XX_INT_NFCON);
3098 }
3099 #endif
3100 if (state == 0)
3101 m_nand.regs.nfstat &= ~(1 << 0);
3102 else
3103 m_nand.regs.nfstat |= (1 << 0);
3104 }
3105
3106 #endif
3107
3108 /* Camera Interface */
3109
3110 #if defined(DEVICE_S3C2440)
3111
s3c24xx_cam_r(offs_t offset,uint32_t mem_mask)3112 uint32_t S3C24_CLASS_NAME::s3c24xx_cam_r(offs_t offset, uint32_t mem_mask)
3113 {
3114 uint32_t data = m_cam.regs.data[offset];
3115 LOGMASKED(LOG_CAM, "%s: camera read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_CAM + (offset << 2), data, mem_mask);
3116 return data;
3117 }
3118
s3c24xx_cam_w(offs_t offset,uint32_t data,uint32_t mem_mask)3119 void S3C24_CLASS_NAME::s3c24xx_cam_w(offs_t offset, uint32_t data, uint32_t mem_mask)
3120 {
3121 LOGMASKED(LOG_CAM, "%s: camera write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_CAM + (offset << 2), data, mem_mask);
3122 COMBINE_DATA(&m_cam.regs.data[offset]);
3123 }
3124
3125 #endif
3126
3127 /* AC97 Interface */
3128
3129 #if defined(DEVICE_S3C2440)
3130
s3c24xx_ac97_r(offs_t offset,uint32_t mem_mask)3131 uint32_t S3C24_CLASS_NAME::s3c24xx_ac97_r(offs_t offset, uint32_t mem_mask)
3132 {
3133 const uint32_t data = m_ac97.regs.data[offset];
3134 LOGMASKED(LOG_AC97, "%s: audio codec read: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_AC97 + (offset << 2), data, mem_mask);
3135 return data;
3136 }
3137
s3c24xx_ac97_w(offs_t offset,uint32_t data,uint32_t mem_mask)3138 void S3C24_CLASS_NAME::s3c24xx_ac97_w(offs_t offset, uint32_t data, uint32_t mem_mask)
3139 {
3140 LOGMASKED(LOG_AC97, "%s: audio codec write: %08x = %08x & %08x\n", machine().describe_context(), S3C24XX_BASE_AC97 + (offset << 2), data, mem_mask);
3141 COMBINE_DATA(&m_ac97.regs.data[offset]);
3142 }
3143
3144 #endif
3145
3146 // ...
3147
3148 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
3149
s3c24xx_nand_auto_boot()3150 void S3C24_CLASS_NAME::s3c24xx_nand_auto_boot()
3151 {
3152 int om0 = iface_core_pin_r(S3C24XX_CORE_PIN_OM0);
3153 int om1 = iface_core_pin_r(S3C24XX_CORE_PIN_OM1);
3154 if ((om0 == 0) && (om1 == 0))
3155 {
3156 int ncon = iface_core_pin_r(S3C24XX_CORE_PIN_NCON);
3157 uint8_t *ptr = m_steppingstone;
3158 int page_size, address_cycle;
3159 #if defined(DEVICE_S3C2410)
3160 page_size = 512;
3161 if (ncon == 0)
3162 address_cycle = 3; // byte-page-page
3163 else
3164 address_cycle = 4; // byte-page-page-page
3165 #elif defined(DEVICE_S3C2440)
3166 uint32_t port_g = iface_gpio_port_r( S3C24XX_GPIO_PORT_G, 0);
3167 if (ncon == 0)
3168 {
3169 if (BIT( port_g, 13) == 0)
3170 {
3171 page_size = 256;
3172 address_cycle = 3; // byte-page-page
3173 }
3174 else
3175 {
3176 page_size = 512;
3177 address_cycle = 4; // byte-page-page-page
3178 }
3179 }
3180 else
3181 {
3182 if (BIT( port_g, 13) == 0)
3183 {
3184 page_size = 1024;
3185 address_cycle = 4; // byte-byte-page-page or byte-page-page-page ??? assume latter
3186 }
3187 else
3188 {
3189 page_size = 2048;
3190 address_cycle = 5; // byte-byte-page-page-page
3191 }
3192 }
3193 #endif
3194 iface_nand_command_w(0xFF);
3195 for (int page = 0; page < (4 * 1024) / page_size; page++)
3196 {
3197 iface_nand_command_w(0x00);
3198 iface_nand_address_w(0x00);
3199 if (address_cycle > 4)
3200 {
3201 iface_nand_address_w(0x00);
3202 }
3203 iface_nand_address_w((page >> 0) & 0xFF);
3204 iface_nand_address_w((page >> 8) & 0xFF);
3205 if (address_cycle > 3)
3206 {
3207 iface_nand_address_w((page >> 16) & 0xFF);
3208 }
3209 for (int i = 0; i < page_size; i++)
3210 {
3211 *ptr++ = iface_nand_data_r();
3212 }
3213 }
3214 iface_nand_command_w(0xFF);
3215 }
3216 }
3217
3218 #endif
3219
s3c24xx_device_reset()3220 void S3C24_CLASS_NAME::s3c24xx_device_reset()
3221 {
3222 LOGMASKED(LOG_RESET, "s3c24xx device reset\n");
3223 for (uart_t &uart : m_uart)
3224 uart.reset();
3225 m_pwm.reset();
3226 s3c24xx_dma_reset();
3227 s3c24xx_iic_reset();
3228 m_iis.reset();
3229 s3c24xx_lcd_reset();
3230 m_rtc.reset();
3231 m_wdt.reset();
3232 s3c24xx_irq_reset();
3233 s3c24xx_gpio_reset();
3234 m_memcon.reset();
3235 s3c24xx_clkpow_reset();
3236 m_usbhost.reset();
3237 s3c24xx_usb_device_reset();
3238 s3c24xx_adc_reset();
3239 s3c24xx_spi_reset();
3240 #if defined(DEVICE_S3C2400)
3241 m_mmc.reset();
3242 #endif
3243 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
3244 s3c24xx_sdi_reset();
3245 s3c24xx_nand_reset();
3246 #endif
3247 #if defined(DEVICE_S3C2440)
3248 m_cam.reset();
3249 m_ac97.reset();
3250 #endif
3251 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
3252 s3c24xx_nand_auto_boot();
3253 #endif
3254 }
3255
s3c24xx_device_start()3256 void S3C24_CLASS_NAME::s3c24xx_device_start()
3257 {
3258 LOGMASKED(LOG_RESET, "s3c24xx device start\n");
3259 m_pin_r_cb.resolve();
3260 m_pin_w_cb.resolve_safe();
3261 m_port_r_cb.resolve();
3262 m_port_w_cb.resolve();
3263 m_scl_w_cb.resolve();
3264 m_sda_r_cb.resolve();
3265 m_sda_w_cb.resolve();
3266 m_data_r_cb.resolve();
3267 m_data_w_cb.resolve();
3268 #if !defined(DEVICE_S3C2400)
3269 m_command_w_cb.resolve();
3270 m_address_w_cb.resolve();
3271 m_nand_data_r_cb.resolve();
3272 m_nand_data_w_cb.resolve();
3273 #endif
3274 for (int i = 0; i < 5; i++)
3275 m_pwm.timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_pwm_timer_exp), this));
3276 for (auto & elem : m_dma)
3277 elem.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_dma_timer_exp), this));
3278 m_iic.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_iic_timer_exp), this));
3279 m_iis.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_iis_timer_exp), this));
3280 m_lcd.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_lcd_timer_exp), this));
3281 m_rtc.timer_tick_count = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_rtc_timer_tick_count_exp), this));
3282 m_rtc.timer_update = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_rtc_timer_update_exp), this));
3283 m_wdt.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(S3C24_CLASS_NAME::s3c24xx_wdt_timer_exp), this));
3284
3285 #if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
3286 int om0 = iface_core_pin_r(S3C24XX_CORE_PIN_OM0);
3287 int om1 = iface_core_pin_r(S3C24XX_CORE_PIN_OM1);
3288 if ((om0 == 0) && (om1 == 0))
3289 {
3290 address_space &space = m_cpu->space(AS_PROGRAM);
3291 space.install_ram(0x00000000, 0x00000fff, m_steppingstone);
3292 space.install_ram(0x40000000, 0x40000fff, m_steppingstone);
3293 }
3294 #endif
3295 }
3296