summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/pxa255.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/pxa255.cpp')
-rw-r--r--src/devices/machine/pxa255.cpp434
1 files changed, 402 insertions, 32 deletions
diff --git a/src/devices/machine/pxa255.cpp b/src/devices/machine/pxa255.cpp
index 4c6c750afd3..e8710f7d891 100644
--- a/src/devices/machine/pxa255.cpp
+++ b/src/devices/machine/pxa255.cpp
@@ -23,9 +23,12 @@
#define LOG_GPIO (1 << 6)
#define LOG_LCD_DMA (1 << 7)
#define LOG_LCD (1 << 8)
-#define LOG_ALL (LOG_UNKNOWN | LOG_I2S | LOG_DMA | LOG_OSTIMER | LOG_INTC | LOG_GPIO | LOG_LCD_DMA | LOG_LCD)
+#define LOG_POWER (1 << 9)
+#define LOG_RTC (1 << 10)
+#define LOG_CLOCKS (1 << 11)
+#define LOG_ALL (LOG_UNKNOWN | LOG_I2S | LOG_DMA | LOG_OSTIMER | LOG_INTC | LOG_GPIO | LOG_LCD_DMA | LOG_LCD | LOG_POWER | LOG_RTC | LOG_CLOCKS)
-#define VERBOSE (0)
+#define VERBOSE (LOG_ALL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(PXA255_PERIPHERALS, pxa255_periphs_device, "pxa255_periphs", "Intel XScale PXA255 Peripherals")
@@ -198,14 +201,14 @@ void pxa255_periphs_device::dma_load_descriptor_and_start(int channel)
m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_STOPSTATE;
}
-TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end)
+void pxa255_periphs_device::dma_end_tick(int channel)
{
- uint32_t sadr = m_dma_regs.dsadr[param];
- uint32_t tadr = m_dma_regs.dtadr[param];
- uint32_t count = m_dma_regs.dcmd[param] & 0x00001fff;
+ uint32_t sadr = m_dma_regs.dsadr[channel];
+ uint32_t tadr = m_dma_regs.dtadr[channel];
+ uint32_t count = m_dma_regs.dcmd[channel] & 0x00001fff;
address_space &space = m_maincpu->space(AS_PROGRAM);
- switch (param)
+ switch (channel)
{
case 3:
for (uint32_t index = 0; index < count; index += 4)
@@ -224,7 +227,7 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end)
default:
for (uint32_t index = 0; index < count;)
{
- switch (m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE)
+ switch (m_dma_regs.dcmd[channel] & PXA255_DCMD_SIZE)
{
case PXA255_DCMD_SIZE_8:
space.write_byte(tadr, space.read_byte(sadr));
@@ -243,9 +246,9 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end)
break;
}
- if (m_dma_regs.dcmd[param] & PXA255_DCMD_INCSRCADDR)
+ if (m_dma_regs.dcmd[channel] & PXA255_DCMD_INCSRCADDR)
{
- switch(m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE)
+ switch(m_dma_regs.dcmd[channel] & PXA255_DCMD_SIZE)
{
case PXA255_DCMD_SIZE_8:
sadr++;
@@ -260,9 +263,9 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end)
break;
}
}
- if(m_dma_regs.dcmd[param] & PXA255_DCMD_INCTRGADDR)
+ if(m_dma_regs.dcmd[channel] & PXA255_DCMD_INCTRGADDR)
{
- switch(m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE)
+ switch(m_dma_regs.dcmd[channel] & PXA255_DCMD_SIZE)
{
case PXA255_DCMD_SIZE_8:
tadr++;
@@ -281,27 +284,27 @@ TIMER_CALLBACK_MEMBER(pxa255_periphs_device::dma_dma_end)
break;
}
- if (m_dma_regs.dcmd[param] & PXA255_DCMD_ENDIRQEN)
+ if (m_dma_regs.dcmd[channel] & PXA255_DCMD_ENDIRQEN)
{
- m_dma_regs.dcsr[param] |= PXA255_DCSR_ENDINTR;
+ m_dma_regs.dcsr[channel] |= PXA255_DCSR_ENDINTR;
}
- if (!(m_dma_regs.ddadr[param] & PXA255_DDADR_STOP) && (m_dma_regs.dcsr[param] & PXA255_DCSR_RUN))
+ if (!(m_dma_regs.ddadr[channel] & PXA255_DDADR_STOP) && (m_dma_regs.dcsr[channel] & PXA255_DCSR_RUN))
{
- if (m_dma_regs.dcsr[param] & PXA255_DCSR_RUN)
+ if (m_dma_regs.dcsr[channel] & PXA255_DCSR_RUN)
{
- dma_load_descriptor_and_start(param);
+ dma_load_descriptor_and_start(channel);
}
else
{
- m_dma_regs.dcsr[param] &= ~PXA255_DCSR_RUN;
- m_dma_regs.dcsr[param] |= PXA255_DCSR_STOPSTATE;
+ m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_RUN;
+ m_dma_regs.dcsr[channel] |= PXA255_DCSR_STOPSTATE;
}
}
else
{
- m_dma_regs.dcsr[param] &= ~PXA255_DCSR_RUN;
- m_dma_regs.dcsr[param] |= PXA255_DCSR_STOPSTATE;
+ m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_RUN;
+ m_dma_regs.dcsr[channel] |= PXA255_DCSR_STOPSTATE;
}
dma_irq_check();
@@ -446,6 +449,95 @@ void pxa255_periphs_device::dma_w(offs_t offset, uint32_t data, uint32_t mem_mas
/*
+ PXA255 Real-Time Clock
+
+ pg. 132 to 138, PXA255 Processor Developers Manual [278693-002].pdf
+
+*/
+
+void pxa255_periphs_device::rtc_tick()
+{
+ m_rtc_regs.rcnr++;
+ if (BIT(m_rtc_regs.rtsr, 3))
+ {
+ m_rtc_regs.rtsr |= (1 << 1);
+ set_irq_line(PXA255_INT_RTC_HZ, 1);
+ }
+
+ if (m_rtc_regs.rcnr == m_rtc_regs.rtar)
+ {
+ if (BIT(m_rtc_regs.rtsr, 2))
+ {
+ m_rtc_regs.rtsr |= (1 << 0);
+ set_irq_line(PXA255_INT_RTC_ALARM, 1);
+ }
+ }
+}
+
+uint32_t pxa255_periphs_device::rtc_r(offs_t offset, uint32_t mem_mask)
+{
+ switch(PXA255_RTC_BASE_ADDR | (offset << 2))
+ {
+ case PXA255_RCNR:
+ LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Counter Register: %08x\n", machine().describe_context(), m_rtc_regs.rcnr);
+ return m_rtc_regs.rcnr;
+ case PXA255_RTAR:
+ LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Alarm Register: %08x\n", machine().describe_context(), m_rtc_regs.rtar);
+ return m_rtc_regs.rtar;
+ case PXA255_RTSR:
+ LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Status Register: %08x\n", machine().describe_context(), m_rtc_regs.rtsr);
+ return m_rtc_regs.rtsr;
+ case PXA255_RTTR:
+ LOGMASKED(LOG_RTC, "%s: pxa255 rtc_r: RTC Trim Register: %08x\n", machine().describe_context(), m_rtc_regs.rttr);
+ return m_rtc_regs.rttr;
+ default:
+ LOGMASKED(LOG_RTC | LOG_UNKNOWN, "pxa255 rtc_r: Unknown address: %08x\n", PXA255_RTC_BASE_ADDR | (offset << 2));
+ break;
+ }
+ return 0;
+}
+
+void pxa255_periphs_device::rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ switch(PXA255_RTC_BASE_ADDR | (offset << 2))
+ {
+ case PXA255_RCNR:
+ LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Counter Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_rtc_regs.rcnr);
+ break;
+ case PXA255_RTAR:
+ LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Alarm Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_rtc_regs.rtar);
+ break;
+ case PXA255_RTSR:
+ {
+ LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ const uint32_t old = m_rtc_regs.rtsr;
+ m_rtc_regs.rtsr &= ~(data & 0x00000003);
+ m_rtc_regs.rtsr &= ~0x0000000c;
+ m_rtc_regs.rtsr |= data & 0x0000000c;
+ const uint32_t diff = old ^ m_rtc_regs.rtsr;
+ if (BIT(diff, 1))
+ set_irq_line(PXA255_INT_RTC_HZ, 0);
+ if (BIT(diff, 0))
+ set_irq_line(PXA255_INT_RTC_ALARM, 0);
+ break;
+ }
+ case PXA255_RTTR:
+ LOGMASKED(LOG_RTC, "pxa255 rtc_w: RTC Trim Register (not yet implemented): %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ if (!BIT(m_rtc_regs.rttr, 31))
+ {
+ COMBINE_DATA(&m_rtc_regs.rttr);
+ }
+ break;
+ default:
+ LOGMASKED(LOG_RTC | LOG_UNKNOWN, "pxa255 rtc_w: Unknown address: %08x = %08x & %08x\n", PXA255_RTC_BASE_ADDR | (offset << 2), data, mem_mask);
+ break;
+ }
+}
+
+/*
+
PXA255 OS Timer register
pg. 138 to 142, PXA255 Processor Developers Manual [278693-002].pdf
@@ -460,10 +552,10 @@ void pxa255_periphs_device::ostimer_irq_check()
//set_irq_line(PXA255_INT_OSTIMER3, (m_ostimer_regs.oier & PXA255_OIER_E3) ? ((m_ostimer_regs.ossr & PXA255_OSSR_M3) ? 1 : 0) : 0);
}
-TIMER_CALLBACK_MEMBER(pxa255_periphs_device::ostimer_match)
+void pxa255_periphs_device::ostimer_match_tick(int channel)
{
- m_ostimer_regs.ossr |= (1 << param);
- m_ostimer_regs.oscr = m_ostimer_regs.osmr[param];
+ m_ostimer_regs.ossr |= (1 << channel);
+ m_ostimer_regs.oscr = m_ostimer_regs.osmr[channel];
ostimer_irq_check();
}
@@ -665,6 +757,77 @@ void pxa255_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_ma
uint32_t pxa255_periphs_device::gpio_r(offs_t offset, uint32_t mem_mask)
{
+ const uint32_t val = (data != 0 ? 1 : 0);
+ LOGMASKED(LOG_GPIO, "pxa255: GPIO%d written: %d\n", offset, val);
+ if (offset < 32)
+ {
+ const uint32_t old = m_gpio_regs.gplr0;
+ m_gpio_regs.gplr0 &= ~(1 << offset);
+ m_gpio_regs.gplr0 |= (val << offset);
+
+ LOGMASKED(LOG_GPIO, "pxa255: Old GPLR0 %08x, New GPLR0 %08x\n", old, m_gpio_regs.gplr0);
+
+ const uint32_t rising = ~old & m_gpio_regs.gplr0;
+ const uint32_t falling = old & ~m_gpio_regs.gplr0;
+
+ LOGMASKED(LOG_GPIO, "pxa255: Rising %08x, Falling %08x\n", rising, falling);
+
+ const uint32_t old_gedr = m_gpio_regs.gedr0;
+ m_gpio_regs.gedr0 |= (rising & m_gpio_regs.grer0);
+ m_gpio_regs.gedr0 |= (falling & m_gpio_regs.gfer0);
+
+ LOGMASKED(LOG_GPIO, "pxa255: Old GEDR0 %08x, New GEDR0 %08x\n", old_gedr, m_gpio_regs.gedr0);
+ if (old_gedr != m_gpio_regs.gedr0)
+ {
+ LOGMASKED(LOG_GPIO, "pxa255: Edge detected on GPIO%d\n", offset);
+ if (offset > 1)
+ set_irq_line(PXA255_INT_GPIO84_2, 1);
+ else if (offset == 1)
+ set_irq_line(PXA255_INT_GPIO1, 1);
+ else
+ set_irq_line(PXA255_INT_GPIO0, 1);
+ }
+ }
+ else if (offset < 64)
+ {
+ const uint32_t old = m_gpio_regs.gplr1;
+ m_gpio_regs.gplr1 &= ~(1 << (offset - 32));
+ m_gpio_regs.gplr1 |= ~(val << (offset - 32));
+
+ const uint32_t rising = ~old & m_gpio_regs.gplr1;
+ const uint32_t falling = old & ~m_gpio_regs.gplr1;
+
+ const uint32_t old_gedr = m_gpio_regs.gedr1;
+ m_gpio_regs.gedr1 |= (rising & m_gpio_regs.grer1);
+ m_gpio_regs.gedr1 |= (falling & m_gpio_regs.gfer1);
+ if (old_gedr != m_gpio_regs.gedr1)
+ {
+ LOGMASKED(LOG_GPIO, "pxa255: Edge detected on GPIO%d\n", offset);
+ set_irq_line(PXA255_INT_GPIO84_2, 1);
+ }
+ }
+ else if (offset < 85)
+ {
+ const uint32_t old = m_gpio_regs.gplr2;
+ m_gpio_regs.gplr2 &= ~(1 << (offset - 64));
+ m_gpio_regs.gplr2 |= ~(val << (offset - 64));
+
+ const uint32_t rising = ~old & m_gpio_regs.gplr2;
+ const uint32_t falling = old & ~m_gpio_regs.gplr2;
+
+ const uint32_t old_gedr = m_gpio_regs.gedr2;
+ m_gpio_regs.gedr2 |= (rising & m_gpio_regs.grer2);
+ m_gpio_regs.gedr2 |= (falling & m_gpio_regs.gfer2);
+ if (old_gedr != m_gpio_regs.gedr2)
+ {
+ LOGMASKED(LOG_GPIO, "pxa255: Edge detected on GPIO%d\n", offset);
+ set_irq_line(PXA255_INT_GPIO84_2, 1);
+ }
+ }
+}
+
+uint32_t pxa255_periphs_device::gpio_r(offs_t offset, uint32_t mem_mask)
+{
switch(PXA255_GPIO_BASE_ADDR | (offset << 2))
{
case PXA255_GPLR0:
@@ -844,17 +1007,39 @@ void pxa255_periphs_device::gpio_w(offs_t offset, uint32_t data, uint32_t mem_ma
m_gpio_regs.gfer2 = data;
break;
case PXA255_GEDR0:
+ {
LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Edge Detect Status Register 0: %08x & %08x\n", m_gpio_regs.gedr0, mem_mask);
+ const uint32_t old = m_gpio_regs.gedr0;
m_gpio_regs.gedr0 &= ~data;
+ const uint32_t lowered = old & ~m_gpio_regs.gedr0;
+ if (BIT(lowered, 0))
+ set_irq_line(PXA255_INT_GPIO0, 0);
+ else if (BIT(lowered, 1))
+ set_irq_line(PXA255_INT_GPIO1, 0);
+ else if ((lowered & 0xfffffffc) && !m_gpio_regs.gedr0 && !m_gpio_regs.gedr1 && !m_gpio_regs.gedr2)
+ set_irq_line(PXA255_INT_GPIO84_2, 0);
break;
+ }
case PXA255_GEDR1:
+ {
LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Edge Detect Status Register 1: %08x & %08x\n", m_gpio_regs.gedr1, mem_mask);
+ const uint32_t old = m_gpio_regs.gedr1;
m_gpio_regs.gedr1 &= ~data;
+ const uint32_t lowered = old & !m_gpio_regs.gedr1;
+ if (lowered && !m_gpio_regs.gedr0 && !m_gpio_regs.gedr1 && !m_gpio_regs.gedr2)
+ set_irq_line(PXA255_INT_GPIO84_2, 0);
break;
+ }
case PXA255_GEDR2:
+ {
LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Edge Detect Status Register 2: %08x & %08x\n", m_gpio_regs.gedr2, mem_mask);
+ const uint32_t old = m_gpio_regs.gedr2;
m_gpio_regs.gedr2 &= ~data;
+ const uint32_t lowered = old & !m_gpio_regs.gedr2;
+ if (lowered && !m_gpio_regs.gedr0 && !m_gpio_regs.gedr1 && !m_gpio_regs.gedr2)
+ set_irq_line(PXA255_INT_GPIO84_2, 0);
break;
+ }
case PXA255_GAFR0_L:
LOGMASKED(LOG_GPIO, "pxa255_gpio_w: GPIO Alternate Function Register 0 Lower: %08x & %08x\n", m_gpio_regs.gafr0l, mem_mask);
m_gpio_regs.gafr0l = data;
@@ -987,15 +1172,15 @@ void pxa255_periphs_device::lcd_check_load_next_branch(int channel)
}
}
-TIMER_CALLBACK_MEMBER(pxa255_periphs_device::lcd_dma_eof)
+void pxa255_periphs_device::lcd_dma_eof_tick(int channel)
{
LOGMASKED(LOG_LCD_DMA, "End of frame callback\n" );
- if(m_lcd_regs.dma[param].ldcmd & PXA255_LDCMD_EOFINT)
+ if(m_lcd_regs.dma[channel].ldcmd & PXA255_LDCMD_EOFINT)
{
- m_lcd_regs.liidr = m_lcd_regs.dma[param].fidr;
+ m_lcd_regs.liidr = m_lcd_regs.dma[channel].fidr;
m_lcd_regs.lcsr |= PXA255_LCSR_EOF;
}
- lcd_check_load_next_branch(param);
+ lcd_check_load_next_branch(channel);
lcd_irq_check();
}
@@ -1168,20 +1353,182 @@ void pxa255_periphs_device::lcd_w(address_space &space, offs_t offset, uint32_t
}
}
+uin32_t pxa255_periphs_device::power_r(offs_t offset, uint32_t mem_mask)
+{
+ switch(PXA255_POWER_BASE_ADDR | (offset << 2))
+ {
+ case PXA255_PMCR:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Control Register: %08x\n", machine().describe_context(), m_power_regs.pmcr);
+ return m_power_regs.pmcr;
+ case PXA255_PSSR:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Sleep Status Register: %08x\n", machine().describe_context(), m_power_regs.pssr);
+ return m_power_regs.pssr;
+ case PXA255_PSPR:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Scratch Pad Register: %08x\n", machine().describe_context(), m_power_regs.pspr);
+ return m_power_regs.pspr;
+ case PXA255_PWER:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Wake-up Enable Register: %08x\n", machine().describe_context(), m_power_regs.pwer);
+ return m_power_regs.pwer;
+ case PXA255_PRER:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Rising-Edge Detect Enable Register: %08x\n", machine().describe_context(), m_power_regs.prer);
+ return m_power_regs.prer;
+ case PXA255_PFER:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Falling-Edge Detect Enable Register: %08x\n", machine().describe_context(), m_power_regs.pfer);
+ return m_power_regs.pfer;
+ case PXA255_PEDR:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Edge Detect Status Register: %08x\n", machine().describe_context(), m_power_regs.pedr);
+ return m_power_regs.pedr;
+ case PXA255_PCFR:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager General Configuration Register: %08x\n", machine().describe_context(), m_power_regs.pcfr);
+ return m_power_regs.pcfr;
+ case PXA255_PGSR0:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register for GP[31-0]: %08x\n", machine().describe_context(), m_power_regs.pgsr0);
+ return m_power_regs.pgsr0;
+ case PXA255_PGSR1:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register for GP[63-32]: %08x\n", machine().describe_context(), m_power_regs.pgsr1);
+ return m_power_regs.pgsr1;
+ case PXA255_PGSR2:
+ LOGMASKED(LOG_POWER, "%s: power_r: Power Manager GPIO Sleep State Register for GP[84-64]: %08x\n", machine().describe_context(), m_power_regs.pgsr2);
+ return m_power_regs.pgsr2;
+ case PXA255_RCSR:
+ LOGMASKED(LOG_POWER, "%s: power_r: Reset Controller Status Register: %08x\n", machine().describe_context(), m_power_regs.rcsr);
+ return m_power_regs.rcsr;
+ case PXA255_PMFW:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Fast Sleep Walk-Up Configuration Register: %08x\n", machine().describe_context(), m_power_regs.pmfw);
+ return m_power_regs.pmfw;
+ default:
+ LOGMASKED(LOG_POWER | LOG_UNKNOWN, "%s: power_r: Unknown address: %08x\n", machine().describe_context(), PXA255_POWER_BASE_ADDR | (offset << 2));
+ break;
+ }
+ return 0;
+}
+
+void pxa255_periphs_device::power_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ switch(PXA255_POWER_BASE_ADDR | (offset << 2))
+ {
+ case PXA255_PMCR:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pmcr);
+ break;
+ case PXA255_PSSR:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Sleep Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ m_power_regs.pssr &= ~(data & 0x00000037);
+ break;
+ case PXA255_PSPR:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Scratch Pad Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pspr);
+ break;
+ case PXA255_PWER:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Wake-Up Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pwer);
+ break;
+ case PXA255_PRER:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Rising-Edge Detect Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.prer);
+ break;
+ case PXA255_PFER:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Falling-Edge Detect Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pfer);
+ break;
+ case PXA255_PEDR:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Edge Detect Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ m_power_regs.pedr &= ~(data & 0x0000ffff);
+ break;
+ case PXA255_PCFR:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager General Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pcfr);
+ break;
+ case PXA255_PGSR0:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pgsr0);
+ break;
+ case PXA255_PGSR1:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pgsr1);
+ break;
+ case PXA255_PGSR2:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager GPIO Sleep State Register 2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pgsr2);
+ break;
+ case PXA255_PMFW:
+ LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Fast Sleep Walk-Up Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_power_regs.pmfw);
+ break;
+ default:
+ LOGMASKED(LOG_POWER | LOG_UNKNOWN, "%s: power_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), PXA255_POWER_BASE_ADDR | (offset << 2),
+ data, mem_mask);
+ break;
+ }
+}
+
+/*
+ PXA255 Clock controller
+
+ pg. 96 to 100, PXA255 Processor Developers Manual [278693-002].pdf
+
+*/
+
+uint32_t pxa255_periphs_device::clocks_r(offs_t offset, uint32_t mem_mask)
+{
+ switch(PXA255_CLOCKS_BASE_ADDR | (offset << 2))
+ {
+ case PXA255_CCCR:
+ LOGMASKED(LOG_CLOCKS, "%s: clocks_r: Core Clock Configuration Register: %08x\n", machine().describe_context(), m_clocks_regs.cccr);
+ return m_clocks_regs.cccr;
+ case PXA255_CKEN:
+ LOGMASKED(LOG_CLOCKS, "%s: clocks_r: Clock Enable Register: %08x\n", machine().describe_context(), m_clocks_regs.cken);
+ return m_clocks_regs.cken;
+ case PXA255_OSCC:
+ LOGMASKED(LOG_CLOCKS, "%s: clocks_r: Oscillator Configuration Register: %08x\n", machine().describe_context(), m_clocks_regs.oscc);
+ return BIT(m_clocks_regs.oscc, 0);
+ default:
+ LOGMASKED(LOG_CLOCKS | LOG_UNKNOWN, "%s: clocks_r: Unknown address: %08x\n", machine().describe_context(), PXA255_CLOCKS_BASE_ADDR | (offset << 2));
+ break;
+ }
+ return 0;
+}
+
+void pxa255_periphs_device::clocks_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ switch(PXA255_CLOCKS_BASE_ADDR | (offset << 2))
+ {
+ case PXA255_CCCR:
+ LOGMASKED(LOG_CLOCKS, "%s: clocks_w: Core Clock Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_clocks_regs.cccr);
+ break;
+ case PXA255_CKEN:
+ LOGMASKED(LOG_CLOCKS, "%s: clocks_w: Clock Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_clocks_regs.cken);
+ break;
+ case PXA255_OSCC:
+ LOGMASKED(LOG_CLOCKS, "%s: clocks_w: Oscillator Configuration Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ if (BIT(data, 1))
+ {
+ m_clocks_regs.oscc |= 0x00000003;
+ }
+ break;
+ default:
+ LOGMASKED(LOG_CLOCKS | LOG_UNKNOWN, "%s: clocks_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), PXA255_CLOCKS_BASE_ADDR | (offset << 2),
+ data, mem_mask);
+ break;
+ }
+}
+
void pxa255_periphs_device::device_start()
{
for (int index = 0; index < 16; index++)
{
- m_dma_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::dma_dma_end),this));
+ m_dma_regs.timer[index] = timer_alloc(TIMER_DMA0 + index);
}
for (int index = 0; index < 4; index++)
{
- m_ostimer_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::ostimer_match),this));
+ m_ostimer_regs.timer[index] = timer_alloc(TIMER_OSTIMER0 + index);
}
- m_lcd_regs.dma[0].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::lcd_dma_eof),this));
- m_lcd_regs.dma[1].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::lcd_dma_eof),this));
+ m_lcd_regs.dma[0].eof = timer_alloc(TIMER_LCD_EOF0);
+ m_lcd_regs.dma[1].eof = timer_alloc(TIMER_LCD_EOF0 + 1);
m_lcd_palette = make_unique_clear<uint32_t[]>(0x100);
m_lcd_framebuffer = make_unique_clear<uint8_t[]>(0x100000);
@@ -1194,6 +1541,8 @@ void pxa255_periphs_device::device_start()
m_gpio0_r.resolve_safe(0xffffffff);
m_gpio1_r.resolve_safe(0xffffffff);
m_gpio2_r.resolve_safe(0xffffffff);
+
+ m_rtc_regs.timer = timer_alloc(TIMER_RTC);
}
void pxa255_periphs_device::device_reset()
@@ -1203,10 +1552,31 @@ void pxa255_periphs_device::device_reset()
m_dma_regs.dcsr[index] = 0x00000008;
}
+ m_rtc_regs.rcnr = 0x00000000;
+ m_rtc_regs.rtar = 0x00000000;
+ m_rtc_regs.rtsr = 0x00000000;
+ m_rtc_regs.rttr = 0x00007fff;
+ m_rtc_regs.timer->adjust(attotime::from_hz(1));
+
memset(&m_intc_regs, 0, sizeof(m_intc_regs));
m_lcd_regs.trgbr = 0x00aa5500;
m_lcd_regs.tcr = 0x0000754f;
+
+ memset(&m_power_regs, 0, sizeof(m_power_regs));
+ memset(&m_clocks_regs, 0, sizeof(m_clocks_regs));
+}
+
+void pxa255_periphs_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id < TIMER_OSTIMER0)
+ dma_end_tick(id);
+ else if (id < TIMER_LCD_EOF0)
+ ostimer_match_tick(id - TIMER_OSTIMER0);
+ else if (id < TIMER_RTC)
+ lcd_dma_eof_tick(id - TIMER_LCD_EOF0);
+ else if (id == TIMER_RTC)
+ rtc_tick();
}
uint32_t pxa255_periphs_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)