⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skyeye_mach_s3c2440.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
字号:
/*
	skyeye_mach_s3c2440.c - define machine S3C2440 for skyeye
	Copyright (C) 2005 Skyeye Develop Group
	for help please send mail to <skyeye-developer@lists.gro.clinux.org>
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
*/

#include "armdefs.h"
#include "s3c2440.h"
//zzc:2005-1-1
#ifdef __CYGWIN__
//chy 2005-07-28
#include <time.h>

struct timeval
{
  long tv_sec;
  long tv_usec;
};
#endif

#define TC_DIVISOR	(1)	/* Set your BogoMips here :) may move elsewhere */

typedef struct s3c2440_io
{
  u32 srcpnd;			/* Indicate the interrupt request status */
  u32 intmod;			/* Interrupt mode register */
  u32 intmsk;			/* Determine which interrupt source is masked */
  u32 priority;			/* IRQ priority control register */
  u32 intpnd;			/* Indicate the interrupt request status */
  u32 intoffset;		/* Indicate the IRQ interrupt request source */
  u32 subsrcpnd;		/* Indicate the interrupt request status */
  u32 intsubmsk;		/* Determin which interrupt source is masked */
  struct s3c2440_timer_io timer;	/* Timer */
  struct s3c2440_uart_io uart0;	/* uart0 */
  struct s3c2440_clkpower clkpower;	/* clock and power management */

  int tc_prescale;


} s3c2440_io_t;
static s3c2440_io_t s3c2440_io;
#define io s3c2440_io


static inline void
s3c2440_set_subsrcint (unsigned int irq)
{
  io.subsrcpnd |= irq;
}
static inline void
s3c2440_update_subsrcint ()
{
  u32 requests;
  s3c2440_set_subsrcint (UART_INT_TXD << (0 * 3));
  s3c2440_set_subsrcint (UART_INT_TXD << (1 * 3));
  s3c2440_set_subsrcint (UART_INT_TXD << (2 * 3));
  requests = ((io.subsrcpnd & (~io.intsubmsk)) & 0x7fff);
  if (requests & 0x7)
    io.srcpnd |= INT_UART0;
  if (requests & 0x38)
    io.srcpnd |= INT_UART1;
  if (requests & 0x1c0)
    io.srcpnd |= INT_UART2;
  if (requests & 0x600)
    io.srcpnd |= INT_ADC;
}
static void
s3c2440_update_int (ARMul_State * state)
{
  ARMword requests;
  s3c2440_update_subsrcint ();
  requests = io.srcpnd & (~io.intmsk & INT_MASK_INIT);
  state->NfiqSig = (requests & io.intmod) ? LOW : HIGH;
  state->NirqSig = (requests & ~io.intmod) ? LOW : HIGH;
}

static void
s3c2440_io_reset (ARMul_State * state)
{
  memset (&s3c2440_io, 0, sizeof (s3c2440_io));
  io.tc_prescale = TC_DIVISOR;
  io.uart0.ulcon = UART_ULCON_INIT;
  io.uart0.utrstat = UART_UTRSTAT_INIT;
  //io.timer.tcnt[4] = 25350;

  io.clkpower.locktime = 0x00FFFFFF;
  io.clkpower.mpllcon = 0x0005C080;
  io.clkpower.upllcon = 0x00028080;
  io.clkpower.clkcon = 0x7FFF0;
  io.clkpower.clkslow = 0x4;

  io.intmsk = INT_MASK_INIT;
  io.intpnd = 0x0;
}

/* s3c2440 io_do_cycle */
static void
s3c2440_io_do_cycle (ARMul_State * state)
{
  io.tc_prescale--;
  if (io.tc_prescale < 0)
    {
      io.tc_prescale = TC_DIVISOR;
      if ((io.timer.tcon & 0x100000) != 0)
	{
	  io.timer.tcnt[4]--;
	  if (io.timer.tcnt[4] < 0)
	    {
	      io.timer.tcnt[4] = io.timer.tcntb[4];
	      /*timer 4 hasn't tcmp */
	      //io.timer.tcmp[4] = io.timer.tcmpb[4];
	      io.timer.tcnto[4] = io.timer.tcntb[4];
	      io.srcpnd |= INT_TIMER4;
	      s3c2440_update_int (state);
	      return;
	    }
	}
      if (((io.uart0.utrstat & 0x1) == 0x0) && ((io.uart0.ucon & 0x3) == 0x1))
	{
	  fd_set rfds;
	  struct timeval tv;

	  FD_ZERO (&rfds);
	  FD_SET (skyeye_config.uart.fd_in, &rfds);
	  tv.tv_sec = 0;	//nonblock
	  tv.tv_usec = 0;

	  if (select
	      (skyeye_config.uart.fd_in + 1, &rfds, NULL, NULL, &tv) == 1)
	    {
	      unsigned char buf;
	      int n, i;
	      n = read (skyeye_config.uart.fd_in, &buf, 1);
	      if (n)
		{
		  //write (skyeye_config.uart.fd_out, &buf, 1);
		  io.uart0.urxh = (int) buf;
		  /* Receiver Ready
		   * */
		  io.uart0.utrstat |= (0x1);
		  /* pending usart0 interrupt
		   * */
		  s3c2440_set_subsrcint (UART_INT_RXD << (0 * 3));
		  //io.srcpnd |= INT_UART0;
		  s3c2440_update_int (state);
		  return;
		}
	    }
	}
      //s3c2440_update_int (state);
    }				/* if (io.tc_prescale < 0) */
}

static void
s3c2440_uart_read (u32 offset, u32 * data)
{
  switch (offset)
    {
    case ULCON:
      *data = io.uart0.ulcon;
      break;
    case UCON:
      *data = io.uart0.ucon;
      break;
    case UFCON:
      *data = io.uart0.ufcon;
      break;
    case UMCON:
      *data = io.uart0.umcon;
      break;
    case UTRSTAT:
      *data = io.uart0.utrstat;
      break;
    case UERSTAT:
      *data = io.uart0.uerstat;
      break;
    case UFSTAT:
      *data = io.uart0.ufstat;
      break;
    case UMSTAT:
      *data = io.uart0.umstat;
      break;
    case URXH:
      /* receive char
       * */
      *data = io.uart0.urxh;
      io.uart0.utrstat &= (~0x1);	/* clear strstat register bit[0] */
      break;
    case UBRDIV:
      *data = io.uart0.ubrdiv;
      break;
    default:
      break;
    }
  SKYEYE_DBG ("%s(0x%x, 0x%x)\n", __func__, offset, data);
}

static void
s3c2440_uart_write (ARMul_State * state, u32 offset, u32 data)
{

  SKYEYE_DBG ("s3c2440_uart_write(0x%x, 0x%x)\n", offset, data);
  switch (offset)
    {
    case ULCON:
      io.uart0.ulcon = data;
      break;
    case UCON:
      io.uart0.ucon = data;
      break;
    case UFCON:
      io.uart0.ufcon = data;
      break;
    case UMCON:
      io.uart0.umcon = data;
      break;
    case UTRSTAT:
      io.uart0.utrstat = data;
      break;
    case UERSTAT:
      io.uart0.uerstat = data;
      break;
    case UFSTAT:
      io.uart0.ufstat = data;
      break;
    case UMSTAT:
      io.uart0.umstat = data;
      break;
    case UTXH:
      {
	char c = data;
	write (skyeye_config.uart.fd_out, &c, 1);
	io.uart0.utrstat |= 0x6;	//set strstat register bit[0]
	if ((io.uart0.ucon & 0xc) == 0x4)
	  {
	    s3c2440_set_subsrcint (UART_INT_TXD << (0 * 3));
	    s3c2440_update_int (state);
	  }
      }
      break;
    case UBRDIV:
      io.uart0.ubrdiv = data;
      break;
    default:
      break;
    }
  SKYEYE_DBG ("%s(0x%x, 0x%x)\n", __func__, offset, data);
}

static void
s3c2440_timer_read (u32 offset, u32 * data)
{
  switch (offset)
    {
    case TCFG0:
      *data = io.timer.tcfg0;
      break;
    case TCFG1:
      *data = io.timer.tcfg1;
      break;
    case TCON:
      *data = io.timer.tcon;
      break;
    case TCNTB0:
    case TCNTB1:
    case TCNTB2:
    case TCNTB3:
    case TCNTB4:
      {
	int n = (offset - 0xC) / 0xC;
	*data = io.timer.tcntb[n];
      }
      break;
    case TCMPB0:
    case TCMPB1:
    case TCMPB2:
    case TCMPB3:
      {
	int n = (offset - 0x10) / 0xC;
	*data = io.timer.tcmpb[n];
      }
      break;
    case TCNTO0:
    case TCNTO1:
    case TCNTO2:
    case TCNTO3:
      {
	int n = (offset - 0x10) / 0xC;
	*data = io.timer.tcnto[n];
      }
      break;
    case TCNTO4:
      *data = io.timer.tcnto[4];
      break;
    default:
      break;
    }
}

static void
s3c2440_timer_write (ARMul_State * state, u32 offset, u32 data)
{
  switch (offset)
    {
    case TCFG0:
      io.timer.tcfg0 = data;
      break;
    case TCFG1:
      io.timer.tcfg1 = data;
      break;
    case TCON:
      {
	io.timer.tcon = data;
	if (io.timer.tcon)
	  {
	  }
      }
      break;
    case TCNTB0:
    case TCNTB1:
    case TCNTB2:
    case TCNTB3:
    case TCNTB4:
      {
	int n = (offset - 0xC) / 0xC;
	//io.timer.tcntb[n] = data;
	io.timer.tcntb[n] = 25350;
      }
      break;
    case TCMPB0:
    case TCMPB1:
    case TCMPB2:
    case TCMPB3:
      {
	int n = (offset - 0x10) / 0xC;
	io.timer.tcmpb[n] = data;
      }
      break;
    default:
      break;
    }
}

static ARMword
s3c2440_io_read_word (ARMul_State * state, ARMword addr)
{

  ARMword data = -1;
  int i;
  /*uart0 */
  if ((addr >= UART_CTL_BASE0) && (addr < (UART_CTL_BASE0 + UART_CTL_SIZE)))
    {
      s3c2440_uart_read ((u32) (addr - UART_CTL_BASE0), (u32 *) & data);
    }
  if ((addr >= PWM_CTL_BASE) && (addr < (PWM_CTL_BASE + PWM_CTL_SIZE)))
    {
      s3c2440_timer_read ((u32) (addr - PWM_CTL_BASE), (u32 *) & data);
    }
  switch (addr)
    {
    case SRCPND:
      data = io.srcpnd;
      break;
    case INTMOD:
      data = io.intmod;
      break;
    case INTMSK:
      data = io.intmsk;
      break;
    case PRIORITY:
      data = io.priority;
      break;
    case INTPND:
    case INTOFFSET:
      {
	/*find which interrupt is pending */
	int i;
	for (i = 0; i < 32; i++)
	  {
	    if (io.srcpnd & (1 << i))
	      break;
	  }
	if (i < 32)
	  {
	    io.intoffset = i;
	    io.intpnd = (1 << i);
	    if (addr == INTPND)
	      data = (1 << i);
	    else
	      data = i;
	  }
	else
	  data = 0;

      }
      io.intpnd = (1 << io.intoffset);
      //printf ("io.intoffset:%x, io.intpnd:%x (0x%08x) = 0x%08x\n", io.intoffset, io.intpnd, addr, data);
      break;
    case SUBSRCPND:
      data = io.subsrcpnd;
      break;
    case INTSUBMSK:
      data = io.intsubmsk;
      break;
      /* GPIO Register */
    case GSTATUS1:
      data = 0x32410000;
      break;
      /* Clock and Power Management Registers */
    case LOCKTIME:
      data = io.clkpower.locktime;
      break;
    case MPLLCON:
      data = io.clkpower.mpllcon;
      break;
    case UPLLCON:
      data = io.clkpower.upllcon;
      break;
    case CLKCON:
      data = io.clkpower.clkcon;
      break;
    case CLKSLOW:
      data = io.clkpower.clkslow;
      break;
    case CLKDIVN:
      data = io.clkpower.clkdivn;
      break;
    default:
      break;
    }
  return data;
}

static ARMword
s3c2440_io_read_byte (ARMul_State * state, ARMword addr)
{
  s3c2440_io_read_word (state, addr);
}

static ARMword
s3c2440_io_read_halfword (ARMul_State * state, ARMword addr)
{
  s3c2440_io_read_word (state, addr);
}

static void
s3c2440_io_write_word (ARMul_State * state, ARMword addr, ARMword data)
{
  if ((addr >= UART_CTL_BASE0) && (addr < UART_CTL_BASE0 + UART_CTL_SIZE))
    {
      s3c2440_uart_write (state, addr - UART_CTL_BASE0, data);
    }
  if ((addr >= PWM_CTL_BASE) && (addr < (PWM_CTL_BASE + PWM_CTL_SIZE)))
    {
      s3c2440_timer_write (state, addr - PWM_CTL_BASE, data);
    }
  switch (addr)
    {
    case SRCPND:
      io.srcpnd &= (~data & INT_MASK_INIT);
      break;
    case INTMOD:
      io.intmod = data;
      break;
    case INTMSK:
      io.intmsk = data;
      s3c2440_update_int (state);
      break;
    case PRIORITY:
      io.priority = data;
      break;
    case INTPND:
      io.intpnd &= (~data & INT_MASK_INIT);
      io.intoffset = 0;
      //printf ("io.intoffset:%x, io.intpnd:%x (0x%08x) = 0x%08x, pc:%x\n", io.intoffset, io.intpnd, addr, data, state->pc);
      break;
      /*read only */
      //case INTOFFSET:
      //      break;
    case SUBSRCPND:
      io.subsrcpnd &= (~data & INT_SUBMSK_INIT);
      break;
    case INTSUBMSK:
      io.intsubmsk = data;
      break;
    default:
      SKYEYE_DBG ("io_write_word(0x%08x) = 0x%08x\n", addr, data);
      break;
    }
}

static void
s3c2440_io_write_byte (ARMul_State * state, ARMword addr, ARMword data)
{
  SKYEYE_DBG ("SKYEYE: s3c2440_io_write_byte error\n");
  s3c2440_io_write_word (state, addr, data);
}

static void
s3c2440_io_write_halfword (ARMul_State * state, ARMword addr, ARMword data)
{
  SKYEYE_DBG ("SKYEYE: s3c2440_io_write_halfword error\n");
  s3c2440_io_write_word (state, addr, data);
}


void
s3c2440_mach_init (ARMul_State * state, machine_config_t * this_mach)
{
  ARMul_SelectProcessor (state, ARM_v4_Prop);
  /* ARM920T uses LOW */
  state->lateabtSig = LOW;

  state->Reg[1] = 241;		//ARCH_S3C2440
  this_mach->mach_io_do_cycle = s3c2440_io_do_cycle;
  this_mach->mach_io_reset = s3c2440_io_reset;
  this_mach->mach_io_read_byte = s3c2440_io_read_byte;
  this_mach->mach_io_write_byte = s3c2440_io_write_byte;
  this_mach->mach_io_read_halfword = s3c2440_io_read_halfword;
  this_mach->mach_io_write_halfword = s3c2440_io_write_halfword;
  this_mach->mach_io_read_word = s3c2440_io_read_word;
  this_mach->mach_io_write_word = s3c2440_io_write_word;

  this_mach->mach_update_int = s3c2440_update_int;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -