Annotation of sys/arch/arm/s3c2xx0/s3c2410.c, Revision 1.1
1.1 ! nbrk 1: /* $NetBSD: s3c2410.c,v 1.10 2005/12/11 12:16:51 christos Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2003, 2005 Genetec corporation. All rights reserved.
! 5: * Written by Hiroyuki Bessho for Genetec corporation.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. The name of Genetec corporation may not be used to endorse
! 16: * or promote products derived from this software without specific prior
! 17: * written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
! 20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
! 23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 29: * POSSIBILITY OF SUCH DAMAGE.
! 30: */
! 31:
! 32: #include <sys/cdefs.h>
! 33: __KERNEL_RCSID(0, "$NetBSD: s3c2410.c,v 1.10 2005/12/11 12:16:51 christos Exp $");
! 34:
! 35: #include <sys/param.h>
! 36: #include <sys/systm.h>
! 37: #include <sys/device.h>
! 38: #include <sys/kernel.h>
! 39: #include <sys/reboot.h>
! 40:
! 41: #include <machine/cpu.h>
! 42: #include <machine/bus.h>
! 43:
! 44: #include <arm/cpufunc.h>
! 45: #include <arm/mainbus/mainbus.h>
! 46: #include <arm/s3c2xx0/s3c2410reg.h>
! 47: #include <arm/s3c2xx0/s3c2410var.h>
! 48:
! 49: #include "locators.h"
! 50: #include "opt_cpuoptions.h"
! 51:
! 52: /* prototypes */
! 53: static int s3c2410_match(struct device *, struct cfdata *, void *);
! 54: static void s3c2410_attach(struct device *, struct device *, void *);
! 55: static int s3c2410_search(struct device *, struct cfdata *,
! 56: const int *, void *);
! 57:
! 58: /* attach structures */
! 59: CFATTACH_DECL(ssio, sizeof(struct s3c24x0_softc), s3c2410_match, s3c2410_attach,
! 60: NULL, NULL);
! 61:
! 62: extern struct bus_space s3c2xx0_bs_tag;
! 63:
! 64: struct s3c2xx0_softc *s3c2xx0_softc;
! 65:
! 66: #ifdef DEBUG_PORTF
! 67: volatile uint8_t *portf; /* for debug */
! 68: #endif
! 69:
! 70: static int
! 71: s3c2410_print(void *aux, const char *name)
! 72: {
! 73: struct s3c2xx0_attach_args *sa = (struct s3c2xx0_attach_args *) aux;
! 74:
! 75: if (sa->sa_size)
! 76: aprint_normal(" addr 0x%lx", sa->sa_addr);
! 77: if (sa->sa_size > 1)
! 78: aprint_normal("-0x%lx", sa->sa_addr + sa->sa_size - 1);
! 79: if (sa->sa_intr != SSIOCF_INTR_DEFAULT)
! 80: aprint_normal(" intr %d", sa->sa_intr);
! 81: if (sa->sa_index != SSIOCF_INDEX_DEFAULT)
! 82: aprint_normal(" unit %d", sa->sa_index);
! 83:
! 84: return (UNCONF);
! 85: }
! 86:
! 87: int
! 88: s3c2410_match(struct device *parent, struct cfdata *match, void *aux)
! 89: {
! 90: return 1;
! 91: }
! 92:
! 93: void
! 94: s3c2410_attach(struct device *parent, struct device *self, void *aux)
! 95: {
! 96: struct s3c24x0_softc *sc = (struct s3c24x0_softc *) self;
! 97: bus_space_tag_t iot;
! 98: const char *which_registers; /* for panic message */
! 99:
! 100: #define FAIL(which) do { \
! 101: which_registers=(which); goto abort; }while(/*CONSTCOND*/0)
! 102:
! 103: s3c2xx0_softc = &(sc->sc_sx);
! 104: sc->sc_sx.sc_iot = iot = &s3c2xx0_bs_tag;
! 105:
! 106: if (bus_space_map(iot,
! 107: S3C2410_INTCTL_BASE, S3C2410_INTCTL_SIZE,
! 108: BUS_SPACE_MAP_LINEAR, &sc->sc_sx.sc_intctl_ioh))
! 109: FAIL("intc");
! 110: /* tell register addresses to interrupt handler */
! 111: s3c2410_intr_init(sc);
! 112:
! 113: /* Map the GPIO registers */
! 114: if (bus_space_map(iot, S3C2410_GPIO_BASE, S3C2410_GPIO_SIZE,
! 115: 0, &sc->sc_sx.sc_gpio_ioh))
! 116: FAIL("GPIO");
! 117: #ifdef DEBUG_PORTF
! 118: {
! 119: extern volatile uint8_t *portf;
! 120: /* make all ports output */
! 121: bus_space_write_2(iot, sc->sc_sx.sc_gpio_ioh, GPIO_PCONF, 0x5555);
! 122: portf = (volatile uint8_t *)
! 123: ((char *)bus_space_vaddr(iot, sc->sc_sx.sc_gpio_ioh) + GPIO_PDATF);
! 124: }
! 125: #endif
! 126:
! 127: #if 0
! 128: /* Map the DMA controller registers */
! 129: if (bus_space_map(iot, S3C2410_DMAC_BASE, S3C2410_DMAC_SIZE,
! 130: 0, &sc->sc_sx.sc_dmach))
! 131: FAIL("DMAC");
! 132: #endif
! 133:
! 134: /* Memory controller */
! 135: if (bus_space_map(iot, S3C2410_MEMCTL_BASE,
! 136: S3C24X0_MEMCTL_SIZE, 0, &sc->sc_sx.sc_memctl_ioh))
! 137: FAIL("MEMC");
! 138: /* Clock manager */
! 139: if (bus_space_map(iot, S3C2410_CLKMAN_BASE,
! 140: S3C24X0_CLKMAN_SIZE, 0, &sc->sc_sx.sc_clkman_ioh))
! 141: FAIL("CLK");
! 142:
! 143: #if 0
! 144: /* Real time clock */
! 145: if (bus_space_map(iot, S3C2410_RTC_BASE,
! 146: S3C24X0_RTC_SIZE, 0, &sc->sc_sx.sc_rtc_ioh))
! 147: FAIL("RTC");
! 148: #endif
! 149:
! 150: if (bus_space_map(iot, S3C2410_TIMER_BASE,
! 151: S3C24X0_TIMER_SIZE, 0, &sc->sc_timer_ioh))
! 152: FAIL("TIMER");
! 153:
! 154: /* calculate current clock frequency */
! 155: s3c24x0_clock_freq(&sc->sc_sx);
! 156: aprint_normal(": fclk %d MHz hclk %d MHz pclk %d MHz\n",
! 157: sc->sc_sx.sc_fclk / 1000000, sc->sc_sx.sc_hclk / 1000000,
! 158: sc->sc_sx.sc_pclk / 1000000);
! 159:
! 160: aprint_naive("\n");
! 161:
! 162: /* get busdma tag for the platform */
! 163: sc->sc_sx.sc_dmat = s3c2xx0_bus_dma_init(&s3c2xx0_bus_dma);
! 164:
! 165: /*
! 166: * Attach devices.
! 167: */
! 168: config_search_ia(s3c2410_search, self, "ssio", NULL);
! 169: return;
! 170:
! 171: abort:
! 172: panic("%s: unable to map %s registers",
! 173: self->dv_xname, which_registers);
! 174:
! 175: #undef FAIL
! 176: }
! 177:
! 178: int
! 179: s3c2410_search(struct device * parent, struct cfdata * cf,
! 180: const int *ldesc, void *aux)
! 181: {
! 182: struct s3c24x0_softc *sc = (struct s3c24x0_softc *) parent;
! 183: struct s3c2xx0_attach_args aa;
! 184:
! 185: aa.sa_sc = sc;
! 186: aa.sa_iot = sc->sc_sx.sc_iot;
! 187: aa.sa_addr = cf->cf_loc[SSIOCF_ADDR];
! 188: aa.sa_size = cf->cf_loc[SSIOCF_SIZE];
! 189: aa.sa_index = cf->cf_loc[SSIOCF_INDEX];
! 190: aa.sa_intr = cf->cf_loc[SSIOCF_INTR];
! 191:
! 192: aa.sa_dmat = sc->sc_sx.sc_dmat;
! 193:
! 194: if (config_match(parent, cf, &aa))
! 195: config_attach(parent, cf, &aa, s3c2410_print);
! 196:
! 197: return 0;
! 198: }
! 199:
! 200: /*
! 201: * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
! 202: *
! 203: * s3c24x0_clock_freq2() is meant to be called from kernel startup routines.
! 204: * s3c24x0_clock_freq() is for after kernel initialization is done.
! 205: */
! 206: void
! 207: s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, int *pclk)
! 208: {
! 209: uint32_t pllcon, divn;
! 210: int mdiv, pdiv, sdiv;
! 211: int f, h, p;
! 212:
! 213: pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
! 214: divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
! 215:
! 216: mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
! 217: pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
! 218: sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
! 219:
! 220: f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
! 221: h = f;
! 222: if (divn & CLKDIVN_HDIVN)
! 223: h /= 2;
! 224: p = h;
! 225: if (divn & CLKDIVN_PDIVN)
! 226: p /= 2;
! 227:
! 228: if (fclk) *fclk = f;
! 229: if (hclk) *hclk = h;
! 230: if (pclk) *pclk = p;
! 231:
! 232: }
! 233:
! 234: void
! 235: s3c24x0_clock_freq(struct s3c2xx0_softc *sc)
! 236: {
! 237: s3c24x0_clock_freq2(
! 238: (vaddr_t)bus_space_vaddr(sc->sc_iot, sc->sc_clkman_ioh),
! 239: &sc->sc_fclk, &sc->sc_hclk, &sc->sc_pclk);
! 240: }
! 241:
! 242: /*
! 243: * Issue software reset command.
! 244: * called with MMU off.
! 245: *
! 246: * S3C2410 doesn't have sowtware reset bit like S3C2800.
! 247: * use watch dog timer and make it fire immediately.
! 248: */
! 249: void
! 250: s3c2410_softreset(void)
! 251: {
! 252: disable_interrupts(I32_bit|F32_bit);
! 253:
! 254: *(volatile unsigned int *)(S3C2410_WDT_BASE + WDT_WTCON)
! 255: = (0 << WTCON_PRESCALE_SHIFT) | WTCON_ENABLE |
! 256: WTCON_CLKSEL_16 | WTCON_ENRST;
! 257: }
! 258:
! 259:
CVSweb