cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

assabet.c (19096B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * linux/arch/arm/mach-sa1100/assabet.c
      4 *
      5 * Author: Nicolas Pitre
      6 *
      7 * This file contains all Assabet-specific tweaks.
      8 */
      9#include <linux/init.h>
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/errno.h>
     13#include <linux/gpio/gpio-reg.h>
     14#include <linux/gpio/machine.h>
     15#include <linux/gpio_keys.h>
     16#include <linux/ioport.h>
     17#include <linux/platform_data/sa11x0-serial.h>
     18#include <linux/regulator/fixed.h>
     19#include <linux/regulator/machine.h>
     20#include <linux/serial_core.h>
     21#include <linux/platform_device.h>
     22#include <linux/mfd/ucb1x00.h>
     23#include <linux/mtd/mtd.h>
     24#include <linux/mtd/partitions.h>
     25#include <linux/delay.h>
     26#include <linux/mm.h>
     27#include <linux/leds.h>
     28#include <linux/slab.h>
     29
     30#include <video/sa1100fb.h>
     31
     32#include <mach/hardware.h>
     33#include <asm/mach-types.h>
     34#include <asm/setup.h>
     35#include <asm/page.h>
     36#include <asm/pgtable-hwdef.h>
     37#include <asm/tlbflush.h>
     38
     39#include <asm/mach/arch.h>
     40#include <asm/mach/flash.h>
     41#include <linux/platform_data/irda-sa11x0.h>
     42#include <asm/mach/map.h>
     43#include <mach/assabet.h>
     44#include <linux/platform_data/mfd-mcp-sa11x0.h>
     45#include <mach/irqs.h>
     46
     47#include "generic.h"
     48
     49#define ASSABET_BCR_DB1110 \
     50	(ASSABET_BCR_SPK_OFF    | \
     51	 ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
     52	 ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
     53	 ASSABET_BCR_IRDA_MD0)
     54
     55#define ASSABET_BCR_DB1111 \
     56	(ASSABET_BCR_SPK_OFF    | \
     57	 ASSABET_BCR_LED_GREEN  | ASSABET_BCR_LED_RED   | \
     58	 ASSABET_BCR_RS232EN    | ASSABET_BCR_LCD_12RGB | \
     59	 ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
     60	 ASSABET_BCR_IRDA_MD0   | ASSABET_BCR_CF_RST)
     61
     62unsigned long SCR_value = ASSABET_SCR_INIT;
     63EXPORT_SYMBOL(SCR_value);
     64
     65static struct gpio_chip *assabet_bcr_gc;
     66
     67static const char *assabet_names[] = {
     68	"cf_pwr", "cf_gfx_reset", "nsoft_reset", "irda_fsel",
     69	"irda_md0", "irda_md1", "stereo_loopback", "ncf_bus_on",
     70	"audio_pwr_on", "light_pwr_on", "lcd16data", "lcd_pwr_on",
     71	"rs232_on", "nred_led", "ngreen_led", "vib_on",
     72	"com_dtr", "com_rts", "radio_wake_mod", "i2c_enab",
     73	"tvir_enab", "qmute", "radio_pwr_on", "spkr_off",
     74	"rs232_valid", "com_dcd", "com_cts", "com_dsr",
     75	"radio_cts", "radio_dsr", "radio_dcd", "radio_ri",
     76};
     77
     78/* The old deprecated interface */
     79void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
     80{
     81	unsigned long m = mask, v = val;
     82
     83	assabet_bcr_gc->set_multiple(assabet_bcr_gc, &m, &v);
     84}
     85EXPORT_SYMBOL(ASSABET_BCR_frob);
     86
     87static void __init assabet_init_gpio(void __iomem *reg, u32 def_val)
     88{
     89	struct gpio_chip *gc;
     90
     91	writel_relaxed(def_val, reg);
     92
     93	gc = gpio_reg_init(NULL, reg, -1, 32, "assabet", 0xff000000, def_val,
     94			   assabet_names, NULL, NULL);
     95
     96	if (IS_ERR(gc))
     97		return;
     98
     99	assabet_bcr_gc = gc;
    100}
    101
    102/*
    103 * The codec reset goes to three devices, so we need to release
    104 * the rest when any one of these requests it.  However, that
    105 * causes the ADV7171 to consume around 100mA - more than half
    106 * the LCD-blanked power.
    107 *
    108 * With the ADV7171, LCD and backlight enabled, we go over
    109 * budget on the MAX846 Li-Ion charger, and if no Li-Ion battery
    110 * is connected, the Assabet crashes.
    111 */
    112#define RST_UCB1X00 (1 << 0)
    113#define RST_UDA1341 (1 << 1)
    114#define RST_ADV7171 (1 << 2)
    115
    116#define SDA GPIO_GPIO(15)
    117#define SCK GPIO_GPIO(18)
    118#define MOD GPIO_GPIO(17)
    119
    120static void adv7171_start(void)
    121{
    122	GPSR = SCK;
    123	udelay(1);
    124	GPSR = SDA;
    125	udelay(2);
    126	GPCR = SDA;
    127}
    128
    129static void adv7171_stop(void)
    130{
    131	GPSR = SCK;
    132	udelay(2);
    133	GPSR = SDA;
    134	udelay(1);
    135}
    136
    137static void adv7171_send(unsigned byte)
    138{
    139	unsigned i;
    140
    141	for (i = 0; i < 8; i++, byte <<= 1) {
    142		GPCR = SCK;
    143		udelay(1);
    144		if (byte & 0x80)
    145			GPSR = SDA;
    146		else
    147			GPCR = SDA;
    148		udelay(1);
    149		GPSR = SCK;
    150		udelay(1);
    151	}
    152	GPCR = SCK;
    153	udelay(1);
    154	GPSR = SDA;
    155	udelay(1);
    156	GPDR &= ~SDA;
    157	GPSR = SCK;
    158	udelay(1);
    159	if (GPLR & SDA)
    160		printk(KERN_WARNING "No ACK from ADV7171\n");
    161	udelay(1);
    162	GPCR = SCK | SDA;
    163	udelay(1);
    164	GPDR |= SDA;
    165	udelay(1);
    166}
    167
    168static void adv7171_write(unsigned reg, unsigned val)
    169{
    170	unsigned gpdr = GPDR;
    171	unsigned gplr = GPLR;
    172
    173	ASSABET_BCR_frob(ASSABET_BCR_AUDIO_ON, ASSABET_BCR_AUDIO_ON);
    174	udelay(100);
    175
    176	GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */
    177	GPDR = (GPDR | SCK | MOD) & ~SDA;
    178	udelay(10);
    179	if (!(GPLR & SDA))
    180		printk(KERN_WARNING "Something dragging SDA down?\n");
    181	GPDR |= SDA;
    182
    183	adv7171_start();
    184	adv7171_send(0x54);
    185	adv7171_send(reg);
    186	adv7171_send(val);
    187	adv7171_stop();
    188
    189	/* Restore GPIO state for L3 bus */
    190	GPSR = gplr & (SDA | SCK | MOD);
    191	GPCR = (~gplr) & (SDA | SCK | MOD);
    192	GPDR = gpdr;
    193}
    194
    195static void adv7171_sleep(void)
    196{
    197	/* Put the ADV7171 into sleep mode */
    198	adv7171_write(0x04, 0x40);
    199}
    200
    201static unsigned codec_nreset;
    202
    203static void assabet_codec_reset(unsigned mask, int set)
    204{
    205	unsigned long flags;
    206	bool old;
    207
    208	local_irq_save(flags);
    209	old = !codec_nreset;
    210	if (set)
    211		codec_nreset &= ~mask;
    212	else
    213		codec_nreset |= mask;
    214
    215	if (old != !codec_nreset) {
    216		if (codec_nreset) {
    217			ASSABET_BCR_set(ASSABET_BCR_NCODEC_RST);
    218			adv7171_sleep();
    219		} else {
    220			ASSABET_BCR_clear(ASSABET_BCR_NCODEC_RST);
    221		}
    222	}
    223	local_irq_restore(flags);
    224}
    225
    226static void assabet_ucb1x00_reset(enum ucb1x00_reset state)
    227{
    228	int set = state == UCB_RST_REMOVE || state == UCB_RST_SUSPEND ||
    229		state == UCB_RST_PROBE_FAIL;
    230	assabet_codec_reset(RST_UCB1X00, set);
    231}
    232
    233void assabet_uda1341_reset(int set)
    234{
    235	assabet_codec_reset(RST_UDA1341, set);
    236}
    237EXPORT_SYMBOL(assabet_uda1341_reset);
    238
    239
    240/*
    241 * Assabet flash support code.
    242 */
    243
    244#ifdef ASSABET_REV_4
    245/*
    246 * Phase 4 Assabet has two 28F160B3 flash parts in bank 0:
    247 */
    248static struct mtd_partition assabet_partitions[] = {
    249	{
    250		.name		= "bootloader",
    251		.size		= 0x00020000,
    252		.offset		= 0,
    253		.mask_flags	= MTD_WRITEABLE,
    254	}, {
    255		.name		= "bootloader params",
    256		.size		= 0x00020000,
    257		.offset		= MTDPART_OFS_APPEND,
    258		.mask_flags	= MTD_WRITEABLE,
    259	}, {
    260		.name		= "jffs",
    261		.size		= MTDPART_SIZ_FULL,
    262		.offset		= MTDPART_OFS_APPEND,
    263	}
    264};
    265#else
    266/*
    267 * Phase 5 Assabet has two 28F128J3A flash parts in bank 0:
    268 */
    269static struct mtd_partition assabet_partitions[] = {
    270	{
    271		.name		= "bootloader",
    272		.size		= 0x00040000,
    273		.offset		= 0,
    274		.mask_flags	= MTD_WRITEABLE,
    275	}, {
    276		.name		= "bootloader params",
    277		.size		= 0x00040000,
    278		.offset		= MTDPART_OFS_APPEND,
    279		.mask_flags	= MTD_WRITEABLE,
    280	}, {
    281		.name		= "jffs",
    282		.size		= MTDPART_SIZ_FULL,
    283		.offset		= MTDPART_OFS_APPEND,
    284	}
    285};
    286#endif
    287
    288static struct flash_platform_data assabet_flash_data = {
    289	.map_name	= "cfi_probe",
    290	.parts		= assabet_partitions,
    291	.nr_parts	= ARRAY_SIZE(assabet_partitions),
    292};
    293
    294static struct resource assabet_flash_resources[] = {
    295	DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
    296	DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M),
    297};
    298
    299
    300/*
    301 * Assabet IrDA support code.
    302 */
    303
    304static int assabet_irda_set_power(struct device *dev, unsigned int state)
    305{
    306	static unsigned int bcr_state[4] = {
    307		ASSABET_BCR_IRDA_MD0,
    308		ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0,
    309		ASSABET_BCR_IRDA_MD1,
    310		0
    311	};
    312
    313	if (state < 4)
    314		ASSABET_BCR_frob(ASSABET_BCR_IRDA_MD1 | ASSABET_BCR_IRDA_MD0,
    315				 bcr_state[state]);
    316	return 0;
    317}
    318
    319static void assabet_irda_set_speed(struct device *dev, unsigned int speed)
    320{
    321	if (speed < 4000000)
    322		ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
    323	else
    324		ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
    325}
    326
    327static struct irda_platform_data assabet_irda_data = {
    328	.set_power	= assabet_irda_set_power,
    329	.set_speed	= assabet_irda_set_speed,
    330};
    331
    332static struct ucb1x00_plat_data assabet_ucb1x00_data = {
    333	.reset		= assabet_ucb1x00_reset,
    334	.gpio_base	= -1,
    335	.can_wakeup	= 1,
    336};
    337
    338static struct mcp_plat_data assabet_mcp_data = {
    339	.mccr0		= MCCR0_ADM,
    340	.sclk_rate	= 11981000,
    341	.codec_pdata	= &assabet_ucb1x00_data,
    342};
    343
    344static void assabet_lcd_set_visual(u32 visual)
    345{
    346	u_int is_true_color = visual == FB_VISUAL_TRUECOLOR;
    347
    348	if (machine_is_assabet()) {
    349#if 1		// phase 4 or newer Assabet's
    350		if (is_true_color)
    351			ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
    352		else
    353			ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
    354#else
    355		// older Assabet's
    356		if (is_true_color)
    357			ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
    358		else
    359			ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
    360#endif
    361	}
    362}
    363
    364#ifndef ASSABET_PAL_VIDEO
    365static void assabet_lcd_backlight_power(int on)
    366{
    367	if (on)
    368		ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
    369	else
    370		ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
    371}
    372
    373/*
    374 * Turn on/off the backlight.  When turning the backlight on, we wait
    375 * 500us after turning it on so we don't cause the supplies to droop
    376 * when we enable the LCD controller (and cause a hard reset.)
    377 */
    378static void assabet_lcd_power(int on)
    379{
    380	if (on) {
    381		ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
    382		udelay(500);
    383	} else
    384		ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
    385}
    386
    387/*
    388 * The assabet uses a sharp LQ039Q2DS54 LCD module.  It is actually
    389 * takes an RGB666 signal, but we provide it with an RGB565 signal
    390 * instead (def_rgb_16).
    391 */
    392static struct sa1100fb_mach_info lq039q2ds54_info = {
    393	.pixclock	= 171521,	.bpp		= 16,
    394	.xres		= 320,		.yres		= 240,
    395
    396	.hsync_len	= 5,		.vsync_len	= 1,
    397	.left_margin	= 61,		.upper_margin	= 3,
    398	.right_margin	= 9,		.lower_margin	= 0,
    399
    400	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
    401
    402	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
    403	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
    404
    405	.backlight_power = assabet_lcd_backlight_power,
    406	.lcd_power = assabet_lcd_power,
    407	.set_visual = assabet_lcd_set_visual,
    408};
    409#else
    410static void assabet_pal_backlight_power(int on)
    411{
    412	ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
    413}
    414
    415static void assabet_pal_power(int on)
    416{
    417	ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
    418}
    419
    420static struct sa1100fb_mach_info pal_info = {
    421	.pixclock	= 67797,	.bpp		= 16,
    422	.xres		= 640,		.yres		= 512,
    423
    424	.hsync_len	= 64,		.vsync_len	= 6,
    425	.left_margin	= 125,		.upper_margin	= 70,
    426	.right_margin	= 115,		.lower_margin	= 36,
    427
    428	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
    429	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
    430
    431	.backlight_power = assabet_pal_backlight_power,
    432	.lcd_power = assabet_pal_power,
    433	.set_visual = assabet_lcd_set_visual,
    434};
    435#endif
    436
    437#ifdef CONFIG_ASSABET_NEPONSET
    438static struct resource neponset_resources[] = {
    439	DEFINE_RES_MEM(0x10000000, 0x08000000),
    440	DEFINE_RES_MEM(0x18000000, 0x04000000),
    441	DEFINE_RES_MEM(0x40000000, SZ_8K),
    442	DEFINE_RES_IRQ(IRQ_GPIO25),
    443};
    444#endif
    445
    446static struct gpiod_lookup_table assabet_cf_gpio_table = {
    447	.dev_id = "sa11x0-pcmcia.1",
    448	.table = {
    449		GPIO_LOOKUP("gpio", 21, "ready", GPIO_ACTIVE_HIGH),
    450		GPIO_LOOKUP("gpio", 22, "detect", GPIO_ACTIVE_LOW),
    451		GPIO_LOOKUP("gpio", 24, "bvd2", GPIO_ACTIVE_HIGH),
    452		GPIO_LOOKUP("gpio", 25, "bvd1", GPIO_ACTIVE_HIGH),
    453		GPIO_LOOKUP("assabet", 1, "reset", GPIO_ACTIVE_HIGH),
    454		GPIO_LOOKUP("assabet", 7, "bus-enable", GPIO_ACTIVE_LOW),
    455		{ },
    456	},
    457};
    458
    459static struct regulator_consumer_supply assabet_cf_vcc_consumers[] = {
    460	REGULATOR_SUPPLY("vcc", "sa11x0-pcmcia.1"),
    461};
    462
    463static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = {
    464	.supply_name = "cf-power",
    465	.microvolts = 3300000,
    466};
    467
    468static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {
    469	.dev_id = "reg-fixed-voltage.0",
    470	.table = {
    471		GPIO_LOOKUP("assabet", 0, NULL, GPIO_ACTIVE_HIGH),
    472		{ },
    473	},
    474};
    475
    476static struct gpiod_lookup_table assabet_leds_gpio_table = {
    477	.dev_id = "leds-gpio",
    478	.table = {
    479		GPIO_LOOKUP("assabet", 13, NULL, GPIO_ACTIVE_LOW),
    480		GPIO_LOOKUP("assabet", 14, NULL, GPIO_ACTIVE_LOW),
    481		{ },
    482	},
    483};
    484
    485static struct gpio_led assabet_leds[] __initdata = {
    486	{
    487		.name = "assabet:red",
    488		.default_trigger = "cpu0",
    489		.default_state = LEDS_GPIO_DEFSTATE_KEEP,
    490	}, {
    491		.name = "assabet:green",
    492		.default_trigger = "heartbeat",
    493		.default_state = LEDS_GPIO_DEFSTATE_KEEP,
    494	},
    495};
    496
    497static const struct gpio_led_platform_data assabet_leds_pdata __initconst = {
    498	.num_leds = ARRAY_SIZE(assabet_leds),
    499	.leds = assabet_leds,
    500};
    501
    502static struct gpio_keys_button assabet_keys_buttons[] = {
    503	{
    504		.gpio = 0,
    505		.irq = IRQ_GPIO0,
    506		.desc = "gpio0",
    507		.wakeup = 1,
    508		.can_disable = 1,
    509		.debounce_interval = 5,
    510	}, {
    511		.gpio = 1,
    512		.irq = IRQ_GPIO1,
    513		.desc = "gpio1",
    514		.wakeup = 1,
    515		.can_disable = 1,
    516		.debounce_interval = 5,
    517	},
    518};
    519
    520static const struct gpio_keys_platform_data assabet_keys_pdata = {
    521	.buttons = assabet_keys_buttons,
    522	.nbuttons = ARRAY_SIZE(assabet_keys_buttons),
    523	.rep = 0,
    524};
    525
    526static struct gpiod_lookup_table assabet_uart1_gpio_table = {
    527	.dev_id = "sa11x0-uart.1",
    528	.table = {
    529		GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW),
    530		GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW),
    531		GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW),
    532		GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW),
    533		GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW),
    534		{ },
    535	},
    536};
    537
    538static struct gpiod_lookup_table assabet_uart3_gpio_table = {
    539	.dev_id = "sa11x0-uart.3",
    540	.table = {
    541		GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW),
    542		GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW),
    543		GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW),
    544		GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW),
    545		{ },
    546	},
    547};
    548
    549static void __init assabet_init(void)
    550{
    551	/*
    552	 * Ensure that the power supply is in "high power" mode.
    553	 */
    554	GPSR = GPIO_GPIO16;
    555	GPDR |= GPIO_GPIO16;
    556
    557	/*
    558	 * Ensure that these pins are set as outputs and are driving
    559	 * logic 0.  This ensures that we won't inadvertently toggle
    560	 * the WS latch in the CPLD, and we don't float causing
    561	 * excessive power drain.  --rmk
    562	 */
    563	GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
    564	GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
    565
    566	/*
    567	 * Also set GPIO27 as an output; this is used to clock UART3
    568	 * via the FPGA and as otherwise has no pullups or pulldowns,
    569	 * so stop it floating.
    570	 */
    571	GPCR = GPIO_GPIO27;
    572	GPDR |= GPIO_GPIO27;
    573
    574	/*
    575	 * Set up registers for sleep mode.
    576	 */
    577	PWER = PWER_GPIO0;
    578	PGSR = 0;
    579	PCFR = 0;
    580	PSDR = 0;
    581	PPDR |= PPC_TXD3 | PPC_TXD1;
    582	PPSR |= PPC_TXD3 | PPC_TXD1;
    583
    584	sa11x0_ppc_configure_mcp();
    585
    586	if (machine_has_neponset()) {
    587#ifndef CONFIG_ASSABET_NEPONSET
    588		printk( "Warning: Neponset detected but full support "
    589			"hasn't been configured in the kernel\n" );
    590#else
    591		platform_device_register_simple("neponset", 0,
    592			neponset_resources, ARRAY_SIZE(neponset_resources));
    593#endif
    594	} else {
    595		gpiod_add_lookup_table(&assabet_uart1_gpio_table);
    596		gpiod_add_lookup_table(&assabet_uart3_gpio_table);
    597		gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
    598
    599		sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
    600					assabet_cf_vcc_consumers,
    601					ARRAY_SIZE(assabet_cf_vcc_consumers),
    602					true);
    603
    604	}
    605
    606	platform_device_register_resndata(NULL, "gpio-keys", 0,
    607					  NULL, 0,
    608					  &assabet_keys_pdata,
    609					  sizeof(assabet_keys_pdata));
    610
    611	gpiod_add_lookup_table(&assabet_leds_gpio_table);
    612	gpio_led_register_device(-1, &assabet_leds_pdata);
    613
    614#ifndef ASSABET_PAL_VIDEO
    615	sa11x0_register_lcd(&lq039q2ds54_info);
    616#else
    617	sa11x0_register_lcd(&pal_video);
    618#endif
    619	sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
    620			    ARRAY_SIZE(assabet_flash_resources));
    621	sa11x0_register_irda(&assabet_irda_data);
    622	sa11x0_register_mcp(&assabet_mcp_data);
    623
    624	if (!machine_has_neponset())
    625		sa11x0_register_pcmcia(1, &assabet_cf_gpio_table);
    626}
    627
    628/*
    629 * On Assabet, we must probe for the Neponset board _before_
    630 * paging_init() has occurred to actually determine the amount
    631 * of RAM available.  To do so, we map the appropriate IO section
    632 * in the page table here in order to access GPIO registers.
    633 */
    634static void __init map_sa1100_gpio_regs( void )
    635{
    636	unsigned long phys = __PREG(GPLR) & PMD_MASK;
    637	unsigned long virt = (unsigned long)io_p2v(phys);
    638	int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
    639	pmd_t *pmd;
    640
    641	pmd = pmd_off_k(virt);
    642	*pmd = __pmd(phys | prot);
    643	flush_pmd_entry(pmd);
    644}
    645
    646/*
    647 * Read System Configuration "Register"
    648 * (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
    649 * User's Guide", section 4.4.1)
    650 *
    651 * This same scan is performed in arch/arm/boot/compressed/head-sa1100.S
    652 * to set up the serial port for decompression status messages. We
    653 * repeat it here because the kernel may not be loaded as a zImage, and
    654 * also because it's a hassle to communicate the SCR value to the kernel
    655 * from the decompressor.
    656 *
    657 * Note that IRQs are guaranteed to be disabled.
    658 */
    659static void __init get_assabet_scr(void)
    660{
    661	unsigned long scr, i;
    662
    663	GPDR |= 0x3fc;			/* Configure GPIO 9:2 as outputs */
    664	GPSR = 0x3fc;			/* Write 0xFF to GPIO 9:2 */
    665	GPDR &= ~(0x3fc);		/* Configure GPIO 9:2 as inputs */
    666	for(i = 100; i--; )		/* Read GPIO 9:2 */
    667		scr = GPLR;
    668	GPDR |= 0x3fc;			/*  restore correct pin direction */
    669	scr &= 0x3fc;			/* save as system configuration byte. */
    670	SCR_value = scr;
    671}
    672
    673static void __init
    674fixup_assabet(struct tag *tags, char **cmdline)
    675{
    676	/* This must be done before any call to machine_has_neponset() */
    677	map_sa1100_gpio_regs();
    678	get_assabet_scr();
    679
    680	if (machine_has_neponset())
    681		printk("Neponset expansion board detected\n");
    682}
    683
    684
    685static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
    686{
    687	if (port->mapbase == _Ser1UTCR0) {
    688		if (state)
    689			ASSABET_BCR_clear(ASSABET_BCR_RS232EN);
    690		else
    691			ASSABET_BCR_set(ASSABET_BCR_RS232EN);
    692	}
    693}
    694
    695static struct sa1100_port_fns assabet_port_fns __initdata = {
    696	.pm		= assabet_uart_pm,
    697};
    698
    699static struct map_desc assabet_io_desc[] __initdata = {
    700  	{	/* Board Control Register */
    701		.virtual	=  0xf1000000,
    702		.pfn		= __phys_to_pfn(0x12000000),
    703		.length		= 0x00100000,
    704		.type		= MT_DEVICE
    705	}, {	/* MQ200 */
    706		.virtual	=  0xf2800000,
    707		.pfn		= __phys_to_pfn(0x4b800000),
    708		.length		= 0x00800000,
    709		.type		= MT_DEVICE
    710	}
    711};
    712
    713static void __init assabet_map_io(void)
    714{
    715	sa1100_map_io();
    716	iotable_init(assabet_io_desc, ARRAY_SIZE(assabet_io_desc));
    717
    718	/*
    719	 * Set SUS bit in SDCR0 so serial port 1 functions.
    720	 * Its called GPCLKR0 in my SA1110 manual.
    721	 */
    722	Ser1SDCR0 |= SDCR0_SUS;
    723	MSC1 = (MSC1 & ~0xffff) |
    724		MSC_NonBrst | MSC_32BitStMem |
    725		MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0);
    726
    727	if (!machine_has_neponset())
    728		sa1100_register_uart_fns(&assabet_port_fns);
    729
    730	/*
    731	 * When Neponset is attached, the first UART should be
    732	 * UART3.  That's what Angel is doing and many documents
    733	 * are stating this.
    734	 *
    735	 * We do the Neponset mapping even if Neponset support
    736	 * isn't compiled in so the user will still get something on
    737	 * the expected physical serial port.
    738	 *
    739	 * We no longer do this; not all boot loaders support it,
    740	 * and UART3 appears to be somewhat unreliable with blob.
    741	 */
    742	sa1100_register_uart(0, 1);
    743	sa1100_register_uart(2, 3);
    744}
    745
    746void __init assabet_init_irq(void)
    747{
    748	u32 def_val;
    749
    750	sa1100_init_irq();
    751
    752	if (machine_has_neponset())
    753		def_val = ASSABET_BCR_DB1111;
    754	else
    755		def_val = ASSABET_BCR_DB1110;
    756
    757	/*
    758	 * Angel sets this, but other bootloaders may not.
    759	 *
    760	 * This must precede any driver calls to BCR_set() or BCR_clear().
    761	 */
    762	assabet_init_gpio((void *)&ASSABET_BCR, def_val);
    763}
    764
    765MACHINE_START(ASSABET, "Intel-Assabet")
    766	.atag_offset	= 0x100,
    767	.fixup		= fixup_assabet,
    768	.map_io		= assabet_map_io,
    769	.nr_irqs	= SA1100_NR_IRQS,
    770	.init_irq	= assabet_init_irq,
    771	.init_time	= sa1100_timer_init,
    772	.init_machine	= assabet_init,
    773	.init_late	= sa11x0_init_late,
    774#ifdef CONFIG_SA1111
    775	.dma_zone_size	= SZ_1M,
    776#endif
    777	.restart	= sa11x0_restart,
    778MACHINE_END