source: mainline/kernel/arch/arm32/src/mach/gta02/gta02.c@ 3c9646b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3c9646b was f9ab562, checked in by Jakub Jermar <jakub@…>, 13 years ago

Remove support for the testarm machine.

  • Property mode set to 100644
File size: 8.3 KB
RevLine 
[7c866dc]1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[f9ab562]29/** @addtogroup arm32gta02
[7c866dc]30 * @{
31 */
32/** @file
33 * @brief Openmoko GTA02 (Neo FreeRunner) platform driver.
34 */
35
36#include <arch/exception.h>
37#include <arch/mach/gta02/gta02.h>
[d7ef14b]38#include <arch/mm/page.h>
[f1fc83a]39#include <mm/page.h>
[d4673296]40#include <mm/km.h>
[5c032932]41#include <genarch/fb/fb.h>
[c0699467]42#include <abi/fb/visuals.h>
[f1fc83a]43#include <genarch/drivers/s3c24xx_uart/s3c24xx_uart.h>
[41ce4d9]44#include <genarch/drivers/s3c24xx_irqc/s3c24xx_irqc.h>
45#include <genarch/drivers/s3c24xx_timer/s3c24xx_timer.h>
[ec08286]46#include <genarch/srln/srln.h>
[a9b5b5f]47#include <sysinfo/sysinfo.h>
[41ce4d9]48#include <interrupt.h>
[5c032932]49#include <ddi/ddi.h>
[41ce4d9]50#include <ddi/device.h>
[d7ef14b]51
52#define GTA02_MEMORY_START 0x30000000 /* physical */
53#define GTA02_MEMORY_SIZE 0x08000000 /* 128 MB */
[f1fc83a]54#define GTA02_MEMORY_SKIP 0x8000
55
56/** GTA02 serial console UART address (UART S3C24XX CPU UART channel 2). */
57#define GTA02_SCONS_BASE 0x50008000
[7c866dc]58
[5c032932]59/** GTA02 framebuffer base address */
60#define GTA02_FB_BASE 0x08800000
61
[41ce4d9]62/** IRQ number used for clock */
63#define GTA02_TIMER_IRQ S3C24XX_INT_TIMER0
64
[7c866dc]65static void gta02_init(void);
66static void gta02_timer_irq_start(void);
67static void gta02_cpu_halt(void);
[2686705]68static void gta02_get_memory_extents(uintptr_t *start, size_t *size);
[7c866dc]69static void gta02_irq_exception(unsigned int exc_no, istate_t *istate);
70static void gta02_frame_init(void);
71static void gta02_output_init(void);
72static void gta02_input_init(void);
[ecf083dd]73static size_t gta02_get_irq_count(void);
[eff1f033]74static const char *gta02_get_platform_name(void);
[7c866dc]75
[41ce4d9]76static void gta02_timer_irq_init(void);
77static void gta02_timer_start(void);
78static irq_ownership_t gta02_timer_irq_claim(irq_t *irq);
79static void gta02_timer_irq_handler(irq_t *irq);
80
[ec08286]81static outdev_t *gta02_scons_dev;
82static s3c24xx_irqc_t gta02_irqc;
[41ce4d9]83static s3c24xx_timer_t *gta02_timer;
84
85static irq_t gta02_timer_irq;
[f1fc83a]86
[7c866dc]87struct arm_machine_ops gta02_machine_ops = {
88 gta02_init,
89 gta02_timer_irq_start,
90 gta02_cpu_halt,
[d7ef14b]91 gta02_get_memory_extents,
[7c866dc]92 gta02_irq_exception,
93 gta02_frame_init,
94 gta02_output_init,
[ecf083dd]95 gta02_input_init,
[eff1f033]96 gta02_get_irq_count,
97 gta02_get_platform_name
[7c866dc]98};
99
100static void gta02_init(void)
101{
[ec08286]102 s3c24xx_irqc_regs_t *irqc_regs;
103
[adec5b45]104 gta02_timer = (void *) km_map(S3C24XX_TIMER_ADDRESS, PAGE_SIZE,
105 PAGE_NOT_CACHEABLE);
106 irqc_regs = (void *) km_map(S3C24XX_IRQC_ADDRESS, PAGE_SIZE,
107 PAGE_NOT_CACHEABLE);
[41ce4d9]108
[ec08286]109 /* Initialize interrupt controller. */
110 s3c24xx_irqc_init(&gta02_irqc, irqc_regs);
[7c866dc]111}
112
113static void gta02_timer_irq_start(void)
114{
[41ce4d9]115 gta02_timer_irq_init();
116 gta02_timer_start();
[7c866dc]117}
118
119static void gta02_cpu_halt(void)
120{
121}
122
[d7ef14b]123/** Get extents of available memory.
124 *
[6250c37]125 * @param start Place to store memory start address (physical).
[d7ef14b]126 * @param size Place to store memory size.
127 */
[2686705]128static void gta02_get_memory_extents(uintptr_t *start, size_t *size)
[7c866dc]129{
[6250c37]130 *start = GTA02_MEMORY_START + GTA02_MEMORY_SKIP;
[d7ef14b]131 *size = GTA02_MEMORY_SIZE - GTA02_MEMORY_SKIP;
[7c866dc]132}
133
134static void gta02_irq_exception(unsigned int exc_no, istate_t *istate)
135{
[41ce4d9]136 uint32_t inum;
137
[ec08286]138 /* Determine IRQ number. */
139 inum = s3c24xx_irqc_inum_get(&gta02_irqc);
140
141 /* Clear interrupt condition in the interrupt controller. */
142 s3c24xx_irqc_clear(&gta02_irqc, inum);
[41ce4d9]143
144 irq_t *irq = irq_dispatch_and_lock(inum);
145 if (irq) {
146 /* The IRQ handler was found. */
147 irq->handler(irq);
148 spinlock_unlock(&irq->lock);
149 } else {
150 /* Spurious interrupt.*/
151 printf("cpu%d: spurious interrupt (inum=%d)\n",
152 CPU->id, inum);
153 }
[7c866dc]154}
155
156static void gta02_frame_init(void)
157{
158}
159
160static void gta02_output_init(void)
161{
[5c032932]162#ifdef CONFIG_FB
163 fb_properties_t prop = {
164 .addr = GTA02_FB_BASE,
165 .offset = 0,
166 .x = 480,
167 .y = 640,
168 .scan = 960,
169 .visual = VISUAL_RGB_5_6_5_LE
170 };
171
172 outdev_t *fb_dev = fb_init(&prop);
[b366a6f4]173 if (fb_dev)
[5c032932]174 stdout_wire(fb_dev);
175#endif
[f1fc83a]176
[ec08286]177 /* Initialize serial port of the debugging console. */
[b366a6f4]178 gta02_scons_dev =
179 s3c24xx_uart_init(GTA02_SCONS_BASE, S3C24XX_INT_UART2);
[ec08286]180
[277cf60]181 if (gta02_scons_dev) {
[ec08286]182 /* Create output device. */
183 stdout_wire(gta02_scons_dev);
184 }
[a9b5b5f]185
186 /*
187 * This is the necessary evil until the userspace driver is entirely
188 * self-sufficient.
189 */
190 sysinfo_set_item_val("s3c24xx_uart", NULL, true);
191 sysinfo_set_item_val("s3c24xx_uart.inr", NULL, S3C24XX_INT_UART2);
192 sysinfo_set_item_val("s3c24xx_uart.address.physical", NULL,
193 (uintptr_t) GTA02_SCONS_BASE);
194
[7c866dc]195}
196
197static void gta02_input_init(void)
198{
[277cf60]199 s3c24xx_uart_t *scons_inst;
[ec08286]200
201 if (gta02_scons_dev) {
202 /* Create input device. */
203 scons_inst = (void *) gta02_scons_dev->data;
204
205 srln_instance_t *srln_instance = srln_init();
206 if (srln_instance) {
207 indev_t *sink = stdin_wire();
208 indev_t *srln = srln_wire(srln_instance, sink);
209 s3c24xx_uart_input_wire(scons_inst, srln);
210
211 /* Enable interrupts from UART2 */
212 s3c24xx_irqc_src_enable(&gta02_irqc,
213 S3C24XX_INT_UART2);
214
215 /* Enable interrupts from UART2 RXD */
216 s3c24xx_irqc_subsrc_enable(&gta02_irqc,
217 S3C24XX_SUBINT_RXD2);
218 }
219 }
[527298a]220
221 /* Enable interrupts from ADC */
222 s3c24xx_irqc_src_enable(&gta02_irqc, S3C24XX_INT_ADC);
223
224 /* Enable interrupts from ADC sub-sources */
225 s3c24xx_irqc_subsrc_enable(&gta02_irqc, S3C24XX_SUBINT_ADC_S);
226 s3c24xx_irqc_subsrc_enable(&gta02_irqc, S3C24XX_SUBINT_TC);
[7c866dc]227}
228
[ecf083dd]229size_t gta02_get_irq_count(void)
230{
231 return GTA02_IRQ_COUNT;
232}
233
[eff1f033]234const char *gta02_get_platform_name(void)
235{
236 return "gta02";
237}
238
[41ce4d9]239static void gta02_timer_irq_init(void)
240{
241 irq_initialize(&gta02_timer_irq);
242 gta02_timer_irq.devno = device_assign_devno();
243 gta02_timer_irq.inr = GTA02_TIMER_IRQ;
244 gta02_timer_irq.claim = gta02_timer_irq_claim;
245 gta02_timer_irq.handler = gta02_timer_irq_handler;
246
247 irq_register(&gta02_timer_irq);
248}
249
250static irq_ownership_t gta02_timer_irq_claim(irq_t *irq)
251{
252 return IRQ_ACCEPT;
253}
254
255static void gta02_timer_irq_handler(irq_t *irq)
256{
257 /*
258 * We are holding a lock which prevents preemption.
259 * Release the lock, call clock() and reacquire the lock again.
260 */
261 spinlock_unlock(&irq->lock);
262 clock();
263 spinlock_lock(&irq->lock);
264}
265
266static void gta02_timer_start(void)
267{
268 s3c24xx_timer_t *timer = gta02_timer;
269
270 /*
271 * See S3C2442B user manual chapter 10 (PWM Timer) for description
272 * of timer operation. Starting a timer is described in the
273 * section 'Timer initialization using manual update bit and
274 * inverter bit'.
275 */
276
[24697c3]277 /*
278 * GTA02 PCLK should be 100 MHz.
279 * Timer input freq. = PCLK / divider / (1+prescaler)
280 * 100 MHz / 2 / (1+7) / 62500 ~= 100 Hz
281 */
282#if HZ != 100
283#warning Other HZ than 100 not suppored.
284#endif
285
286 /* Set prescaler values. No pre-divison, no dead zone. */
287 pio_write_32(&timer->tcfg0, 7); /* prescale 1/8 */
[41ce4d9]288
289 /* No DMA request, divider value = 2 for all timers. */
290 pio_write_32(&timer->tcfg1, 0);
291
292 /* Stop all timers. */
293 pio_write_32(&timer->tcon, 0);
294
295 /* Start counting from 64k-1. Compare value is irrelevant. */
[24697c3]296 pio_write_32(&timer->timer[0].cntb, 62500);
[41ce4d9]297 pio_write_32(&timer->timer[0].cmpb, 0);
298
299 /* Enable interrupts from timer0 */
[ec08286]300 s3c24xx_irqc_src_enable(&gta02_irqc, S3C24XX_INT_TIMER0);
[41ce4d9]301
302 /* Load data from tcntb0/tcmpb0 into tcnt0/tcmp0. */
303 pio_write_32(&timer->tcon, TCON_T0_AUTO_RLD | TCON_T0_MUPDATE);
304
305 /* Start timer 0. Inverter is off. */
306 pio_write_32(&timer->tcon, TCON_T0_AUTO_RLD | TCON_T0_START);
307}
308
[7c866dc]309/** @}
310 */
Note: See TracBrowser for help on using the repository browser.