Changeset 41ce4d9 in mainline


Ignore:
Timestamp:
2010-07-15T10:24:39Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
074c9bd
Parents:
0e796cc
Message:

Make use of s3c24xx timer and interrupt controller as a clock source on the GTA02.

Location:
kernel
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/src/mach/gta02/gta02.c

    r0e796cc r41ce4d9  
    4141#include <genarch/fb/visuals.h>
    4242#include <genarch/drivers/s3c24xx_uart/s3c24xx_uart.h>
     43#include <genarch/drivers/s3c24xx_irqc/s3c24xx_irqc.h>
     44#include <genarch/drivers/s3c24xx_timer/s3c24xx_timer.h>
     45#include <interrupt.h>
    4346#include <ddi/ddi.h>
     47#include <ddi/device.h>
    4448
    4549#define GTA02_MEMORY_START      0x30000000      /* physical */
     
    5256/** GTA02 framebuffer base address */
    5357#define GTA02_FB_BASE           0x08800000
     58
     59/** IRQ number used for clock */
     60#define GTA02_TIMER_IRQ         S3C24XX_INT_TIMER0
    5461
    5562static void gta02_init(void);
     
    6269static void gta02_input_init(void);
    6370
     71static void gta02_timer_irq_init(void);
     72static void gta02_timer_start(void);
     73static irq_ownership_t gta02_timer_irq_claim(irq_t *irq);
     74static void gta02_timer_irq_handler(irq_t *irq);
     75
    6476static void *gta02_scons_out;
     77static s3c24xx_irqc_t *gta02_irqc;
     78static s3c24xx_timer_t *gta02_timer;
     79
     80static irq_t gta02_timer_irq;
    6581
    6682struct arm_machine_ops gta02_machine_ops = {
     
    7894{
    7995        gta02_scons_out = (void *) hw_map(GTA02_SCONS_BASE, PAGE_SIZE);
     96        gta02_irqc = (void *) hw_map(S3C24XX_IRQC_ADDRESS, PAGE_SIZE);
     97        gta02_timer = (void *) hw_map(S3C24XX_TIMER_ADDRESS, PAGE_SIZE);
     98
     99        /* Make all interrupt sources use IRQ mode (not FIQ). */
     100        pio_write_32(&gta02_irqc->intmod, 0x00000000);
     101
     102        /* Disable all interrupt sources. */
     103        pio_write_32(&gta02_irqc->intmsk, 0xffffffff);
     104
     105        /* Disable interrupts from all sub-sources. */
     106        pio_write_32(&gta02_irqc->intsubmsk, 0xffffffff);
    80107}
    81108
    82109static void gta02_timer_irq_start(void)
    83110{
     111        gta02_timer_irq_init();
     112        gta02_timer_start();
    84113}
    85114
     
    101130static void gta02_irq_exception(unsigned int exc_no, istate_t *istate)
    102131{
     132        uint32_t inum;
     133
     134        inum = pio_read_32(&gta02_irqc->intoffset);
     135
     136        irq_t *irq = irq_dispatch_and_lock(inum);
     137        if (irq) {
     138                /* The IRQ handler was found. */
     139                irq->handler(irq);
     140                spinlock_unlock(&irq->lock);
     141        } else {
     142                /* Spurious interrupt.*/
     143                printf("cpu%d: spurious interrupt (inum=%d)\n",
     144                    CPU->id, inum);
     145        }
     146
     147        /* Clear interrupt condition in the interrupt controller. */
     148        pio_write_32(&gta02_irqc->srcpnd, S3C24XX_INT_BIT(inum));
     149        pio_write_32(&gta02_irqc->intpnd, S3C24XX_INT_BIT(inum));
    103150}
    104151
     
    140187}
    141188
     189static void gta02_timer_irq_init(void)
     190{
     191        irq_initialize(&gta02_timer_irq);
     192        gta02_timer_irq.devno = device_assign_devno();
     193        gta02_timer_irq.inr = GTA02_TIMER_IRQ;
     194        gta02_timer_irq.claim = gta02_timer_irq_claim;
     195        gta02_timer_irq.handler = gta02_timer_irq_handler;
     196
     197        irq_register(&gta02_timer_irq);
     198}
     199
     200static irq_ownership_t gta02_timer_irq_claim(irq_t *irq)
     201{
     202        return IRQ_ACCEPT;
     203}
     204
     205static void gta02_timer_irq_handler(irq_t *irq)
     206{
     207        /*
     208         * We are holding a lock which prevents preemption.
     209         * Release the lock, call clock() and reacquire the lock again.
     210         */
     211        spinlock_unlock(&irq->lock);
     212        clock();
     213        spinlock_lock(&irq->lock);
     214}
     215
     216static void gta02_timer_start(void)
     217{
     218        s3c24xx_timer_t *timer = gta02_timer;
     219
     220        /*
     221         * See S3C2442B user manual chapter 10 (PWM Timer) for description
     222         * of timer operation. Starting a timer is described in the
     223         * section 'Timer initialization using manual update bit and
     224         * inverter bit'.
     225         */
     226
     227        /* Set prescaler values to zero. (no pre-divison), no dead zone. */
     228        pio_write_32(&timer->tcfg0, 0);
     229
     230        /* No DMA request, divider value = 2 for all timers. */
     231        pio_write_32(&timer->tcfg1, 0);
     232
     233        /* Stop all timers. */
     234        pio_write_32(&timer->tcon, 0);
     235
     236        /* Start counting from 64k-1. Compare value is irrelevant. */
     237        pio_write_32(&timer->timer[0].cntb, 0xffff);
     238        pio_write_32(&timer->timer[0].cmpb, 0);
     239
     240        /* Enable interrupts from timer0 */
     241        pio_write_32(&gta02_irqc->intmsk, pio_read_32(&gta02_irqc->intmsk) &
     242            ~S3C24XX_INT_BIT(S3C24XX_INT_TIMER0));
     243
     244        /* Load data from tcntb0/tcmpb0 into tcnt0/tcmp0. */
     245        pio_write_32(&timer->tcon, TCON_T0_AUTO_RLD | TCON_T0_MUPDATE);
     246
     247        /* Start timer 0. Inverter is off. */
     248        pio_write_32(&timer->tcon, TCON_T0_AUTO_RLD | TCON_T0_START);
     249}
     250
    142251/** @}
    143252 */
Note: See TracChangeset for help on using the changeset viewer.