18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/mach-sa1100/generic.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Nicolas Pitre 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Code common to all SA11x0 machines. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/gpio.h> 108c2ecf20Sopenharmony_ci#include <linux/gpio/machine.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 168c2ecf20Sopenharmony_ci#include <linux/pm.h> 178c2ecf20Sopenharmony_ci#include <linux/cpufreq.h> 188c2ecf20Sopenharmony_ci#include <linux/ioport.h> 198c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 208c2ecf20Sopenharmony_ci#include <linux/reboot.h> 218c2ecf20Sopenharmony_ci#include <linux/regulator/fixed.h> 228c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 238c2ecf20Sopenharmony_ci#include <linux/irqchip/irq-sa11x0.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <video/sa1100fb.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include <soc/sa1100/pwer.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <asm/div64.h> 308c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 318c2ecf20Sopenharmony_ci#include <asm/mach/flash.h> 328c2ecf20Sopenharmony_ci#include <asm/irq.h> 338c2ecf20Sopenharmony_ci#include <asm/system_misc.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <mach/hardware.h> 368c2ecf20Sopenharmony_ci#include <mach/irqs.h> 378c2ecf20Sopenharmony_ci#include <mach/reset.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include "generic.h" 408c2ecf20Sopenharmony_ci#include <clocksource/pxa.h> 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciunsigned int reset_status; 438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(reset_status); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define NR_FREQS 16 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* 488c2ecf20Sopenharmony_ci * This table is setup for a 3.6864MHz Crystal. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cistruct cpufreq_frequency_table sa11x0_freq_table[NR_FREQS+1] = { 518c2ecf20Sopenharmony_ci { .frequency = 59000, /* 59.0 MHz */}, 528c2ecf20Sopenharmony_ci { .frequency = 73700, /* 73.7 MHz */}, 538c2ecf20Sopenharmony_ci { .frequency = 88500, /* 88.5 MHz */}, 548c2ecf20Sopenharmony_ci { .frequency = 103200, /* 103.2 MHz */}, 558c2ecf20Sopenharmony_ci { .frequency = 118000, /* 118.0 MHz */}, 568c2ecf20Sopenharmony_ci { .frequency = 132700, /* 132.7 MHz */}, 578c2ecf20Sopenharmony_ci { .frequency = 147500, /* 147.5 MHz */}, 588c2ecf20Sopenharmony_ci { .frequency = 162200, /* 162.2 MHz */}, 598c2ecf20Sopenharmony_ci { .frequency = 176900, /* 176.9 MHz */}, 608c2ecf20Sopenharmony_ci { .frequency = 191700, /* 191.7 MHz */}, 618c2ecf20Sopenharmony_ci { .frequency = 206400, /* 206.4 MHz */}, 628c2ecf20Sopenharmony_ci { .frequency = 221200, /* 221.2 MHz */}, 638c2ecf20Sopenharmony_ci { .frequency = 235900, /* 235.9 MHz */}, 648c2ecf20Sopenharmony_ci { .frequency = 250700, /* 250.7 MHz */}, 658c2ecf20Sopenharmony_ci { .frequency = 265400, /* 265.4 MHz */}, 668c2ecf20Sopenharmony_ci { .frequency = 280200, /* 280.2 MHz */}, 678c2ecf20Sopenharmony_ci { .frequency = CPUFREQ_TABLE_END, }, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciunsigned int sa11x0_getspeed(unsigned int cpu) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci if (cpu) 738c2ecf20Sopenharmony_ci return 0; 748c2ecf20Sopenharmony_ci return sa11x0_freq_table[PPCR & 0xf].frequency; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* 788c2ecf20Sopenharmony_ci * Default power-off for SA1100 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_cistatic void sa1100_power_off(void) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci mdelay(100); 838c2ecf20Sopenharmony_ci local_irq_disable(); 848c2ecf20Sopenharmony_ci /* disable internal oscillator, float CS lines */ 858c2ecf20Sopenharmony_ci PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); 868c2ecf20Sopenharmony_ci /* enable wake-up on GPIO0 (Assabet...) */ 878c2ecf20Sopenharmony_ci PWER = GFER = GRER = 1; 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * set scratchpad to zero, just in case it is used as a 908c2ecf20Sopenharmony_ci * restart address by the bootloader. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci PSPR = 0; 938c2ecf20Sopenharmony_ci /* enter sleep mode */ 948c2ecf20Sopenharmony_ci PMCR = PMCR_SF; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_civoid sa11x0_restart(enum reboot_mode mode, const char *cmd) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci clear_reset_status(RESET_STATUS_ALL); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (mode == REBOOT_SOFT) { 1028c2ecf20Sopenharmony_ci /* Jump into ROM at address 0 */ 1038c2ecf20Sopenharmony_ci soft_restart(0); 1048c2ecf20Sopenharmony_ci } else { 1058c2ecf20Sopenharmony_ci /* Use on-chip reset capability */ 1068c2ecf20Sopenharmony_ci RSRR = RSRR_SWR; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic void sa11x0_register_device(struct platform_device *dev, void *data) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci int err; 1138c2ecf20Sopenharmony_ci dev->dev.platform_data = data; 1148c2ecf20Sopenharmony_ci err = platform_device_register(dev); 1158c2ecf20Sopenharmony_ci if (err) 1168c2ecf20Sopenharmony_ci printk(KERN_ERR "Unable to register device %s: %d\n", 1178c2ecf20Sopenharmony_ci dev->name, err); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic struct resource sa11x0udc_resources[] = { 1228c2ecf20Sopenharmony_ci [0] = DEFINE_RES_MEM(__PREG(Ser0UDCCR), SZ_64K), 1238c2ecf20Sopenharmony_ci [1] = DEFINE_RES_IRQ(IRQ_Ser0UDC), 1248c2ecf20Sopenharmony_ci}; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic u64 sa11x0udc_dma_mask = 0xffffffffUL; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic struct platform_device sa11x0udc_device = { 1298c2ecf20Sopenharmony_ci .name = "sa11x0-udc", 1308c2ecf20Sopenharmony_ci .id = -1, 1318c2ecf20Sopenharmony_ci .dev = { 1328c2ecf20Sopenharmony_ci .dma_mask = &sa11x0udc_dma_mask, 1338c2ecf20Sopenharmony_ci .coherent_dma_mask = 0xffffffff, 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0udc_resources), 1368c2ecf20Sopenharmony_ci .resource = sa11x0udc_resources, 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic struct resource sa11x0uart1_resources[] = { 1408c2ecf20Sopenharmony_ci [0] = DEFINE_RES_MEM(__PREG(Ser1UTCR0), SZ_64K), 1418c2ecf20Sopenharmony_ci [1] = DEFINE_RES_IRQ(IRQ_Ser1UART), 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic struct platform_device sa11x0uart1_device = { 1458c2ecf20Sopenharmony_ci .name = "sa11x0-uart", 1468c2ecf20Sopenharmony_ci .id = 1, 1478c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0uart1_resources), 1488c2ecf20Sopenharmony_ci .resource = sa11x0uart1_resources, 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic struct resource sa11x0uart3_resources[] = { 1528c2ecf20Sopenharmony_ci [0] = DEFINE_RES_MEM(__PREG(Ser3UTCR0), SZ_64K), 1538c2ecf20Sopenharmony_ci [1] = DEFINE_RES_IRQ(IRQ_Ser3UART), 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic struct platform_device sa11x0uart3_device = { 1578c2ecf20Sopenharmony_ci .name = "sa11x0-uart", 1588c2ecf20Sopenharmony_ci .id = 3, 1598c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0uart3_resources), 1608c2ecf20Sopenharmony_ci .resource = sa11x0uart3_resources, 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic struct resource sa11x0mcp_resources[] = { 1648c2ecf20Sopenharmony_ci [0] = DEFINE_RES_MEM(__PREG(Ser4MCCR0), SZ_64K), 1658c2ecf20Sopenharmony_ci [1] = DEFINE_RES_MEM(__PREG(Ser4MCCR1), 4), 1668c2ecf20Sopenharmony_ci [2] = DEFINE_RES_IRQ(IRQ_Ser4MCP), 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic u64 sa11x0mcp_dma_mask = 0xffffffffUL; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic struct platform_device sa11x0mcp_device = { 1728c2ecf20Sopenharmony_ci .name = "sa11x0-mcp", 1738c2ecf20Sopenharmony_ci .id = -1, 1748c2ecf20Sopenharmony_ci .dev = { 1758c2ecf20Sopenharmony_ci .dma_mask = &sa11x0mcp_dma_mask, 1768c2ecf20Sopenharmony_ci .coherent_dma_mask = 0xffffffff, 1778c2ecf20Sopenharmony_ci }, 1788c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0mcp_resources), 1798c2ecf20Sopenharmony_ci .resource = sa11x0mcp_resources, 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_civoid __init sa11x0_ppc_configure_mcp(void) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci /* Setup the PPC unit for the MCP */ 1858c2ecf20Sopenharmony_ci PPDR &= ~PPC_RXD4; 1868c2ecf20Sopenharmony_ci PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; 1878c2ecf20Sopenharmony_ci PSDR |= PPC_RXD4; 1888c2ecf20Sopenharmony_ci PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); 1898c2ecf20Sopenharmony_ci PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_civoid sa11x0_register_mcp(struct mcp_plat_data *data) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci sa11x0_register_device(&sa11x0mcp_device, data); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic struct resource sa11x0ssp_resources[] = { 1988c2ecf20Sopenharmony_ci [0] = DEFINE_RES_MEM(0x80070000, SZ_64K), 1998c2ecf20Sopenharmony_ci [1] = DEFINE_RES_IRQ(IRQ_Ser4SSP), 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic u64 sa11x0ssp_dma_mask = 0xffffffffUL; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic struct platform_device sa11x0ssp_device = { 2058c2ecf20Sopenharmony_ci .name = "sa11x0-ssp", 2068c2ecf20Sopenharmony_ci .id = -1, 2078c2ecf20Sopenharmony_ci .dev = { 2088c2ecf20Sopenharmony_ci .dma_mask = &sa11x0ssp_dma_mask, 2098c2ecf20Sopenharmony_ci .coherent_dma_mask = 0xffffffff, 2108c2ecf20Sopenharmony_ci }, 2118c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0ssp_resources), 2128c2ecf20Sopenharmony_ci .resource = sa11x0ssp_resources, 2138c2ecf20Sopenharmony_ci}; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic struct resource sa11x0fb_resources[] = { 2168c2ecf20Sopenharmony_ci [0] = DEFINE_RES_MEM(0xb0100000, SZ_64K), 2178c2ecf20Sopenharmony_ci [1] = DEFINE_RES_IRQ(IRQ_LCD), 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic struct platform_device sa11x0fb_device = { 2218c2ecf20Sopenharmony_ci .name = "sa11x0-fb", 2228c2ecf20Sopenharmony_ci .id = -1, 2238c2ecf20Sopenharmony_ci .dev = { 2248c2ecf20Sopenharmony_ci .coherent_dma_mask = 0xffffffff, 2258c2ecf20Sopenharmony_ci }, 2268c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0fb_resources), 2278c2ecf20Sopenharmony_ci .resource = sa11x0fb_resources, 2288c2ecf20Sopenharmony_ci}; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_civoid sa11x0_register_lcd(struct sa1100fb_mach_info *inf) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci sa11x0_register_device(&sa11x0fb_device, inf); 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_civoid sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *table) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci if (table) 2388c2ecf20Sopenharmony_ci gpiod_add_lookup_table(table); 2398c2ecf20Sopenharmony_ci platform_device_register_simple("sa11x0-pcmcia", socket, NULL, 0); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic struct platform_device sa11x0mtd_device = { 2438c2ecf20Sopenharmony_ci .name = "sa1100-mtd", 2448c2ecf20Sopenharmony_ci .id = -1, 2458c2ecf20Sopenharmony_ci}; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_civoid sa11x0_register_mtd(struct flash_platform_data *flash, 2488c2ecf20Sopenharmony_ci struct resource *res, int nr) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci flash->name = "sa1100"; 2518c2ecf20Sopenharmony_ci sa11x0mtd_device.resource = res; 2528c2ecf20Sopenharmony_ci sa11x0mtd_device.num_resources = nr; 2538c2ecf20Sopenharmony_ci sa11x0_register_device(&sa11x0mtd_device, flash); 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic struct resource sa11x0ir_resources[] = { 2578c2ecf20Sopenharmony_ci DEFINE_RES_MEM(__PREG(Ser2UTCR0), 0x24), 2588c2ecf20Sopenharmony_ci DEFINE_RES_MEM(__PREG(Ser2HSCR0), 0x1c), 2598c2ecf20Sopenharmony_ci DEFINE_RES_MEM(__PREG(Ser2HSCR2), 0x04), 2608c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_Ser2ICP), 2618c2ecf20Sopenharmony_ci}; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic struct platform_device sa11x0ir_device = { 2648c2ecf20Sopenharmony_ci .name = "sa11x0-ir", 2658c2ecf20Sopenharmony_ci .id = -1, 2668c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0ir_resources), 2678c2ecf20Sopenharmony_ci .resource = sa11x0ir_resources, 2688c2ecf20Sopenharmony_ci}; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_civoid sa11x0_register_irda(struct irda_platform_data *irda) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci sa11x0_register_device(&sa11x0ir_device, irda); 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic struct resource sa1100_rtc_resources[] = { 2768c2ecf20Sopenharmony_ci DEFINE_RES_MEM(0x90010000, 0x40), 2778c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"), 2788c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"), 2798c2ecf20Sopenharmony_ci}; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic struct platform_device sa11x0rtc_device = { 2828c2ecf20Sopenharmony_ci .name = "sa1100-rtc", 2838c2ecf20Sopenharmony_ci .id = -1, 2848c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa1100_rtc_resources), 2858c2ecf20Sopenharmony_ci .resource = sa1100_rtc_resources, 2868c2ecf20Sopenharmony_ci}; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic struct resource sa11x0dma_resources[] = { 2898c2ecf20Sopenharmony_ci DEFINE_RES_MEM(DMA_PHYS, DMA_SIZE), 2908c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_DMA0), 2918c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_DMA1), 2928c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_DMA2), 2938c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_DMA3), 2948c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_DMA4), 2958c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(IRQ_DMA5), 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic u64 sa11x0dma_dma_mask = DMA_BIT_MASK(32); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic struct platform_device sa11x0dma_device = { 3018c2ecf20Sopenharmony_ci .name = "sa11x0-dma", 3028c2ecf20Sopenharmony_ci .id = -1, 3038c2ecf20Sopenharmony_ci .dev = { 3048c2ecf20Sopenharmony_ci .dma_mask = &sa11x0dma_dma_mask, 3058c2ecf20Sopenharmony_ci .coherent_dma_mask = 0xffffffff, 3068c2ecf20Sopenharmony_ci }, 3078c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sa11x0dma_resources), 3088c2ecf20Sopenharmony_ci .resource = sa11x0dma_resources, 3098c2ecf20Sopenharmony_ci}; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic struct platform_device *sa11x0_devices[] __initdata = { 3128c2ecf20Sopenharmony_ci &sa11x0udc_device, 3138c2ecf20Sopenharmony_ci &sa11x0uart1_device, 3148c2ecf20Sopenharmony_ci &sa11x0uart3_device, 3158c2ecf20Sopenharmony_ci &sa11x0ssp_device, 3168c2ecf20Sopenharmony_ci &sa11x0rtc_device, 3178c2ecf20Sopenharmony_ci &sa11x0dma_device, 3188c2ecf20Sopenharmony_ci}; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int __init sa1100_init(void) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci pm_power_off = sa1100_power_off; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci regulator_has_full_constraints(); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices)); 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ciarch_initcall(sa1100_init); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_civoid __init sa11x0_init_late(void) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci sa11x0_pm_init(); 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ciint __init sa11x0_register_fixed_regulator(int n, 3378c2ecf20Sopenharmony_ci struct fixed_voltage_config *cfg, 3388c2ecf20Sopenharmony_ci struct regulator_consumer_supply *supplies, unsigned num_supplies, 3398c2ecf20Sopenharmony_ci bool uses_gpio) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci struct regulator_init_data *id; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci cfg->init_data = id = kzalloc(sizeof(*cfg->init_data), GFP_KERNEL); 3448c2ecf20Sopenharmony_ci if (!cfg->init_data) 3458c2ecf20Sopenharmony_ci return -ENOMEM; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (!uses_gpio) 3488c2ecf20Sopenharmony_ci id->constraints.always_on = 1; 3498c2ecf20Sopenharmony_ci id->constraints.name = cfg->supply_name; 3508c2ecf20Sopenharmony_ci id->constraints.min_uV = cfg->microvolts; 3518c2ecf20Sopenharmony_ci id->constraints.max_uV = cfg->microvolts; 3528c2ecf20Sopenharmony_ci id->constraints.valid_modes_mask = REGULATOR_MODE_NORMAL; 3538c2ecf20Sopenharmony_ci id->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; 3548c2ecf20Sopenharmony_ci id->consumer_supplies = supplies; 3558c2ecf20Sopenharmony_ci id->num_consumer_supplies = num_supplies; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci platform_device_register_resndata(NULL, "reg-fixed-voltage", n, 3588c2ecf20Sopenharmony_ci NULL, 0, cfg, sizeof(*cfg)); 3598c2ecf20Sopenharmony_ci return 0; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci/* 3638c2ecf20Sopenharmony_ci * Common I/O mapping: 3648c2ecf20Sopenharmony_ci * 3658c2ecf20Sopenharmony_ci * Typically, static virtual address mappings are as follow: 3668c2ecf20Sopenharmony_ci * 3678c2ecf20Sopenharmony_ci * 0xf0000000-0xf3ffffff: miscellaneous stuff (CPLDs, etc.) 3688c2ecf20Sopenharmony_ci * 0xf4000000-0xf4ffffff: SA-1111 3698c2ecf20Sopenharmony_ci * 0xf5000000-0xf5ffffff: reserved (used by cache flushing area) 3708c2ecf20Sopenharmony_ci * 0xf6000000-0xfffeffff: reserved (internal SA1100 IO defined above) 3718c2ecf20Sopenharmony_ci * 0xffff0000-0xffff0fff: SA1100 exception vectors 3728c2ecf20Sopenharmony_ci * 0xffff2000-0xffff2fff: Minicache copy_user_page area 3738c2ecf20Sopenharmony_ci * 3748c2ecf20Sopenharmony_ci * Below 0xe8000000 is reserved for vm allocation. 3758c2ecf20Sopenharmony_ci * 3768c2ecf20Sopenharmony_ci * The machine specific code must provide the extra mapping beside the 3778c2ecf20Sopenharmony_ci * default mapping provided here. 3788c2ecf20Sopenharmony_ci */ 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic struct map_desc standard_io_desc[] __initdata = { 3818c2ecf20Sopenharmony_ci { /* PCM */ 3828c2ecf20Sopenharmony_ci .virtual = 0xf8000000, 3838c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0x80000000), 3848c2ecf20Sopenharmony_ci .length = 0x00100000, 3858c2ecf20Sopenharmony_ci .type = MT_DEVICE 3868c2ecf20Sopenharmony_ci }, { /* SCM */ 3878c2ecf20Sopenharmony_ci .virtual = 0xfa000000, 3888c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0x90000000), 3898c2ecf20Sopenharmony_ci .length = 0x00100000, 3908c2ecf20Sopenharmony_ci .type = MT_DEVICE 3918c2ecf20Sopenharmony_ci }, { /* MER */ 3928c2ecf20Sopenharmony_ci .virtual = 0xfc000000, 3938c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0xa0000000), 3948c2ecf20Sopenharmony_ci .length = 0x00100000, 3958c2ecf20Sopenharmony_ci .type = MT_DEVICE 3968c2ecf20Sopenharmony_ci }, { /* LCD + DMA */ 3978c2ecf20Sopenharmony_ci .virtual = 0xfe000000, 3988c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0xb0000000), 3998c2ecf20Sopenharmony_ci .length = 0x00200000, 4008c2ecf20Sopenharmony_ci .type = MT_DEVICE 4018c2ecf20Sopenharmony_ci }, 4028c2ecf20Sopenharmony_ci}; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_civoid __init sa1100_map_io(void) 4058c2ecf20Sopenharmony_ci{ 4068c2ecf20Sopenharmony_ci iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_civoid __init sa1100_timer_init(void) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000)); 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic struct resource irq_resource = 4158c2ecf20Sopenharmony_ci DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_civoid __init sa1100_init_irq(void) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci request_resource(&iomem_resource, &irq_resource); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci sa11x0_init_irq_nodt(IRQ_GPIO0_SC, irq_resource.start); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci sa1100_init_gpio(); 4248c2ecf20Sopenharmony_ci sa11xx_clk_init(); 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/* 4288c2ecf20Sopenharmony_ci * Disable the memory bus request/grant signals on the SA1110 to 4298c2ecf20Sopenharmony_ci * ensure that we don't receive spurious memory requests. We set 4308c2ecf20Sopenharmony_ci * the MBGNT signal false to ensure the SA1111 doesn't own the 4318c2ecf20Sopenharmony_ci * SDRAM bus. 4328c2ecf20Sopenharmony_ci */ 4338c2ecf20Sopenharmony_civoid sa1110_mb_disable(void) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci unsigned long flags; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci local_irq_save(flags); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci PGSR &= ~GPIO_MBGNT; 4408c2ecf20Sopenharmony_ci GPCR = GPIO_MBGNT; 4418c2ecf20Sopenharmony_ci GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci GAFR &= ~(GPIO_MBGNT | GPIO_MBREQ); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci local_irq_restore(flags); 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci/* 4498c2ecf20Sopenharmony_ci * If the system is going to use the SA-1111 DMA engines, set up 4508c2ecf20Sopenharmony_ci * the memory bus request/grant pins. 4518c2ecf20Sopenharmony_ci */ 4528c2ecf20Sopenharmony_civoid sa1110_mb_enable(void) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci unsigned long flags; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci local_irq_save(flags); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci PGSR &= ~GPIO_MBGNT; 4598c2ecf20Sopenharmony_ci GPCR = GPIO_MBGNT; 4608c2ecf20Sopenharmony_ci GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci GAFR |= (GPIO_MBGNT | GPIO_MBREQ); 4638c2ecf20Sopenharmony_ci TUCR |= TUCR_MR; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci local_irq_restore(flags); 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ciint sa11x0_gpio_set_wake(unsigned int gpio, unsigned int on) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci if (on) 4718c2ecf20Sopenharmony_ci PWER |= BIT(gpio); 4728c2ecf20Sopenharmony_ci else 4738c2ecf20Sopenharmony_ci PWER &= ~BIT(gpio); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci return 0; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ciint sa11x0_sc_set_wake(unsigned int irq, unsigned int on) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci if (BIT(irq) != IC_RTCAlrm) 4818c2ecf20Sopenharmony_ci return -EINVAL; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (on) 4848c2ecf20Sopenharmony_ci PWER |= PWER_RTC; 4858c2ecf20Sopenharmony_ci else 4868c2ecf20Sopenharmony_ci PWER &= ~PWER_RTC; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci return 0; 4898c2ecf20Sopenharmony_ci} 490