Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/arch/arm/mach-sa1100/assabet.c
0004  *
0005  * Author: Nicolas Pitre
0006  *
0007  * This file contains all Assabet-specific tweaks.
0008  */
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/errno.h>
0013 #include <linux/gpio/gpio-reg.h>
0014 #include <linux/gpio/machine.h>
0015 #include <linux/gpio_keys.h>
0016 #include <linux/ioport.h>
0017 #include <linux/platform_data/sa11x0-serial.h>
0018 #include <linux/regulator/fixed.h>
0019 #include <linux/regulator/machine.h>
0020 #include <linux/serial_core.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/mfd/ucb1x00.h>
0023 #include <linux/mtd/mtd.h>
0024 #include <linux/mtd/partitions.h>
0025 #include <linux/delay.h>
0026 #include <linux/mm.h>
0027 #include <linux/leds.h>
0028 #include <linux/slab.h>
0029 
0030 #include <video/sa1100fb.h>
0031 
0032 #include <mach/hardware.h>
0033 #include <asm/mach-types.h>
0034 #include <asm/setup.h>
0035 #include <asm/page.h>
0036 #include <asm/pgtable-hwdef.h>
0037 #include <asm/tlbflush.h>
0038 
0039 #include <asm/mach/arch.h>
0040 #include <asm/mach/flash.h>
0041 #include <linux/platform_data/irda-sa11x0.h>
0042 #include <asm/mach/map.h>
0043 #include <mach/assabet.h>
0044 #include <linux/platform_data/mfd-mcp-sa11x0.h>
0045 #include <mach/irqs.h>
0046 
0047 #include "generic.h"
0048 
0049 #define ASSABET_BCR_DB1110 \
0050     (ASSABET_BCR_SPK_OFF    | \
0051      ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
0052      ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
0053      ASSABET_BCR_IRDA_MD0)
0054 
0055 #define ASSABET_BCR_DB1111 \
0056     (ASSABET_BCR_SPK_OFF    | \
0057      ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
0058      ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
0059      ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
0060      ASSABET_BCR_IRDA_MD0   | ASSABET_BCR_CF_RST)
0061 
0062 unsigned long SCR_value = ASSABET_SCR_INIT;
0063 EXPORT_SYMBOL(SCR_value);
0064 
0065 static struct gpio_chip *assabet_bcr_gc;
0066 
0067 static const char *assabet_names[] = {
0068     "cf_pwr", "cf_gfx_reset", "nsoft_reset", "irda_fsel",
0069     "irda_md0", "irda_md1", "stereo_loopback", "ncf_bus_on",
0070     "audio_pwr_on", "light_pwr_on", "lcd16data", "lcd_pwr_on",
0071     "rs232_on", "nred_led", "ngreen_led", "vib_on",
0072     "com_dtr", "com_rts", "radio_wake_mod", "i2c_enab",
0073     "tvir_enab", "qmute", "radio_pwr_on", "spkr_off",
0074     "rs232_valid", "com_dcd", "com_cts", "com_dsr",
0075     "radio_cts", "radio_dsr", "radio_dcd", "radio_ri",
0076 };
0077 
0078 /* The old deprecated interface */
0079 void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
0080 {
0081     unsigned long m = mask, v = val;
0082 
0083     assabet_bcr_gc->set_multiple(assabet_bcr_gc, &m, &v);
0084 }
0085 EXPORT_SYMBOL(ASSABET_BCR_frob);
0086 
0087 static void __init assabet_init_gpio(void __iomem *reg, u32 def_val)
0088 {
0089     struct gpio_chip *gc;
0090 
0091     writel_relaxed(def_val, reg);
0092 
0093     gc = gpio_reg_init(NULL, reg, -1, 32, "assabet", 0xff000000, def_val,
0094                assabet_names, NULL, NULL);
0095 
0096     if (IS_ERR(gc))
0097         return;
0098 
0099     assabet_bcr_gc = gc;
0100 }
0101 
0102 /*
0103  * The codec reset goes to three devices, so we need to release
0104  * the rest when any one of these requests it.  However, that
0105  * causes the ADV7171 to consume around 100mA - more than half
0106  * the LCD-blanked power.
0107  *
0108  * With the ADV7171, LCD and backlight enabled, we go over
0109  * budget on the MAX846 Li-Ion charger, and if no Li-Ion battery
0110  * is connected, the Assabet crashes.
0111  */
0112 #define RST_UCB1X00 (1 << 0)
0113 #define RST_UDA1341 (1 << 1)
0114 #define RST_ADV7171 (1 << 2)
0115 
0116 #define SDA GPIO_GPIO(15)
0117 #define SCK GPIO_GPIO(18)
0118 #define MOD GPIO_GPIO(17)
0119 
0120 static void adv7171_start(void)
0121 {
0122     GPSR = SCK;
0123     udelay(1);
0124     GPSR = SDA;
0125     udelay(2);
0126     GPCR = SDA;
0127 }
0128 
0129 static void adv7171_stop(void)
0130 {
0131     GPSR = SCK;
0132     udelay(2);
0133     GPSR = SDA;
0134     udelay(1);
0135 }
0136 
0137 static void adv7171_send(unsigned byte)
0138 {
0139     unsigned i;
0140 
0141     for (i = 0; i < 8; i++, byte <<= 1) {
0142         GPCR = SCK;
0143         udelay(1);
0144         if (byte & 0x80)
0145             GPSR = SDA;
0146         else
0147             GPCR = SDA;
0148         udelay(1);
0149         GPSR = SCK;
0150         udelay(1);
0151     }
0152     GPCR = SCK;
0153     udelay(1);
0154     GPSR = SDA;
0155     udelay(1);
0156     GPDR &= ~SDA;
0157     GPSR = SCK;
0158     udelay(1);
0159     if (GPLR & SDA)
0160         printk(KERN_WARNING "No ACK from ADV7171\n");
0161     udelay(1);
0162     GPCR = SCK | SDA;
0163     udelay(1);
0164     GPDR |= SDA;
0165     udelay(1);
0166 }
0167 
0168 static void adv7171_write(unsigned reg, unsigned val)
0169 {
0170     unsigned gpdr = GPDR;
0171     unsigned gplr = GPLR;
0172 
0173     ASSABET_BCR_frob(ASSABET_BCR_AUDIO_ON, ASSABET_BCR_AUDIO_ON);
0174     udelay(100);
0175 
0176     GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */
0177     GPDR = (GPDR | SCK | MOD) & ~SDA;
0178     udelay(10);
0179     if (!(GPLR & SDA))
0180         printk(KERN_WARNING "Something dragging SDA down?\n");
0181     GPDR |= SDA;
0182 
0183     adv7171_start();
0184     adv7171_send(0x54);
0185     adv7171_send(reg);
0186     adv7171_send(val);
0187     adv7171_stop();
0188 
0189     /* Restore GPIO state for L3 bus */
0190     GPSR = gplr & (SDA | SCK | MOD);
0191     GPCR = (~gplr) & (SDA | SCK | MOD);
0192     GPDR = gpdr;
0193 }
0194 
0195 static void adv7171_sleep(void)
0196 {
0197     /* Put the ADV7171 into sleep mode */
0198     adv7171_write(0x04, 0x40);
0199 }
0200 
0201 static unsigned codec_nreset;
0202 
0203 static void assabet_codec_reset(unsigned mask, int set)
0204 {
0205     unsigned long flags;
0206     bool old;
0207 
0208     local_irq_save(flags);
0209     old = !codec_nreset;
0210     if (set)
0211         codec_nreset &= ~mask;
0212     else
0213         codec_nreset |= mask;
0214 
0215     if (old != !codec_nreset) {
0216         if (codec_nreset) {
0217             ASSABET_BCR_set(ASSABET_BCR_NCODEC_RST);
0218             adv7171_sleep();
0219         } else {
0220             ASSABET_BCR_clear(ASSABET_BCR_NCODEC_RST);
0221         }
0222     }
0223     local_irq_restore(flags);
0224 }
0225 
0226 static void assabet_ucb1x00_reset(enum ucb1x00_reset state)
0227 {
0228     int set = state == UCB_RST_REMOVE || state == UCB_RST_SUSPEND ||
0229         state == UCB_RST_PROBE_FAIL;
0230     assabet_codec_reset(RST_UCB1X00, set);
0231 }
0232 
0233 void assabet_uda1341_reset(int set)
0234 {
0235     assabet_codec_reset(RST_UDA1341, set);
0236 }
0237 EXPORT_SYMBOL(assabet_uda1341_reset);
0238 
0239 
0240 /*
0241  * Assabet flash support code.
0242  */
0243 
0244 #ifdef ASSABET_REV_4
0245 /*
0246  * Phase 4 Assabet has two 28F160B3 flash parts in bank 0:
0247  */
0248 static struct mtd_partition assabet_partitions[] = {
0249     {
0250         .name       = "bootloader",
0251         .size       = 0x00020000,
0252         .offset     = 0,
0253         .mask_flags = MTD_WRITEABLE,
0254     }, {
0255         .name       = "bootloader params",
0256         .size       = 0x00020000,
0257         .offset     = MTDPART_OFS_APPEND,
0258         .mask_flags = MTD_WRITEABLE,
0259     }, {
0260         .name       = "jffs",
0261         .size       = MTDPART_SIZ_FULL,
0262         .offset     = MTDPART_OFS_APPEND,
0263     }
0264 };
0265 #else
0266 /*
0267  * Phase 5 Assabet has two 28F128J3A flash parts in bank 0:
0268  */
0269 static struct mtd_partition assabet_partitions[] = {
0270     {
0271         .name       = "bootloader",
0272         .size       = 0x00040000,
0273         .offset     = 0,
0274         .mask_flags = MTD_WRITEABLE,
0275     }, {
0276         .name       = "bootloader params",
0277         .size       = 0x00040000,
0278         .offset     = MTDPART_OFS_APPEND,
0279         .mask_flags = MTD_WRITEABLE,
0280     }, {
0281         .name       = "jffs",
0282         .size       = MTDPART_SIZ_FULL,
0283         .offset     = MTDPART_OFS_APPEND,
0284     }
0285 };
0286 #endif
0287 
0288 static struct flash_platform_data assabet_flash_data = {
0289     .map_name   = "cfi_probe",
0290     .parts      = assabet_partitions,
0291     .nr_parts   = ARRAY_SIZE(assabet_partitions),
0292 };
0293 
0294 static struct resource assabet_flash_resources[] = {
0295     DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
0296     DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M),
0297 };
0298 
0299 
0300 /*
0301  * Assabet IrDA support code.
0302  */
0303 
0304 static int assabet_irda_set_power(struct device *dev, unsigned int state)
0305 {
0306     static unsigned int bcr_state[4] = {
0307         ASSABET_BCR_IRDA_MD0,
0308         ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0,
0309         ASSABET_BCR_IRDA_MD1,
0310         0
0311     };
0312 
0313     if (state < 4)
0314         ASSABET_BCR_frob(ASSABET_BCR_IRDA_MD1 | ASSABET_BCR_IRDA_MD0,
0315                  bcr_state[state]);
0316     return 0;
0317 }
0318 
0319 static void assabet_irda_set_speed(struct device *dev, unsigned int speed)
0320 {
0321     if (speed < 4000000)
0322         ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
0323     else
0324         ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
0325 }
0326 
0327 static struct irda_platform_data assabet_irda_data = {
0328     .set_power  = assabet_irda_set_power,
0329     .set_speed  = assabet_irda_set_speed,
0330 };
0331 
0332 static struct ucb1x00_plat_data assabet_ucb1x00_data = {
0333     .reset      = assabet_ucb1x00_reset,
0334     .gpio_base  = -1,
0335     .can_wakeup = 1,
0336 };
0337 
0338 static struct mcp_plat_data assabet_mcp_data = {
0339     .mccr0      = MCCR0_ADM,
0340     .sclk_rate  = 11981000,
0341     .codec_pdata    = &assabet_ucb1x00_data,
0342 };
0343 
0344 static void assabet_lcd_set_visual(u32 visual)
0345 {
0346     u_int is_true_color = visual == FB_VISUAL_TRUECOLOR;
0347 
0348     if (machine_is_assabet()) {
0349 #if 1       // phase 4 or newer Assabet's
0350         if (is_true_color)
0351             ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
0352         else
0353             ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
0354 #else
0355         // older Assabet's
0356         if (is_true_color)
0357             ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
0358         else
0359             ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
0360 #endif
0361     }
0362 }
0363 
0364 #ifndef ASSABET_PAL_VIDEO
0365 static void assabet_lcd_backlight_power(int on)
0366 {
0367     if (on)
0368         ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
0369     else
0370         ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
0371 }
0372 
0373 /*
0374  * Turn on/off the backlight.  When turning the backlight on, we wait
0375  * 500us after turning it on so we don't cause the supplies to droop
0376  * when we enable the LCD controller (and cause a hard reset.)
0377  */
0378 static void assabet_lcd_power(int on)
0379 {
0380     if (on) {
0381         ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
0382         udelay(500);
0383     } else
0384         ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
0385 }
0386 
0387 /*
0388  * The assabet uses a sharp LQ039Q2DS54 LCD module.  It is actually
0389  * takes an RGB666 signal, but we provide it with an RGB565 signal
0390  * instead (def_rgb_16).
0391  */
0392 static struct sa1100fb_mach_info lq039q2ds54_info = {
0393     .pixclock   = 171521,   .bpp        = 16,
0394     .xres       = 320,      .yres       = 240,
0395 
0396     .hsync_len  = 5,        .vsync_len  = 1,
0397     .left_margin    = 61,       .upper_margin   = 3,
0398     .right_margin   = 9,        .lower_margin   = 0,
0399 
0400     .sync       = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0401 
0402     .lccr0      = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
0403     .lccr3      = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
0404 
0405     .backlight_power = assabet_lcd_backlight_power,
0406     .lcd_power = assabet_lcd_power,
0407     .set_visual = assabet_lcd_set_visual,
0408 };
0409 #else
0410 static void assabet_pal_backlight_power(int on)
0411 {
0412     ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
0413 }
0414 
0415 static void assabet_pal_power(int on)
0416 {
0417     ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
0418 }
0419 
0420 static struct sa1100fb_mach_info pal_info = {
0421     .pixclock   = 67797,    .bpp        = 16,
0422     .xres       = 640,      .yres       = 512,
0423 
0424     .hsync_len  = 64,       .vsync_len  = 6,
0425     .left_margin    = 125,      .upper_margin   = 70,
0426     .right_margin   = 115,      .lower_margin   = 36,
0427 
0428     .lccr0      = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
0429     .lccr3      = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
0430 
0431     .backlight_power = assabet_pal_backlight_power,
0432     .lcd_power = assabet_pal_power,
0433     .set_visual = assabet_lcd_set_visual,
0434 };
0435 #endif
0436 
0437 #ifdef CONFIG_ASSABET_NEPONSET
0438 static struct resource neponset_resources[] = {
0439     DEFINE_RES_MEM(0x10000000, 0x08000000),
0440     DEFINE_RES_MEM(0x18000000, 0x04000000),
0441     DEFINE_RES_MEM(0x40000000, SZ_8K),
0442     DEFINE_RES_IRQ(IRQ_GPIO25),
0443 };
0444 #endif
0445 
0446 static struct gpiod_lookup_table assabet_cf_gpio_table = {
0447     .dev_id = "sa11x0-pcmcia.1",
0448     .table = {
0449         GPIO_LOOKUP("gpio", 21, "ready", GPIO_ACTIVE_HIGH),
0450         GPIO_LOOKUP("gpio", 22, "detect", GPIO_ACTIVE_LOW),
0451         GPIO_LOOKUP("gpio", 24, "bvd2", GPIO_ACTIVE_HIGH),
0452         GPIO_LOOKUP("gpio", 25, "bvd1", GPIO_ACTIVE_HIGH),
0453         GPIO_LOOKUP("assabet", 1, "reset", GPIO_ACTIVE_HIGH),
0454         GPIO_LOOKUP("assabet", 7, "bus-enable", GPIO_ACTIVE_LOW),
0455         { },
0456     },
0457 };
0458 
0459 static struct regulator_consumer_supply assabet_cf_vcc_consumers[] = {
0460     REGULATOR_SUPPLY("vcc", "sa11x0-pcmcia.1"),
0461 };
0462 
0463 static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = {
0464     .supply_name = "cf-power",
0465     .microvolts = 3300000,
0466 };
0467 
0468 static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {
0469     .dev_id = "reg-fixed-voltage.0",
0470     .table = {
0471         GPIO_LOOKUP("assabet", 0, NULL, GPIO_ACTIVE_HIGH),
0472         { },
0473     },
0474 };
0475 
0476 static struct gpiod_lookup_table assabet_leds_gpio_table = {
0477     .dev_id = "leds-gpio",
0478     .table = {
0479         GPIO_LOOKUP("assabet", 13, NULL, GPIO_ACTIVE_LOW),
0480         GPIO_LOOKUP("assabet", 14, NULL, GPIO_ACTIVE_LOW),
0481         { },
0482     },
0483 };
0484 
0485 static struct gpio_led assabet_leds[] __initdata = {
0486     {
0487         .name = "assabet:red",
0488         .default_trigger = "cpu0",
0489         .default_state = LEDS_GPIO_DEFSTATE_KEEP,
0490     }, {
0491         .name = "assabet:green",
0492         .default_trigger = "heartbeat",
0493         .default_state = LEDS_GPIO_DEFSTATE_KEEP,
0494     },
0495 };
0496 
0497 static const struct gpio_led_platform_data assabet_leds_pdata __initconst = {
0498     .num_leds = ARRAY_SIZE(assabet_leds),
0499     .leds = assabet_leds,
0500 };
0501 
0502 static struct gpio_keys_button assabet_keys_buttons[] = {
0503     {
0504         .gpio = 0,
0505         .irq = IRQ_GPIO0,
0506         .desc = "gpio0",
0507         .wakeup = 1,
0508         .can_disable = 1,
0509         .debounce_interval = 5,
0510     }, {
0511         .gpio = 1,
0512         .irq = IRQ_GPIO1,
0513         .desc = "gpio1",
0514         .wakeup = 1,
0515         .can_disable = 1,
0516         .debounce_interval = 5,
0517     },
0518 };
0519 
0520 static const struct gpio_keys_platform_data assabet_keys_pdata = {
0521     .buttons = assabet_keys_buttons,
0522     .nbuttons = ARRAY_SIZE(assabet_keys_buttons),
0523     .rep = 0,
0524 };
0525 
0526 static struct gpiod_lookup_table assabet_uart1_gpio_table = {
0527     .dev_id = "sa11x0-uart.1",
0528     .table = {
0529         GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW),
0530         GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW),
0531         GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW),
0532         GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW),
0533         GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW),
0534         { },
0535     },
0536 };
0537 
0538 static struct gpiod_lookup_table assabet_uart3_gpio_table = {
0539     .dev_id = "sa11x0-uart.3",
0540     .table = {
0541         GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW),
0542         GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW),
0543         GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW),
0544         GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW),
0545         { },
0546     },
0547 };
0548 
0549 static void __init assabet_init(void)
0550 {
0551     /*
0552      * Ensure that the power supply is in "high power" mode.
0553      */
0554     GPSR = GPIO_GPIO16;
0555     GPDR |= GPIO_GPIO16;
0556 
0557     /*
0558      * Ensure that these pins are set as outputs and are driving
0559      * logic 0.  This ensures that we won't inadvertently toggle
0560      * the WS latch in the CPLD, and we don't float causing
0561      * excessive power drain.  --rmk
0562      */
0563     GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
0564     GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
0565 
0566     /*
0567      * Also set GPIO27 as an output; this is used to clock UART3
0568      * via the FPGA and as otherwise has no pullups or pulldowns,
0569      * so stop it floating.
0570      */
0571     GPCR = GPIO_GPIO27;
0572     GPDR |= GPIO_GPIO27;
0573 
0574     /*
0575      * Set up registers for sleep mode.
0576      */
0577     PWER = PWER_GPIO0;
0578     PGSR = 0;
0579     PCFR = 0;
0580     PSDR = 0;
0581     PPDR |= PPC_TXD3 | PPC_TXD1;
0582     PPSR |= PPC_TXD3 | PPC_TXD1;
0583 
0584     sa11x0_ppc_configure_mcp();
0585 
0586     if (machine_has_neponset()) {
0587 #ifndef CONFIG_ASSABET_NEPONSET
0588         printk( "Warning: Neponset detected but full support "
0589             "hasn't been configured in the kernel\n" );
0590 #else
0591         platform_device_register_simple("neponset", 0,
0592             neponset_resources, ARRAY_SIZE(neponset_resources));
0593 #endif
0594     } else {
0595         gpiod_add_lookup_table(&assabet_uart1_gpio_table);
0596         gpiod_add_lookup_table(&assabet_uart3_gpio_table);
0597         gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
0598 
0599         sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
0600                     assabet_cf_vcc_consumers,
0601                     ARRAY_SIZE(assabet_cf_vcc_consumers),
0602                     true);
0603 
0604     }
0605 
0606     platform_device_register_resndata(NULL, "gpio-keys", 0,
0607                       NULL, 0,
0608                       &assabet_keys_pdata,
0609                       sizeof(assabet_keys_pdata));
0610 
0611     gpiod_add_lookup_table(&assabet_leds_gpio_table);
0612     gpio_led_register_device(-1, &assabet_leds_pdata);
0613 
0614 #ifndef ASSABET_PAL_VIDEO
0615     sa11x0_register_lcd(&lq039q2ds54_info);
0616 #else
0617     sa11x0_register_lcd(&pal_video);
0618 #endif
0619     sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
0620                 ARRAY_SIZE(assabet_flash_resources));
0621     sa11x0_register_irda(&assabet_irda_data);
0622     sa11x0_register_mcp(&assabet_mcp_data);
0623 
0624     if (!machine_has_neponset())
0625         sa11x0_register_pcmcia(1, &assabet_cf_gpio_table);
0626 }
0627 
0628 /*
0629  * On Assabet, we must probe for the Neponset board _before_
0630  * paging_init() has occurred to actually determine the amount
0631  * of RAM available.  To do so, we map the appropriate IO section
0632  * in the page table here in order to access GPIO registers.
0633  */
0634 static void __init map_sa1100_gpio_regs( void )
0635 {
0636     unsigned long phys = __PREG(GPLR) & PMD_MASK;
0637     unsigned long virt = (unsigned long)io_p2v(phys);
0638     int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
0639     pmd_t *pmd;
0640 
0641     pmd = pmd_off_k(virt);
0642     *pmd = __pmd(phys | prot);
0643     flush_pmd_entry(pmd);
0644 }
0645 
0646 /*
0647  * Read System Configuration "Register"
0648  * (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
0649  * User's Guide", section 4.4.1)
0650  *
0651  * This same scan is performed in arch/arm/boot/compressed/head-sa1100.S
0652  * to set up the serial port for decompression status messages. We
0653  * repeat it here because the kernel may not be loaded as a zImage, and
0654  * also because it's a hassle to communicate the SCR value to the kernel
0655  * from the decompressor.
0656  *
0657  * Note that IRQs are guaranteed to be disabled.
0658  */
0659 static void __init get_assabet_scr(void)
0660 {
0661     unsigned long scr, i;
0662 
0663     GPDR |= 0x3fc;          /* Configure GPIO 9:2 as outputs */
0664     GPSR = 0x3fc;           /* Write 0xFF to GPIO 9:2 */
0665     GPDR &= ~(0x3fc);       /* Configure GPIO 9:2 as inputs */
0666     for(i = 100; i--; )     /* Read GPIO 9:2 */
0667         scr = GPLR;
0668     GPDR |= 0x3fc;          /*  restore correct pin direction */
0669     scr &= 0x3fc;           /* save as system configuration byte. */
0670     SCR_value = scr;
0671 }
0672 
0673 static void __init
0674 fixup_assabet(struct tag *tags, char **cmdline)
0675 {
0676     /* This must be done before any call to machine_has_neponset() */
0677     map_sa1100_gpio_regs();
0678     get_assabet_scr();
0679 
0680     if (machine_has_neponset())
0681         printk("Neponset expansion board detected\n");
0682 }
0683 
0684 
0685 static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
0686 {
0687     if (port->mapbase == _Ser1UTCR0) {
0688         if (state)
0689             ASSABET_BCR_clear(ASSABET_BCR_RS232EN);
0690         else
0691             ASSABET_BCR_set(ASSABET_BCR_RS232EN);
0692     }
0693 }
0694 
0695 static struct sa1100_port_fns assabet_port_fns __initdata = {
0696     .pm     = assabet_uart_pm,
0697 };
0698 
0699 static struct map_desc assabet_io_desc[] __initdata = {
0700     {   /* Board Control Register */
0701         .virtual    =  0xf1000000,
0702         .pfn        = __phys_to_pfn(0x12000000),
0703         .length     = 0x00100000,
0704         .type       = MT_DEVICE
0705     }, {    /* MQ200 */
0706         .virtual    =  0xf2800000,
0707         .pfn        = __phys_to_pfn(0x4b800000),
0708         .length     = 0x00800000,
0709         .type       = MT_DEVICE
0710     }
0711 };
0712 
0713 static void __init assabet_map_io(void)
0714 {
0715     sa1100_map_io();
0716     iotable_init(assabet_io_desc, ARRAY_SIZE(assabet_io_desc));
0717 
0718     /*
0719      * Set SUS bit in SDCR0 so serial port 1 functions.
0720      * Its called GPCLKR0 in my SA1110 manual.
0721      */
0722     Ser1SDCR0 |= SDCR0_SUS;
0723     MSC1 = (MSC1 & ~0xffff) |
0724         MSC_NonBrst | MSC_32BitStMem |
0725         MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0);
0726 
0727     if (!machine_has_neponset())
0728         sa1100_register_uart_fns(&assabet_port_fns);
0729 
0730     /*
0731      * When Neponset is attached, the first UART should be
0732      * UART3.  That's what Angel is doing and many documents
0733      * are stating this.
0734      *
0735      * We do the Neponset mapping even if Neponset support
0736      * isn't compiled in so the user will still get something on
0737      * the expected physical serial port.
0738      *
0739      * We no longer do this; not all boot loaders support it,
0740      * and UART3 appears to be somewhat unreliable with blob.
0741      */
0742     sa1100_register_uart(0, 1);
0743     sa1100_register_uart(2, 3);
0744 }
0745 
0746 void __init assabet_init_irq(void)
0747 {
0748     u32 def_val;
0749 
0750     sa1100_init_irq();
0751 
0752     if (machine_has_neponset())
0753         def_val = ASSABET_BCR_DB1111;
0754     else
0755         def_val = ASSABET_BCR_DB1110;
0756 
0757     /*
0758      * Angel sets this, but other bootloaders may not.
0759      *
0760      * This must precede any driver calls to BCR_set() or BCR_clear().
0761      */
0762     assabet_init_gpio((void *)&ASSABET_BCR, def_val);
0763 }
0764 
0765 MACHINE_START(ASSABET, "Intel-Assabet")
0766     .atag_offset    = 0x100,
0767     .fixup      = fixup_assabet,
0768     .map_io     = assabet_map_io,
0769     .nr_irqs    = SA1100_NR_IRQS,
0770     .init_irq   = assabet_init_irq,
0771     .init_time  = sa1100_timer_init,
0772     .init_machine   = assabet_init,
0773     .init_late  = sa11x0_init_late,
0774 #ifdef CONFIG_SA1111
0775     .dma_zone_size  = SZ_1M,
0776 #endif
0777     .restart    = sa11x0_restart,
0778 MACHINE_END