18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/mach-sa1100/assabet.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Nicolas Pitre 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file contains all Assabet-specific tweaks. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/errno.h> 138c2ecf20Sopenharmony_ci#include <linux/gpio/gpio-reg.h> 148c2ecf20Sopenharmony_ci#include <linux/gpio/machine.h> 158c2ecf20Sopenharmony_ci#include <linux/gpio_keys.h> 168c2ecf20Sopenharmony_ci#include <linux/ioport.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_data/sa11x0-serial.h> 188c2ecf20Sopenharmony_ci#include <linux/regulator/fixed.h> 198c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 208c2ecf20Sopenharmony_ci#include <linux/serial_core.h> 218c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 228c2ecf20Sopenharmony_ci#include <linux/mfd/ucb1x00.h> 238c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 248c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h> 258c2ecf20Sopenharmony_ci#include <linux/delay.h> 268c2ecf20Sopenharmony_ci#include <linux/mm.h> 278c2ecf20Sopenharmony_ci#include <linux/leds.h> 288c2ecf20Sopenharmony_ci#include <linux/slab.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <video/sa1100fb.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <mach/hardware.h> 338c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 348c2ecf20Sopenharmony_ci#include <asm/setup.h> 358c2ecf20Sopenharmony_ci#include <asm/page.h> 368c2ecf20Sopenharmony_ci#include <asm/pgtable-hwdef.h> 378c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 408c2ecf20Sopenharmony_ci#include <asm/mach/flash.h> 418c2ecf20Sopenharmony_ci#include <linux/platform_data/irda-sa11x0.h> 428c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 438c2ecf20Sopenharmony_ci#include <mach/assabet.h> 448c2ecf20Sopenharmony_ci#include <linux/platform_data/mfd-mcp-sa11x0.h> 458c2ecf20Sopenharmony_ci#include <mach/irqs.h> 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#include "generic.h" 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define ASSABET_BCR_DB1110 \ 508c2ecf20Sopenharmony_ci (ASSABET_BCR_SPK_OFF | \ 518c2ecf20Sopenharmony_ci ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \ 528c2ecf20Sopenharmony_ci ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \ 538c2ecf20Sopenharmony_ci ASSABET_BCR_IRDA_MD0) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define ASSABET_BCR_DB1111 \ 568c2ecf20Sopenharmony_ci (ASSABET_BCR_SPK_OFF | \ 578c2ecf20Sopenharmony_ci ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \ 588c2ecf20Sopenharmony_ci ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \ 598c2ecf20Sopenharmony_ci ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \ 608c2ecf20Sopenharmony_ci ASSABET_BCR_IRDA_MD0 | ASSABET_BCR_CF_RST) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciunsigned long SCR_value = ASSABET_SCR_INIT; 638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(SCR_value); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic struct gpio_chip *assabet_bcr_gc; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic const char *assabet_names[] = { 688c2ecf20Sopenharmony_ci "cf_pwr", "cf_gfx_reset", "nsoft_reset", "irda_fsel", 698c2ecf20Sopenharmony_ci "irda_md0", "irda_md1", "stereo_loopback", "ncf_bus_on", 708c2ecf20Sopenharmony_ci "audio_pwr_on", "light_pwr_on", "lcd16data", "lcd_pwr_on", 718c2ecf20Sopenharmony_ci "rs232_on", "nred_led", "ngreen_led", "vib_on", 728c2ecf20Sopenharmony_ci "com_dtr", "com_rts", "radio_wake_mod", "i2c_enab", 738c2ecf20Sopenharmony_ci "tvir_enab", "qmute", "radio_pwr_on", "spkr_off", 748c2ecf20Sopenharmony_ci "rs232_valid", "com_dcd", "com_cts", "com_dsr", 758c2ecf20Sopenharmony_ci "radio_cts", "radio_dsr", "radio_dcd", "radio_ri", 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* The old deprecated interface */ 798c2ecf20Sopenharmony_civoid ASSABET_BCR_frob(unsigned int mask, unsigned int val) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci unsigned long m = mask, v = val; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci assabet_bcr_gc->set_multiple(assabet_bcr_gc, &m, &v); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ASSABET_BCR_frob); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic int __init assabet_init_gpio(void __iomem *reg, u32 def_val) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct gpio_chip *gc; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci writel_relaxed(def_val, reg); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci gc = gpio_reg_init(NULL, reg, -1, 32, "assabet", 0xff000000, def_val, 948c2ecf20Sopenharmony_ci assabet_names, NULL, NULL); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (IS_ERR(gc)) 978c2ecf20Sopenharmony_ci return PTR_ERR(gc); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci assabet_bcr_gc = gc; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return gc->base; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* 1058c2ecf20Sopenharmony_ci * The codec reset goes to three devices, so we need to release 1068c2ecf20Sopenharmony_ci * the rest when any one of these requests it. However, that 1078c2ecf20Sopenharmony_ci * causes the ADV7171 to consume around 100mA - more than half 1088c2ecf20Sopenharmony_ci * the LCD-blanked power. 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * With the ADV7171, LCD and backlight enabled, we go over 1118c2ecf20Sopenharmony_ci * budget on the MAX846 Li-Ion charger, and if no Li-Ion battery 1128c2ecf20Sopenharmony_ci * is connected, the Assabet crashes. 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci#define RST_UCB1X00 (1 << 0) 1158c2ecf20Sopenharmony_ci#define RST_UDA1341 (1 << 1) 1168c2ecf20Sopenharmony_ci#define RST_ADV7171 (1 << 2) 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define SDA GPIO_GPIO(15) 1198c2ecf20Sopenharmony_ci#define SCK GPIO_GPIO(18) 1208c2ecf20Sopenharmony_ci#define MOD GPIO_GPIO(17) 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic void adv7171_start(void) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci GPSR = SCK; 1258c2ecf20Sopenharmony_ci udelay(1); 1268c2ecf20Sopenharmony_ci GPSR = SDA; 1278c2ecf20Sopenharmony_ci udelay(2); 1288c2ecf20Sopenharmony_ci GPCR = SDA; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void adv7171_stop(void) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci GPSR = SCK; 1348c2ecf20Sopenharmony_ci udelay(2); 1358c2ecf20Sopenharmony_ci GPSR = SDA; 1368c2ecf20Sopenharmony_ci udelay(1); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic void adv7171_send(unsigned byte) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci unsigned i; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++, byte <<= 1) { 1448c2ecf20Sopenharmony_ci GPCR = SCK; 1458c2ecf20Sopenharmony_ci udelay(1); 1468c2ecf20Sopenharmony_ci if (byte & 0x80) 1478c2ecf20Sopenharmony_ci GPSR = SDA; 1488c2ecf20Sopenharmony_ci else 1498c2ecf20Sopenharmony_ci GPCR = SDA; 1508c2ecf20Sopenharmony_ci udelay(1); 1518c2ecf20Sopenharmony_ci GPSR = SCK; 1528c2ecf20Sopenharmony_ci udelay(1); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci GPCR = SCK; 1558c2ecf20Sopenharmony_ci udelay(1); 1568c2ecf20Sopenharmony_ci GPSR = SDA; 1578c2ecf20Sopenharmony_ci udelay(1); 1588c2ecf20Sopenharmony_ci GPDR &= ~SDA; 1598c2ecf20Sopenharmony_ci GPSR = SCK; 1608c2ecf20Sopenharmony_ci udelay(1); 1618c2ecf20Sopenharmony_ci if (GPLR & SDA) 1628c2ecf20Sopenharmony_ci printk(KERN_WARNING "No ACK from ADV7171\n"); 1638c2ecf20Sopenharmony_ci udelay(1); 1648c2ecf20Sopenharmony_ci GPCR = SCK | SDA; 1658c2ecf20Sopenharmony_ci udelay(1); 1668c2ecf20Sopenharmony_ci GPDR |= SDA; 1678c2ecf20Sopenharmony_ci udelay(1); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic void adv7171_write(unsigned reg, unsigned val) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci unsigned gpdr = GPDR; 1738c2ecf20Sopenharmony_ci unsigned gplr = GPLR; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci ASSABET_BCR_frob(ASSABET_BCR_AUDIO_ON, ASSABET_BCR_AUDIO_ON); 1768c2ecf20Sopenharmony_ci udelay(100); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */ 1798c2ecf20Sopenharmony_ci GPDR = (GPDR | SCK | MOD) & ~SDA; 1808c2ecf20Sopenharmony_ci udelay(10); 1818c2ecf20Sopenharmony_ci if (!(GPLR & SDA)) 1828c2ecf20Sopenharmony_ci printk(KERN_WARNING "Something dragging SDA down?\n"); 1838c2ecf20Sopenharmony_ci GPDR |= SDA; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci adv7171_start(); 1868c2ecf20Sopenharmony_ci adv7171_send(0x54); 1878c2ecf20Sopenharmony_ci adv7171_send(reg); 1888c2ecf20Sopenharmony_ci adv7171_send(val); 1898c2ecf20Sopenharmony_ci adv7171_stop(); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* Restore GPIO state for L3 bus */ 1928c2ecf20Sopenharmony_ci GPSR = gplr & (SDA | SCK | MOD); 1938c2ecf20Sopenharmony_ci GPCR = (~gplr) & (SDA | SCK | MOD); 1948c2ecf20Sopenharmony_ci GPDR = gpdr; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic void adv7171_sleep(void) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci /* Put the ADV7171 into sleep mode */ 2008c2ecf20Sopenharmony_ci adv7171_write(0x04, 0x40); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic unsigned codec_nreset; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic void assabet_codec_reset(unsigned mask, int set) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci unsigned long flags; 2088c2ecf20Sopenharmony_ci bool old; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci local_irq_save(flags); 2118c2ecf20Sopenharmony_ci old = !codec_nreset; 2128c2ecf20Sopenharmony_ci if (set) 2138c2ecf20Sopenharmony_ci codec_nreset &= ~mask; 2148c2ecf20Sopenharmony_ci else 2158c2ecf20Sopenharmony_ci codec_nreset |= mask; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (old != !codec_nreset) { 2188c2ecf20Sopenharmony_ci if (codec_nreset) { 2198c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_NCODEC_RST); 2208c2ecf20Sopenharmony_ci adv7171_sleep(); 2218c2ecf20Sopenharmony_ci } else { 2228c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_NCODEC_RST); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci local_irq_restore(flags); 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic void assabet_ucb1x00_reset(enum ucb1x00_reset state) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci int set = state == UCB_RST_REMOVE || state == UCB_RST_SUSPEND || 2318c2ecf20Sopenharmony_ci state == UCB_RST_PROBE_FAIL; 2328c2ecf20Sopenharmony_ci assabet_codec_reset(RST_UCB1X00, set); 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_civoid assabet_uda1341_reset(int set) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci assabet_codec_reset(RST_UDA1341, set); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(assabet_uda1341_reset); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci/* 2438c2ecf20Sopenharmony_ci * Assabet flash support code. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci#ifdef ASSABET_REV_4 2478c2ecf20Sopenharmony_ci/* 2488c2ecf20Sopenharmony_ci * Phase 4 Assabet has two 28F160B3 flash parts in bank 0: 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_cistatic struct mtd_partition assabet_partitions[] = { 2518c2ecf20Sopenharmony_ci { 2528c2ecf20Sopenharmony_ci .name = "bootloader", 2538c2ecf20Sopenharmony_ci .size = 0x00020000, 2548c2ecf20Sopenharmony_ci .offset = 0, 2558c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 2568c2ecf20Sopenharmony_ci }, { 2578c2ecf20Sopenharmony_ci .name = "bootloader params", 2588c2ecf20Sopenharmony_ci .size = 0x00020000, 2598c2ecf20Sopenharmony_ci .offset = MTDPART_OFS_APPEND, 2608c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 2618c2ecf20Sopenharmony_ci }, { 2628c2ecf20Sopenharmony_ci .name = "jffs", 2638c2ecf20Sopenharmony_ci .size = MTDPART_SIZ_FULL, 2648c2ecf20Sopenharmony_ci .offset = MTDPART_OFS_APPEND, 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci}; 2678c2ecf20Sopenharmony_ci#else 2688c2ecf20Sopenharmony_ci/* 2698c2ecf20Sopenharmony_ci * Phase 5 Assabet has two 28F128J3A flash parts in bank 0: 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_cistatic struct mtd_partition assabet_partitions[] = { 2728c2ecf20Sopenharmony_ci { 2738c2ecf20Sopenharmony_ci .name = "bootloader", 2748c2ecf20Sopenharmony_ci .size = 0x00040000, 2758c2ecf20Sopenharmony_ci .offset = 0, 2768c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 2778c2ecf20Sopenharmony_ci }, { 2788c2ecf20Sopenharmony_ci .name = "bootloader params", 2798c2ecf20Sopenharmony_ci .size = 0x00040000, 2808c2ecf20Sopenharmony_ci .offset = MTDPART_OFS_APPEND, 2818c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 2828c2ecf20Sopenharmony_ci }, { 2838c2ecf20Sopenharmony_ci .name = "jffs", 2848c2ecf20Sopenharmony_ci .size = MTDPART_SIZ_FULL, 2858c2ecf20Sopenharmony_ci .offset = MTDPART_OFS_APPEND, 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci}; 2888c2ecf20Sopenharmony_ci#endif 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic struct flash_platform_data assabet_flash_data = { 2918c2ecf20Sopenharmony_ci .map_name = "cfi_probe", 2928c2ecf20Sopenharmony_ci .parts = assabet_partitions, 2938c2ecf20Sopenharmony_ci .nr_parts = ARRAY_SIZE(assabet_partitions), 2948c2ecf20Sopenharmony_ci}; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic struct resource assabet_flash_resources[] = { 2978c2ecf20Sopenharmony_ci DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M), 2988c2ecf20Sopenharmony_ci DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M), 2998c2ecf20Sopenharmony_ci}; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci/* 3038c2ecf20Sopenharmony_ci * Assabet IrDA support code. 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic int assabet_irda_set_power(struct device *dev, unsigned int state) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci static unsigned int bcr_state[4] = { 3098c2ecf20Sopenharmony_ci ASSABET_BCR_IRDA_MD0, 3108c2ecf20Sopenharmony_ci ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0, 3118c2ecf20Sopenharmony_ci ASSABET_BCR_IRDA_MD1, 3128c2ecf20Sopenharmony_ci 0 3138c2ecf20Sopenharmony_ci }; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (state < 4) 3168c2ecf20Sopenharmony_ci ASSABET_BCR_frob(ASSABET_BCR_IRDA_MD1 | ASSABET_BCR_IRDA_MD0, 3178c2ecf20Sopenharmony_ci bcr_state[state]); 3188c2ecf20Sopenharmony_ci return 0; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void assabet_irda_set_speed(struct device *dev, unsigned int speed) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci if (speed < 4000000) 3248c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL); 3258c2ecf20Sopenharmony_ci else 3268c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL); 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic struct irda_platform_data assabet_irda_data = { 3308c2ecf20Sopenharmony_ci .set_power = assabet_irda_set_power, 3318c2ecf20Sopenharmony_ci .set_speed = assabet_irda_set_speed, 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic struct ucb1x00_plat_data assabet_ucb1x00_data = { 3358c2ecf20Sopenharmony_ci .reset = assabet_ucb1x00_reset, 3368c2ecf20Sopenharmony_ci .gpio_base = -1, 3378c2ecf20Sopenharmony_ci .can_wakeup = 1, 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic struct mcp_plat_data assabet_mcp_data = { 3418c2ecf20Sopenharmony_ci .mccr0 = MCCR0_ADM, 3428c2ecf20Sopenharmony_ci .sclk_rate = 11981000, 3438c2ecf20Sopenharmony_ci .codec_pdata = &assabet_ucb1x00_data, 3448c2ecf20Sopenharmony_ci}; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic void assabet_lcd_set_visual(u32 visual) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci u_int is_true_color = visual == FB_VISUAL_TRUECOLOR; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (machine_is_assabet()) { 3518c2ecf20Sopenharmony_ci#if 1 // phase 4 or newer Assabet's 3528c2ecf20Sopenharmony_ci if (is_true_color) 3538c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); 3548c2ecf20Sopenharmony_ci else 3558c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB); 3568c2ecf20Sopenharmony_ci#else 3578c2ecf20Sopenharmony_ci // older Assabet's 3588c2ecf20Sopenharmony_ci if (is_true_color) 3598c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB); 3608c2ecf20Sopenharmony_ci else 3618c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); 3628c2ecf20Sopenharmony_ci#endif 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci#ifndef ASSABET_PAL_VIDEO 3678c2ecf20Sopenharmony_cistatic void assabet_lcd_backlight_power(int on) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci if (on) 3708c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON); 3718c2ecf20Sopenharmony_ci else 3728c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci/* 3768c2ecf20Sopenharmony_ci * Turn on/off the backlight. When turning the backlight on, we wait 3778c2ecf20Sopenharmony_ci * 500us after turning it on so we don't cause the supplies to droop 3788c2ecf20Sopenharmony_ci * when we enable the LCD controller (and cause a hard reset.) 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_cistatic void assabet_lcd_power(int on) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci if (on) { 3838c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_LCD_ON); 3848c2ecf20Sopenharmony_ci udelay(500); 3858c2ecf20Sopenharmony_ci } else 3868c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci/* 3908c2ecf20Sopenharmony_ci * The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually 3918c2ecf20Sopenharmony_ci * takes an RGB666 signal, but we provide it with an RGB565 signal 3928c2ecf20Sopenharmony_ci * instead (def_rgb_16). 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_cistatic struct sa1100fb_mach_info lq039q2ds54_info = { 3958c2ecf20Sopenharmony_ci .pixclock = 171521, .bpp = 16, 3968c2ecf20Sopenharmony_ci .xres = 320, .yres = 240, 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci .hsync_len = 5, .vsync_len = 1, 3998c2ecf20Sopenharmony_ci .left_margin = 61, .upper_margin = 3, 4008c2ecf20Sopenharmony_ci .right_margin = 9, .lower_margin = 0, 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 4058c2ecf20Sopenharmony_ci .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci .backlight_power = assabet_lcd_backlight_power, 4088c2ecf20Sopenharmony_ci .lcd_power = assabet_lcd_power, 4098c2ecf20Sopenharmony_ci .set_visual = assabet_lcd_set_visual, 4108c2ecf20Sopenharmony_ci}; 4118c2ecf20Sopenharmony_ci#else 4128c2ecf20Sopenharmony_cistatic void assabet_pal_backlight_power(int on) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cistatic void assabet_pal_power(int on) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic struct sa1100fb_mach_info pal_info = { 4238c2ecf20Sopenharmony_ci .pixclock = 67797, .bpp = 16, 4248c2ecf20Sopenharmony_ci .xres = 640, .yres = 512, 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci .hsync_len = 64, .vsync_len = 6, 4278c2ecf20Sopenharmony_ci .left_margin = 125, .upper_margin = 70, 4288c2ecf20Sopenharmony_ci .right_margin = 115, .lower_margin = 36, 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 4318c2ecf20Sopenharmony_ci .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci .backlight_power = assabet_pal_backlight_power, 4348c2ecf20Sopenharmony_ci .lcd_power = assabet_pal_power, 4358c2ecf20Sopenharmony_ci .set_visual = assabet_lcd_set_visual, 4368c2ecf20Sopenharmony_ci}; 4378c2ecf20Sopenharmony_ci#endif 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci#ifdef CONFIG_ASSABET_NEPONSET 4408c2ecf20Sopenharmony_cistatic struct resource neponset_resources[] = { 4418c2ecf20Sopenharmony_ci DEFINE_RES_MEM(0x10000000, 0x08000000), 4428c2ecf20Sopenharmony_ci DEFINE_RES_MEM(0x18000000, 0x04000000), 4438c2ecf20Sopenharmony_ci DEFINE_RES_MEM(0x40000000, SZ_8K), 4448c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_GPIO25), 4458c2ecf20Sopenharmony_ci}; 4468c2ecf20Sopenharmony_ci#endif 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table assabet_cf_gpio_table = { 4498c2ecf20Sopenharmony_ci .dev_id = "sa11x0-pcmcia.1", 4508c2ecf20Sopenharmony_ci .table = { 4518c2ecf20Sopenharmony_ci GPIO_LOOKUP("gpio", 21, "ready", GPIO_ACTIVE_HIGH), 4528c2ecf20Sopenharmony_ci GPIO_LOOKUP("gpio", 22, "detect", GPIO_ACTIVE_LOW), 4538c2ecf20Sopenharmony_ci GPIO_LOOKUP("gpio", 24, "bvd2", GPIO_ACTIVE_HIGH), 4548c2ecf20Sopenharmony_ci GPIO_LOOKUP("gpio", 25, "bvd1", GPIO_ACTIVE_HIGH), 4558c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 1, "reset", GPIO_ACTIVE_HIGH), 4568c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 7, "bus-enable", GPIO_ACTIVE_LOW), 4578c2ecf20Sopenharmony_ci { }, 4588c2ecf20Sopenharmony_ci }, 4598c2ecf20Sopenharmony_ci}; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic struct regulator_consumer_supply assabet_cf_vcc_consumers[] = { 4628c2ecf20Sopenharmony_ci REGULATOR_SUPPLY("vcc", "sa11x0-pcmcia.1"), 4638c2ecf20Sopenharmony_ci}; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_cistatic struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = { 4668c2ecf20Sopenharmony_ci .supply_name = "cf-power", 4678c2ecf20Sopenharmony_ci .microvolts = 3300000, 4688c2ecf20Sopenharmony_ci}; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table assabet_cf_vcc_gpio_table = { 4718c2ecf20Sopenharmony_ci .dev_id = "reg-fixed-voltage.0", 4728c2ecf20Sopenharmony_ci .table = { 4738c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 0, NULL, GPIO_ACTIVE_HIGH), 4748c2ecf20Sopenharmony_ci { }, 4758c2ecf20Sopenharmony_ci }, 4768c2ecf20Sopenharmony_ci}; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic struct gpio_led assabet_leds[] __initdata = { 4798c2ecf20Sopenharmony_ci { 4808c2ecf20Sopenharmony_ci .name = "assabet:red", 4818c2ecf20Sopenharmony_ci .default_trigger = "cpu0", 4828c2ecf20Sopenharmony_ci .active_low = 1, 4838c2ecf20Sopenharmony_ci .default_state = LEDS_GPIO_DEFSTATE_KEEP, 4848c2ecf20Sopenharmony_ci }, { 4858c2ecf20Sopenharmony_ci .name = "assabet:green", 4868c2ecf20Sopenharmony_ci .default_trigger = "heartbeat", 4878c2ecf20Sopenharmony_ci .active_low = 1, 4888c2ecf20Sopenharmony_ci .default_state = LEDS_GPIO_DEFSTATE_KEEP, 4898c2ecf20Sopenharmony_ci }, 4908c2ecf20Sopenharmony_ci}; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic const struct gpio_led_platform_data assabet_leds_pdata __initconst = { 4938c2ecf20Sopenharmony_ci .num_leds = ARRAY_SIZE(assabet_leds), 4948c2ecf20Sopenharmony_ci .leds = assabet_leds, 4958c2ecf20Sopenharmony_ci}; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic struct gpio_keys_button assabet_keys_buttons[] = { 4988c2ecf20Sopenharmony_ci { 4998c2ecf20Sopenharmony_ci .gpio = 0, 5008c2ecf20Sopenharmony_ci .irq = IRQ_GPIO0, 5018c2ecf20Sopenharmony_ci .desc = "gpio0", 5028c2ecf20Sopenharmony_ci .wakeup = 1, 5038c2ecf20Sopenharmony_ci .can_disable = 1, 5048c2ecf20Sopenharmony_ci .debounce_interval = 5, 5058c2ecf20Sopenharmony_ci }, { 5068c2ecf20Sopenharmony_ci .gpio = 1, 5078c2ecf20Sopenharmony_ci .irq = IRQ_GPIO1, 5088c2ecf20Sopenharmony_ci .desc = "gpio1", 5098c2ecf20Sopenharmony_ci .wakeup = 1, 5108c2ecf20Sopenharmony_ci .can_disable = 1, 5118c2ecf20Sopenharmony_ci .debounce_interval = 5, 5128c2ecf20Sopenharmony_ci }, 5138c2ecf20Sopenharmony_ci}; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic const struct gpio_keys_platform_data assabet_keys_pdata = { 5168c2ecf20Sopenharmony_ci .buttons = assabet_keys_buttons, 5178c2ecf20Sopenharmony_ci .nbuttons = ARRAY_SIZE(assabet_keys_buttons), 5188c2ecf20Sopenharmony_ci .rep = 0, 5198c2ecf20Sopenharmony_ci}; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table assabet_uart1_gpio_table = { 5228c2ecf20Sopenharmony_ci .dev_id = "sa11x0-uart.1", 5238c2ecf20Sopenharmony_ci .table = { 5248c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW), 5258c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW), 5268c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW), 5278c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW), 5288c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW), 5298c2ecf20Sopenharmony_ci { }, 5308c2ecf20Sopenharmony_ci }, 5318c2ecf20Sopenharmony_ci}; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table assabet_uart3_gpio_table = { 5348c2ecf20Sopenharmony_ci .dev_id = "sa11x0-uart.3", 5358c2ecf20Sopenharmony_ci .table = { 5368c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW), 5378c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW), 5388c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW), 5398c2ecf20Sopenharmony_ci GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW), 5408c2ecf20Sopenharmony_ci { }, 5418c2ecf20Sopenharmony_ci }, 5428c2ecf20Sopenharmony_ci}; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_cistatic void __init assabet_init(void) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci /* 5478c2ecf20Sopenharmony_ci * Ensure that the power supply is in "high power" mode. 5488c2ecf20Sopenharmony_ci */ 5498c2ecf20Sopenharmony_ci GPSR = GPIO_GPIO16; 5508c2ecf20Sopenharmony_ci GPDR |= GPIO_GPIO16; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* 5538c2ecf20Sopenharmony_ci * Ensure that these pins are set as outputs and are driving 5548c2ecf20Sopenharmony_ci * logic 0. This ensures that we won't inadvertently toggle 5558c2ecf20Sopenharmony_ci * the WS latch in the CPLD, and we don't float causing 5568c2ecf20Sopenharmony_ci * excessive power drain. --rmk 5578c2ecf20Sopenharmony_ci */ 5588c2ecf20Sopenharmony_ci GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; 5598c2ecf20Sopenharmony_ci GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* 5628c2ecf20Sopenharmony_ci * Also set GPIO27 as an output; this is used to clock UART3 5638c2ecf20Sopenharmony_ci * via the FPGA and as otherwise has no pullups or pulldowns, 5648c2ecf20Sopenharmony_ci * so stop it floating. 5658c2ecf20Sopenharmony_ci */ 5668c2ecf20Sopenharmony_ci GPCR = GPIO_GPIO27; 5678c2ecf20Sopenharmony_ci GPDR |= GPIO_GPIO27; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* 5708c2ecf20Sopenharmony_ci * Set up registers for sleep mode. 5718c2ecf20Sopenharmony_ci */ 5728c2ecf20Sopenharmony_ci PWER = PWER_GPIO0; 5738c2ecf20Sopenharmony_ci PGSR = 0; 5748c2ecf20Sopenharmony_ci PCFR = 0; 5758c2ecf20Sopenharmony_ci PSDR = 0; 5768c2ecf20Sopenharmony_ci PPDR |= PPC_TXD3 | PPC_TXD1; 5778c2ecf20Sopenharmony_ci PPSR |= PPC_TXD3 | PPC_TXD1; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci sa11x0_ppc_configure_mcp(); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci if (machine_has_neponset()) { 5828c2ecf20Sopenharmony_ci#ifndef CONFIG_ASSABET_NEPONSET 5838c2ecf20Sopenharmony_ci printk( "Warning: Neponset detected but full support " 5848c2ecf20Sopenharmony_ci "hasn't been configured in the kernel\n" ); 5858c2ecf20Sopenharmony_ci#else 5868c2ecf20Sopenharmony_ci platform_device_register_simple("neponset", 0, 5878c2ecf20Sopenharmony_ci neponset_resources, ARRAY_SIZE(neponset_resources)); 5888c2ecf20Sopenharmony_ci#endif 5898c2ecf20Sopenharmony_ci } else { 5908c2ecf20Sopenharmony_ci gpiod_add_lookup_table(&assabet_uart1_gpio_table); 5918c2ecf20Sopenharmony_ci gpiod_add_lookup_table(&assabet_uart3_gpio_table); 5928c2ecf20Sopenharmony_ci gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata, 5958c2ecf20Sopenharmony_ci assabet_cf_vcc_consumers, 5968c2ecf20Sopenharmony_ci ARRAY_SIZE(assabet_cf_vcc_consumers), 5978c2ecf20Sopenharmony_ci true); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci platform_device_register_resndata(NULL, "gpio-keys", 0, 6028c2ecf20Sopenharmony_ci NULL, 0, 6038c2ecf20Sopenharmony_ci &assabet_keys_pdata, 6048c2ecf20Sopenharmony_ci sizeof(assabet_keys_pdata)); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci gpio_led_register_device(-1, &assabet_leds_pdata); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci#ifndef ASSABET_PAL_VIDEO 6098c2ecf20Sopenharmony_ci sa11x0_register_lcd(&lq039q2ds54_info); 6108c2ecf20Sopenharmony_ci#else 6118c2ecf20Sopenharmony_ci sa11x0_register_lcd(&pal_video); 6128c2ecf20Sopenharmony_ci#endif 6138c2ecf20Sopenharmony_ci sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources, 6148c2ecf20Sopenharmony_ci ARRAY_SIZE(assabet_flash_resources)); 6158c2ecf20Sopenharmony_ci sa11x0_register_irda(&assabet_irda_data); 6168c2ecf20Sopenharmony_ci sa11x0_register_mcp(&assabet_mcp_data); 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (!machine_has_neponset()) 6198c2ecf20Sopenharmony_ci sa11x0_register_pcmcia(1, &assabet_cf_gpio_table); 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci/* 6238c2ecf20Sopenharmony_ci * On Assabet, we must probe for the Neponset board _before_ 6248c2ecf20Sopenharmony_ci * paging_init() has occurred to actually determine the amount 6258c2ecf20Sopenharmony_ci * of RAM available. To do so, we map the appropriate IO section 6268c2ecf20Sopenharmony_ci * in the page table here in order to access GPIO registers. 6278c2ecf20Sopenharmony_ci */ 6288c2ecf20Sopenharmony_cistatic void __init map_sa1100_gpio_regs( void ) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci unsigned long phys = __PREG(GPLR) & PMD_MASK; 6318c2ecf20Sopenharmony_ci unsigned long virt = (unsigned long)io_p2v(phys); 6328c2ecf20Sopenharmony_ci int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO); 6338c2ecf20Sopenharmony_ci pmd_t *pmd; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci pmd = pmd_off_k(virt); 6368c2ecf20Sopenharmony_ci *pmd = __pmd(phys | prot); 6378c2ecf20Sopenharmony_ci flush_pmd_entry(pmd); 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci/* 6418c2ecf20Sopenharmony_ci * Read System Configuration "Register" 6428c2ecf20Sopenharmony_ci * (taken from "Intel StrongARM SA-1110 Microprocessor Development Board 6438c2ecf20Sopenharmony_ci * User's Guide", section 4.4.1) 6448c2ecf20Sopenharmony_ci * 6458c2ecf20Sopenharmony_ci * This same scan is performed in arch/arm/boot/compressed/head-sa1100.S 6468c2ecf20Sopenharmony_ci * to set up the serial port for decompression status messages. We 6478c2ecf20Sopenharmony_ci * repeat it here because the kernel may not be loaded as a zImage, and 6488c2ecf20Sopenharmony_ci * also because it's a hassle to communicate the SCR value to the kernel 6498c2ecf20Sopenharmony_ci * from the decompressor. 6508c2ecf20Sopenharmony_ci * 6518c2ecf20Sopenharmony_ci * Note that IRQs are guaranteed to be disabled. 6528c2ecf20Sopenharmony_ci */ 6538c2ecf20Sopenharmony_cistatic void __init get_assabet_scr(void) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci unsigned long scr, i; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */ 6588c2ecf20Sopenharmony_ci GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */ 6598c2ecf20Sopenharmony_ci GPDR &= ~(0x3fc); /* Configure GPIO 9:2 as inputs */ 6608c2ecf20Sopenharmony_ci for(i = 100; i--; ) /* Read GPIO 9:2 */ 6618c2ecf20Sopenharmony_ci scr = GPLR; 6628c2ecf20Sopenharmony_ci GPDR |= 0x3fc; /* restore correct pin direction */ 6638c2ecf20Sopenharmony_ci scr &= 0x3fc; /* save as system configuration byte. */ 6648c2ecf20Sopenharmony_ci SCR_value = scr; 6658c2ecf20Sopenharmony_ci} 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_cistatic void __init 6688c2ecf20Sopenharmony_cifixup_assabet(struct tag *tags, char **cmdline) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci /* This must be done before any call to machine_has_neponset() */ 6718c2ecf20Sopenharmony_ci map_sa1100_gpio_regs(); 6728c2ecf20Sopenharmony_ci get_assabet_scr(); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci if (machine_has_neponset()) 6758c2ecf20Sopenharmony_ci printk("Neponset expansion board detected\n"); 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci if (port->mapbase == _Ser1UTCR0) { 6828c2ecf20Sopenharmony_ci if (state) 6838c2ecf20Sopenharmony_ci ASSABET_BCR_clear(ASSABET_BCR_RS232EN); 6848c2ecf20Sopenharmony_ci else 6858c2ecf20Sopenharmony_ci ASSABET_BCR_set(ASSABET_BCR_RS232EN); 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic struct sa1100_port_fns assabet_port_fns __initdata = { 6908c2ecf20Sopenharmony_ci .pm = assabet_uart_pm, 6918c2ecf20Sopenharmony_ci}; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic struct map_desc assabet_io_desc[] __initdata = { 6948c2ecf20Sopenharmony_ci { /* Board Control Register */ 6958c2ecf20Sopenharmony_ci .virtual = 0xf1000000, 6968c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0x12000000), 6978c2ecf20Sopenharmony_ci .length = 0x00100000, 6988c2ecf20Sopenharmony_ci .type = MT_DEVICE 6998c2ecf20Sopenharmony_ci }, { /* MQ200 */ 7008c2ecf20Sopenharmony_ci .virtual = 0xf2800000, 7018c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0x4b800000), 7028c2ecf20Sopenharmony_ci .length = 0x00800000, 7038c2ecf20Sopenharmony_ci .type = MT_DEVICE 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci}; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cistatic void __init assabet_map_io(void) 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci sa1100_map_io(); 7108c2ecf20Sopenharmony_ci iotable_init(assabet_io_desc, ARRAY_SIZE(assabet_io_desc)); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* 7138c2ecf20Sopenharmony_ci * Set SUS bit in SDCR0 so serial port 1 functions. 7148c2ecf20Sopenharmony_ci * Its called GPCLKR0 in my SA1110 manual. 7158c2ecf20Sopenharmony_ci */ 7168c2ecf20Sopenharmony_ci Ser1SDCR0 |= SDCR0_SUS; 7178c2ecf20Sopenharmony_ci MSC1 = (MSC1 & ~0xffff) | 7188c2ecf20Sopenharmony_ci MSC_NonBrst | MSC_32BitStMem | 7198c2ecf20Sopenharmony_ci MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci if (!machine_has_neponset()) 7228c2ecf20Sopenharmony_ci sa1100_register_uart_fns(&assabet_port_fns); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* 7258c2ecf20Sopenharmony_ci * When Neponset is attached, the first UART should be 7268c2ecf20Sopenharmony_ci * UART3. That's what Angel is doing and many documents 7278c2ecf20Sopenharmony_ci * are stating this. 7288c2ecf20Sopenharmony_ci * 7298c2ecf20Sopenharmony_ci * We do the Neponset mapping even if Neponset support 7308c2ecf20Sopenharmony_ci * isn't compiled in so the user will still get something on 7318c2ecf20Sopenharmony_ci * the expected physical serial port. 7328c2ecf20Sopenharmony_ci * 7338c2ecf20Sopenharmony_ci * We no longer do this; not all boot loaders support it, 7348c2ecf20Sopenharmony_ci * and UART3 appears to be somewhat unreliable with blob. 7358c2ecf20Sopenharmony_ci */ 7368c2ecf20Sopenharmony_ci sa1100_register_uart(0, 1); 7378c2ecf20Sopenharmony_ci sa1100_register_uart(2, 3); 7388c2ecf20Sopenharmony_ci} 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_civoid __init assabet_init_irq(void) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci unsigned int assabet_gpio_base; 7438c2ecf20Sopenharmony_ci u32 def_val; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci sa1100_init_irq(); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (machine_has_neponset()) 7488c2ecf20Sopenharmony_ci def_val = ASSABET_BCR_DB1111; 7498c2ecf20Sopenharmony_ci else 7508c2ecf20Sopenharmony_ci def_val = ASSABET_BCR_DB1110; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* 7538c2ecf20Sopenharmony_ci * Angel sets this, but other bootloaders may not. 7548c2ecf20Sopenharmony_ci * 7558c2ecf20Sopenharmony_ci * This must precede any driver calls to BCR_set() or BCR_clear(). 7568c2ecf20Sopenharmony_ci */ 7578c2ecf20Sopenharmony_ci assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR, def_val); 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci assabet_leds[0].gpio = assabet_gpio_base + 13; 7608c2ecf20Sopenharmony_ci assabet_leds[1].gpio = assabet_gpio_base + 14; 7618c2ecf20Sopenharmony_ci} 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ciMACHINE_START(ASSABET, "Intel-Assabet") 7648c2ecf20Sopenharmony_ci .atag_offset = 0x100, 7658c2ecf20Sopenharmony_ci .fixup = fixup_assabet, 7668c2ecf20Sopenharmony_ci .map_io = assabet_map_io, 7678c2ecf20Sopenharmony_ci .nr_irqs = SA1100_NR_IRQS, 7688c2ecf20Sopenharmony_ci .init_irq = assabet_init_irq, 7698c2ecf20Sopenharmony_ci .init_time = sa1100_timer_init, 7708c2ecf20Sopenharmony_ci .init_machine = assabet_init, 7718c2ecf20Sopenharmony_ci .init_late = sa11x0_init_late, 7728c2ecf20Sopenharmony_ci#ifdef CONFIG_SA1111 7738c2ecf20Sopenharmony_ci .dma_zone_size = SZ_1M, 7748c2ecf20Sopenharmony_ci#endif 7758c2ecf20Sopenharmony_ci .restart = sa11x0_restart, 7768c2ecf20Sopenharmony_ciMACHINE_END 777