linux/arch/arm/mach-sa1100/assabet.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-sa1100/assabet.c
   3 *
   4 * Author: Nicolas Pitre
   5 *
   6 * This file contains all Assabet-specific tweaks.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12#include <linux/init.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/errno.h>
  16#include <linux/ioport.h>
  17#include <linux/serial_core.h>
  18#include <linux/mtd/mtd.h>
  19#include <linux/mtd/partitions.h>
  20#include <linux/delay.h>
  21#include <linux/mm.h>
  22
  23#include <mach/hardware.h>
  24#include <asm/mach-types.h>
  25#include <asm/irq.h>
  26#include <asm/setup.h>
  27#include <asm/page.h>
  28#include <asm/pgtable-hwdef.h>
  29#include <asm/pgtable.h>
  30#include <asm/tlbflush.h>
  31
  32#include <asm/mach/arch.h>
  33#include <asm/mach/flash.h>
  34#include <asm/mach/irda.h>
  35#include <asm/mach/map.h>
  36#include <asm/mach/serial_sa1100.h>
  37#include <mach/assabet.h>
  38#include <mach/mcp.h>
  39
  40#include "generic.h"
  41
  42#define ASSABET_BCR_DB1110 \
  43        (ASSABET_BCR_SPK_OFF    | ASSABET_BCR_QMUTE     | \
  44         ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
  45         ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
  46         ASSABET_BCR_IRDA_MD0)
  47
  48#define ASSABET_BCR_DB1111 \
  49        (ASSABET_BCR_SPK_OFF    | ASSABET_BCR_QMUTE     | \
  50         ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
  51         ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
  52         ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
  53         ASSABET_BCR_IRDA_MD0   | ASSABET_BCR_CF_RST)
  54
  55unsigned long SCR_value = ASSABET_SCR_INIT;
  56EXPORT_SYMBOL(SCR_value);
  57
  58static unsigned long BCR_value = ASSABET_BCR_DB1110;
  59
  60void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
  61{
  62        unsigned long flags;
  63
  64        local_irq_save(flags);
  65        BCR_value = (BCR_value & ~mask) | val;
  66        ASSABET_BCR = BCR_value;
  67        local_irq_restore(flags);
  68}
  69
  70EXPORT_SYMBOL(ASSABET_BCR_frob);
  71
  72static void assabet_backlight_power(int on)
  73{
  74#ifndef ASSABET_PAL_VIDEO
  75        if (on)
  76                ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
  77        else
  78#endif
  79                ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
  80}
  81
  82/*
  83 * Turn on/off the backlight.  When turning the backlight on,
  84 * we wait 500us after turning it on so we don't cause the
  85 * supplies to droop when we enable the LCD controller (and
  86 * cause a hard reset.)
  87 */
  88static void assabet_lcd_power(int on)
  89{
  90#ifndef ASSABET_PAL_VIDEO
  91        if (on) {
  92                ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
  93                udelay(500);
  94        } else
  95#endif
  96                ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
  97}
  98
  99
 100/*
 101 * Assabet flash support code.
 102 */
 103
 104#ifdef ASSABET_REV_4
 105/*
 106 * Phase 4 Assabet has two 28F160B3 flash parts in bank 0:
 107 */
 108static struct mtd_partition assabet_partitions[] = {
 109        {
 110                .name           = "bootloader",
 111                .size           = 0x00020000,
 112                .offset         = 0,
 113                .mask_flags     = MTD_WRITEABLE,
 114        }, {
 115                .name           = "bootloader params",
 116                .size           = 0x00020000,
 117                .offset         = MTDPART_OFS_APPEND,
 118                .mask_flags     = MTD_WRITEABLE,
 119        }, {
 120                .name           = "jffs",
 121                .size           = MTDPART_SIZ_FULL,
 122                .offset         = MTDPART_OFS_APPEND,
 123        }
 124};
 125#else
 126/*
 127 * Phase 5 Assabet has two 28F128J3A flash parts in bank 0:
 128 */
 129static struct mtd_partition assabet_partitions[] = {
 130        {
 131                .name           = "bootloader",
 132                .size           = 0x00040000,
 133                .offset         = 0,
 134                .mask_flags     = MTD_WRITEABLE,
 135        }, {
 136                .name           = "bootloader params",
 137                .size           = 0x00040000,
 138                .offset         = MTDPART_OFS_APPEND,
 139                .mask_flags     = MTD_WRITEABLE,
 140        }, {
 141                .name           = "jffs",
 142                .size           = MTDPART_SIZ_FULL,
 143                .offset         = MTDPART_OFS_APPEND,
 144        }
 145};
 146#endif
 147
 148static struct flash_platform_data assabet_flash_data = {
 149        .map_name       = "cfi_probe",
 150        .parts          = assabet_partitions,
 151        .nr_parts       = ARRAY_SIZE(assabet_partitions),
 152};
 153
 154static struct resource assabet_flash_resources[] = {
 155        {
 156                .start  = SA1100_CS0_PHYS,
 157                .end    = SA1100_CS0_PHYS + SZ_32M - 1,
 158                .flags  = IORESOURCE_MEM,
 159        }, {
 160                .start  = SA1100_CS1_PHYS,
 161                .end    = SA1100_CS1_PHYS + SZ_32M - 1,
 162                .flags  = IORESOURCE_MEM,
 163        }
 164};
 165
 166
 167/*
 168 * Assabet IrDA support code.
 169 */
 170
 171static int assabet_irda_set_power(struct device *dev, unsigned int state)
 172{
 173        static unsigned int bcr_state[4] = {
 174                ASSABET_BCR_IRDA_MD0,
 175                ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0,
 176                ASSABET_BCR_IRDA_MD1,
 177                0
 178        };
 179
 180        if (state < 4) {
 181                state = bcr_state[state];
 182                ASSABET_BCR_clear(state ^ (ASSABET_BCR_IRDA_MD1|
 183                                           ASSABET_BCR_IRDA_MD0));
 184                ASSABET_BCR_set(state);
 185        }
 186        return 0;
 187}
 188
 189static void assabet_irda_set_speed(struct device *dev, unsigned int speed)
 190{
 191        if (speed < 4000000)
 192                ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
 193        else
 194                ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
 195}
 196
 197static struct irda_platform_data assabet_irda_data = {
 198        .set_power      = assabet_irda_set_power,
 199        .set_speed      = assabet_irda_set_speed,
 200};
 201
 202static struct mcp_plat_data assabet_mcp_data = {
 203        .mccr0          = MCCR0_ADM,
 204        .sclk_rate      = 11981000,
 205};
 206
 207static void __init assabet_init(void)
 208{
 209        /*
 210         * Ensure that the power supply is in "high power" mode.
 211         */
 212        GPDR |= GPIO_GPIO16;
 213        GPSR = GPIO_GPIO16;
 214
 215        /*
 216         * Ensure that these pins are set as outputs and are driving
 217         * logic 0.  This ensures that we won't inadvertently toggle
 218         * the WS latch in the CPLD, and we don't float causing
 219         * excessive power drain.  --rmk
 220         */
 221        GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
 222        GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
 223
 224        /*
 225         * Set up registers for sleep mode.
 226         */
 227        PWER = PWER_GPIO0;
 228        PGSR = 0;
 229        PCFR = 0;
 230        PSDR = 0;
 231        PPDR |= PPC_TXD3 | PPC_TXD1;
 232        PPSR |= PPC_TXD3 | PPC_TXD1;
 233
 234        sa1100fb_lcd_power = assabet_lcd_power;
 235        sa1100fb_backlight_power = assabet_backlight_power;
 236
 237        if (machine_has_neponset()) {
 238                /*
 239                 * Angel sets this, but other bootloaders may not.
 240                 *
 241                 * This must precede any driver calls to BCR_set()
 242                 * or BCR_clear().
 243                 */
 244                ASSABET_BCR = BCR_value = ASSABET_BCR_DB1111;
 245
 246#ifndef CONFIG_ASSABET_NEPONSET
 247                printk( "Warning: Neponset detected but full support "
 248                        "hasn't been configured in the kernel\n" );
 249#endif
 250        }
 251
 252        sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources,
 253                              ARRAY_SIZE(assabet_flash_resources));
 254        sa11x0_set_irda_data(&assabet_irda_data);
 255        sa11x0_set_mcp_data(&assabet_mcp_data);
 256}
 257
 258/*
 259 * On Assabet, we must probe for the Neponset board _before_
 260 * paging_init() has occurred to actually determine the amount
 261 * of RAM available.  To do so, we map the appropriate IO section
 262 * in the page table here in order to access GPIO registers.
 263 */
 264static void __init map_sa1100_gpio_regs( void )
 265{
 266        unsigned long phys = __PREG(GPLR) & PMD_MASK;
 267        unsigned long virt = io_p2v(phys);
 268        int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
 269        pmd_t *pmd;
 270
 271        pmd = pmd_offset(pgd_offset_k(virt), virt);
 272        *pmd = __pmd(phys | prot);
 273        flush_pmd_entry(pmd);
 274}
 275
 276/*
 277 * Read System Configuration "Register"
 278 * (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
 279 * User's Guide", section 4.4.1)
 280 *
 281 * This same scan is performed in arch/arm/boot/compressed/head-sa1100.S
 282 * to set up the serial port for decompression status messages. We
 283 * repeat it here because the kernel may not be loaded as a zImage, and
 284 * also because it's a hassle to communicate the SCR value to the kernel
 285 * from the decompressor.
 286 *
 287 * Note that IRQs are guaranteed to be disabled.
 288 */
 289static void __init get_assabet_scr(void)
 290{
 291        unsigned long scr, i;
 292
 293        GPDR |= 0x3fc;                  /* Configure GPIO 9:2 as outputs */
 294        GPSR = 0x3fc;                   /* Write 0xFF to GPIO 9:2 */
 295        GPDR &= ~(0x3fc);               /* Configure GPIO 9:2 as inputs */
 296        for(i = 100; i--; )             /* Read GPIO 9:2 */
 297                scr = GPLR;
 298        GPDR |= 0x3fc;                  /*  restore correct pin direction */
 299        scr &= 0x3fc;                   /* save as system configuration byte. */
 300        SCR_value = scr;
 301}
 302
 303static void __init
 304fixup_assabet(struct machine_desc *desc, struct tag *tags,
 305              char **cmdline, struct meminfo *mi)
 306{
 307        /* This must be done before any call to machine_has_neponset() */
 308        map_sa1100_gpio_regs();
 309        get_assabet_scr();
 310
 311        if (machine_has_neponset())
 312                printk("Neponset expansion board detected\n");
 313}
 314
 315
 316static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 317{
 318        if (port->mapbase == _Ser1UTCR0) {
 319                if (state)
 320                        ASSABET_BCR_clear(ASSABET_BCR_RS232EN |
 321                                          ASSABET_BCR_COM_RTS |
 322                                          ASSABET_BCR_COM_DTR);
 323                else
 324                        ASSABET_BCR_set(ASSABET_BCR_RS232EN |
 325                                        ASSABET_BCR_COM_RTS |
 326                                        ASSABET_BCR_COM_DTR);
 327        }
 328}
 329
 330/*
 331 * Assabet uses COM_RTS and COM_DTR for both UART1 (com port)
 332 * and UART3 (radio module).  We only handle them for UART1 here.
 333 */
 334static void assabet_set_mctrl(struct uart_port *port, u_int mctrl)
 335{
 336        if (port->mapbase == _Ser1UTCR0) {
 337                u_int set = 0, clear = 0;
 338
 339                if (mctrl & TIOCM_RTS)
 340                        clear |= ASSABET_BCR_COM_RTS;
 341                else
 342                        set |= ASSABET_BCR_COM_RTS;
 343
 344                if (mctrl & TIOCM_DTR)
 345                        clear |= ASSABET_BCR_COM_DTR;
 346                else
 347                        set |= ASSABET_BCR_COM_DTR;
 348
 349                ASSABET_BCR_clear(clear);
 350                ASSABET_BCR_set(set);
 351        }
 352}
 353
 354static u_int assabet_get_mctrl(struct uart_port *port)
 355{
 356        u_int ret = 0;
 357        u_int bsr = ASSABET_BSR;
 358
 359        /* need 2 reads to read current value */
 360        bsr = ASSABET_BSR;
 361
 362        if (port->mapbase == _Ser1UTCR0) {
 363                if (bsr & ASSABET_BSR_COM_DCD)
 364                        ret |= TIOCM_CD;
 365                if (bsr & ASSABET_BSR_COM_CTS)
 366                        ret |= TIOCM_CTS;
 367                if (bsr & ASSABET_BSR_COM_DSR)
 368                        ret |= TIOCM_DSR;
 369        } else if (port->mapbase == _Ser3UTCR0) {
 370                if (bsr & ASSABET_BSR_RAD_DCD)
 371                        ret |= TIOCM_CD;
 372                if (bsr & ASSABET_BSR_RAD_CTS)
 373                        ret |= TIOCM_CTS;
 374                if (bsr & ASSABET_BSR_RAD_DSR)
 375                        ret |= TIOCM_DSR;
 376                if (bsr & ASSABET_BSR_RAD_RI)
 377                        ret |= TIOCM_RI;
 378        } else {
 379                ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
 380        }
 381
 382        return ret;
 383}
 384
 385static struct sa1100_port_fns assabet_port_fns __initdata = {
 386        .set_mctrl      = assabet_set_mctrl,
 387        .get_mctrl      = assabet_get_mctrl,
 388        .pm             = assabet_uart_pm,
 389};
 390
 391static struct map_desc assabet_io_desc[] __initdata = {
 392        {       /* Board Control Register */
 393                .virtual        =  0xf1000000,
 394                .pfn            = __phys_to_pfn(0x12000000),
 395                .length         = 0x00100000,
 396                .type           = MT_DEVICE
 397        }, {    /* MQ200 */
 398                .virtual        =  0xf2800000,
 399                .pfn            = __phys_to_pfn(0x4b800000),
 400                .length         = 0x00800000,
 401                .type           = MT_DEVICE
 402        }
 403};
 404
 405static void __init assabet_map_io(void)
 406{
 407        sa1100_map_io();
 408        iotable_init(assabet_io_desc, ARRAY_SIZE(assabet_io_desc));
 409
 410        /*
 411         * Set SUS bit in SDCR0 so serial port 1 functions.
 412         * Its called GPCLKR0 in my SA1110 manual.
 413         */
 414        Ser1SDCR0 |= SDCR0_SUS;
 415
 416        if (machine_has_neponset()) {
 417#ifdef CONFIG_ASSABET_NEPONSET
 418                extern void neponset_map_io(void);
 419
 420                /*
 421                 * We map Neponset registers even if it isn't present since
 422                 * many drivers will try to probe their stuff (and fail).
 423                 * This is still more friendly than a kernel paging request
 424                 * crash.
 425                 */
 426                neponset_map_io();
 427#endif
 428        } else {
 429                sa1100_register_uart_fns(&assabet_port_fns);
 430        }
 431
 432        /*
 433         * When Neponset is attached, the first UART should be
 434         * UART3.  That's what Angel is doing and many documents
 435         * are stating this.
 436         *
 437         * We do the Neponset mapping even if Neponset support
 438         * isn't compiled in so the user will still get something on
 439         * the expected physical serial port.
 440         *
 441         * We no longer do this; not all boot loaders support it,
 442         * and UART3 appears to be somewhat unreliable with blob.
 443         */
 444        sa1100_register_uart(0, 1);
 445        sa1100_register_uart(2, 3);
 446}
 447
 448
 449MACHINE_START(ASSABET, "Intel-Assabet")
 450        .phys_io        = 0x80000000,
 451        .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
 452        .boot_params    = 0xc0000100,
 453        .fixup          = fixup_assabet,
 454        .map_io         = assabet_map_io,
 455        .init_irq       = sa1100_init_irq,
 456        .timer          = &sa1100_timer,
 457        .init_machine   = assabet_init,
 458MACHINE_END
 459
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.