18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * arch/arm/mach-ixp4xx/common.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Generic code shared across all IXP4XX platforms 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Maintainer: Deepak Saxena <dsaxena@plexity.net> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright 2002 (c) Intel Corporation 98c2ecf20Sopenharmony_ci * Copyright 2003-2004 (c) MontaVista, Software, Inc. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 128c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any 138c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/mm.h> 188c2ecf20Sopenharmony_ci#include <linux/init.h> 198c2ecf20Sopenharmony_ci#include <linux/serial.h> 208c2ecf20Sopenharmony_ci#include <linux/tty.h> 218c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 228c2ecf20Sopenharmony_ci#include <linux/serial_core.h> 238c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 248c2ecf20Sopenharmony_ci#include <linux/bitops.h> 258c2ecf20Sopenharmony_ci#include <linux/io.h> 268c2ecf20Sopenharmony_ci#include <linux/export.h> 278c2ecf20Sopenharmony_ci#include <linux/cpu.h> 288c2ecf20Sopenharmony_ci#include <linux/pci.h> 298c2ecf20Sopenharmony_ci#include <linux/sched_clock.h> 308c2ecf20Sopenharmony_ci#include <linux/irqchip/irq-ixp4xx.h> 318c2ecf20Sopenharmony_ci#include <linux/platform_data/timer-ixp4xx.h> 328c2ecf20Sopenharmony_ci#include <linux/dma-map-ops.h> 338c2ecf20Sopenharmony_ci#include <mach/udc.h> 348c2ecf20Sopenharmony_ci#include <mach/hardware.h> 358c2ecf20Sopenharmony_ci#include <mach/io.h> 368c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 378c2ecf20Sopenharmony_ci#include <asm/page.h> 388c2ecf20Sopenharmony_ci#include <asm/exception.h> 398c2ecf20Sopenharmony_ci#include <asm/irq.h> 408c2ecf20Sopenharmony_ci#include <asm/system_misc.h> 418c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 428c2ecf20Sopenharmony_ci#include <asm/mach/irq.h> 438c2ecf20Sopenharmony_ci#include <asm/mach/time.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include "irqs.h" 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define IXP4XX_TIMER_FREQ 66666000 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/************************************************************************* 508c2ecf20Sopenharmony_ci * IXP4xx chipset I/O mapping 518c2ecf20Sopenharmony_ci *************************************************************************/ 528c2ecf20Sopenharmony_cistatic struct map_desc ixp4xx_io_desc[] __initdata = { 538c2ecf20Sopenharmony_ci { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACs, USB .... */ 548c2ecf20Sopenharmony_ci .virtual = (unsigned long)IXP4XX_PERIPHERAL_BASE_VIRT, 558c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(IXP4XX_PERIPHERAL_BASE_PHYS), 568c2ecf20Sopenharmony_ci .length = IXP4XX_PERIPHERAL_REGION_SIZE, 578c2ecf20Sopenharmony_ci .type = MT_DEVICE 588c2ecf20Sopenharmony_ci }, { /* Expansion Bus Config Registers */ 598c2ecf20Sopenharmony_ci .virtual = (unsigned long)IXP4XX_EXP_CFG_BASE_VIRT, 608c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS), 618c2ecf20Sopenharmony_ci .length = IXP4XX_EXP_CFG_REGION_SIZE, 628c2ecf20Sopenharmony_ci .type = MT_DEVICE 638c2ecf20Sopenharmony_ci }, { /* PCI Registers */ 648c2ecf20Sopenharmony_ci .virtual = (unsigned long)IXP4XX_PCI_CFG_BASE_VIRT, 658c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS), 668c2ecf20Sopenharmony_ci .length = IXP4XX_PCI_CFG_REGION_SIZE, 678c2ecf20Sopenharmony_ci .type = MT_DEVICE 688c2ecf20Sopenharmony_ci }, 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_civoid __init ixp4xx_map_io(void) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc)); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_civoid __init ixp4xx_init_irq(void) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci /* 798c2ecf20Sopenharmony_ci * ixp4xx does not implement the XScale PWRMODE register 808c2ecf20Sopenharmony_ci * so it must not call cpu_do_idle(). 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci cpu_idle_poll_ctrl(true); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS, 858c2ecf20Sopenharmony_ci (cpu_is_ixp46x() || cpu_is_ixp43x())); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_civoid __init ixp4xx_timer_init(void) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS, 918c2ecf20Sopenharmony_ci IRQ_IXP4XX_TIMER1, 928c2ecf20Sopenharmony_ci IXP4XX_TIMER_FREQ); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic struct pxa2xx_udc_mach_info ixp4xx_udc_info; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_civoid __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci memcpy(&ixp4xx_udc_info, info, sizeof *info); 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic struct resource ixp4xx_udc_resources[] = { 1038c2ecf20Sopenharmony_ci [0] = { 1048c2ecf20Sopenharmony_ci .start = 0xc800b000, 1058c2ecf20Sopenharmony_ci .end = 0xc800bfff, 1068c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1078c2ecf20Sopenharmony_ci }, 1088c2ecf20Sopenharmony_ci [1] = { 1098c2ecf20Sopenharmony_ci .start = IRQ_IXP4XX_USB, 1108c2ecf20Sopenharmony_ci .end = IRQ_IXP4XX_USB, 1118c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ, 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic struct resource ixp4xx_gpio_resource[] = { 1168c2ecf20Sopenharmony_ci { 1178c2ecf20Sopenharmony_ci .start = IXP4XX_GPIO_BASE_PHYS, 1188c2ecf20Sopenharmony_ci .end = IXP4XX_GPIO_BASE_PHYS + 0xfff, 1198c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1208c2ecf20Sopenharmony_ci }, 1218c2ecf20Sopenharmony_ci}; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic struct platform_device ixp4xx_gpio_device = { 1248c2ecf20Sopenharmony_ci .name = "ixp4xx-gpio", 1258c2ecf20Sopenharmony_ci .id = -1, 1268c2ecf20Sopenharmony_ci .dev = { 1278c2ecf20Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 1288c2ecf20Sopenharmony_ci }, 1298c2ecf20Sopenharmony_ci .resource = ixp4xx_gpio_resource, 1308c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ixp4xx_gpio_resource), 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* 1348c2ecf20Sopenharmony_ci * USB device controller. The IXP4xx uses the same controller as PXA25X, 1358c2ecf20Sopenharmony_ci * so we just use the same device. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_cistatic struct platform_device ixp4xx_udc_device = { 1388c2ecf20Sopenharmony_ci .name = "pxa25x-udc", 1398c2ecf20Sopenharmony_ci .id = -1, 1408c2ecf20Sopenharmony_ci .num_resources = 2, 1418c2ecf20Sopenharmony_ci .resource = ixp4xx_udc_resources, 1428c2ecf20Sopenharmony_ci .dev = { 1438c2ecf20Sopenharmony_ci .platform_data = &ixp4xx_udc_info, 1448c2ecf20Sopenharmony_ci }, 1458c2ecf20Sopenharmony_ci}; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic struct resource ixp4xx_npe_resources[] = { 1488c2ecf20Sopenharmony_ci { 1498c2ecf20Sopenharmony_ci .start = IXP4XX_NPEA_BASE_PHYS, 1508c2ecf20Sopenharmony_ci .end = IXP4XX_NPEA_BASE_PHYS + 0xfff, 1518c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1528c2ecf20Sopenharmony_ci }, 1538c2ecf20Sopenharmony_ci { 1548c2ecf20Sopenharmony_ci .start = IXP4XX_NPEB_BASE_PHYS, 1558c2ecf20Sopenharmony_ci .end = IXP4XX_NPEB_BASE_PHYS + 0xfff, 1568c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1578c2ecf20Sopenharmony_ci }, 1588c2ecf20Sopenharmony_ci { 1598c2ecf20Sopenharmony_ci .start = IXP4XX_NPEC_BASE_PHYS, 1608c2ecf20Sopenharmony_ci .end = IXP4XX_NPEC_BASE_PHYS + 0xfff, 1618c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1628c2ecf20Sopenharmony_ci }, 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic struct platform_device ixp4xx_npe_device = { 1678c2ecf20Sopenharmony_ci .name = "ixp4xx-npe", 1688c2ecf20Sopenharmony_ci .id = -1, 1698c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ixp4xx_npe_resources), 1708c2ecf20Sopenharmony_ci .resource = ixp4xx_npe_resources, 1718c2ecf20Sopenharmony_ci}; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic struct resource ixp4xx_qmgr_resources[] = { 1748c2ecf20Sopenharmony_ci { 1758c2ecf20Sopenharmony_ci .start = IXP4XX_QMGR_BASE_PHYS, 1768c2ecf20Sopenharmony_ci .end = IXP4XX_QMGR_BASE_PHYS + 0x3fff, 1778c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1788c2ecf20Sopenharmony_ci }, 1798c2ecf20Sopenharmony_ci { 1808c2ecf20Sopenharmony_ci .start = IRQ_IXP4XX_QM1, 1818c2ecf20Sopenharmony_ci .end = IRQ_IXP4XX_QM1, 1828c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ, 1838c2ecf20Sopenharmony_ci }, 1848c2ecf20Sopenharmony_ci { 1858c2ecf20Sopenharmony_ci .start = IRQ_IXP4XX_QM2, 1868c2ecf20Sopenharmony_ci .end = IRQ_IXP4XX_QM2, 1878c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ, 1888c2ecf20Sopenharmony_ci }, 1898c2ecf20Sopenharmony_ci}; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic struct platform_device ixp4xx_qmgr_device = { 1928c2ecf20Sopenharmony_ci .name = "ixp4xx-qmgr", 1938c2ecf20Sopenharmony_ci .id = -1, 1948c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ixp4xx_qmgr_resources), 1958c2ecf20Sopenharmony_ci .resource = ixp4xx_qmgr_resources, 1968c2ecf20Sopenharmony_ci}; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic struct platform_device *ixp4xx_devices[] __initdata = { 1998c2ecf20Sopenharmony_ci &ixp4xx_npe_device, 2008c2ecf20Sopenharmony_ci &ixp4xx_qmgr_device, 2018c2ecf20Sopenharmony_ci &ixp4xx_gpio_device, 2028c2ecf20Sopenharmony_ci &ixp4xx_udc_device, 2038c2ecf20Sopenharmony_ci}; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic struct resource ixp46x_i2c_resources[] = { 2068c2ecf20Sopenharmony_ci [0] = { 2078c2ecf20Sopenharmony_ci .start = 0xc8011000, 2088c2ecf20Sopenharmony_ci .end = 0xc801101c, 2098c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 2108c2ecf20Sopenharmony_ci }, 2118c2ecf20Sopenharmony_ci [1] = { 2128c2ecf20Sopenharmony_ci .start = IRQ_IXP4XX_I2C, 2138c2ecf20Sopenharmony_ci .end = IRQ_IXP4XX_I2C, 2148c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci/* 2198c2ecf20Sopenharmony_ci * I2C controller. The IXP46x uses the same block as the IOP3xx, so 2208c2ecf20Sopenharmony_ci * we just use the same device name. 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_cistatic struct platform_device ixp46x_i2c_controller = { 2238c2ecf20Sopenharmony_ci .name = "IOP3xx-I2C", 2248c2ecf20Sopenharmony_ci .id = 0, 2258c2ecf20Sopenharmony_ci .num_resources = 2, 2268c2ecf20Sopenharmony_ci .resource = ixp46x_i2c_resources 2278c2ecf20Sopenharmony_ci}; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic struct platform_device *ixp46x_devices[] __initdata = { 2308c2ecf20Sopenharmony_ci &ixp46x_i2c_controller 2318c2ecf20Sopenharmony_ci}; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ciunsigned long ixp4xx_exp_bus_size; 2348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ixp4xx_exp_bus_size); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_civoid __init ixp4xx_sys_init(void) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci ixp4xx_exp_bus_size = SZ_16M; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (cpu_is_ixp46x()) { 2438c2ecf20Sopenharmony_ci int region; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci platform_add_devices(ixp46x_devices, 2468c2ecf20Sopenharmony_ci ARRAY_SIZE(ixp46x_devices)); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci for (region = 0; region < 7; region++) { 2498c2ecf20Sopenharmony_ci if((*(IXP4XX_EXP_REG(0x4 * region)) & 0x200)) { 2508c2ecf20Sopenharmony_ci ixp4xx_exp_bus_size = SZ_32M; 2518c2ecf20Sopenharmony_ci break; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci printk("IXP4xx: Using %luMiB expansion bus window size\n", 2578c2ecf20Sopenharmony_ci ixp4xx_exp_bus_size >> 20); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ciunsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; 2618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ixp4xx_timer_freq); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_civoid ixp4xx_restart(enum reboot_mode mode, const char *cmd) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci if (mode == REBOOT_SOFT) { 2668c2ecf20Sopenharmony_ci /* Jump into ROM at address 0 */ 2678c2ecf20Sopenharmony_ci soft_restart(0); 2688c2ecf20Sopenharmony_ci } else { 2698c2ecf20Sopenharmony_ci /* Use on-chip reset capability */ 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* set the "key" register to enable access to 2728c2ecf20Sopenharmony_ci * "timer" and "enable" registers 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_ci *IXP4XX_OSWK = IXP4XX_WDT_KEY; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* write 0 to the timer register for an immediate reset */ 2778c2ecf20Sopenharmony_ci *IXP4XX_OSWT = 0; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci *IXP4XX_OSWE = IXP4XX_WDT_RESET_ENABLE | IXP4XX_WDT_COUNT_ENABLE; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 2848c2ecf20Sopenharmony_cistatic int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci return (dma_addr + size) > SZ_64M; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic int ixp4xx_platform_notify_remove(struct device *dev) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci if (dev_is_pci(dev)) 2928c2ecf20Sopenharmony_ci dmabounce_unregister_dev(dev); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci#endif 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/* 2998c2ecf20Sopenharmony_ci * Setup DMA mask to 64MB on PCI devices and 4 GB on all other things. 3008c2ecf20Sopenharmony_ci */ 3018c2ecf20Sopenharmony_cistatic int ixp4xx_platform_notify(struct device *dev) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci dev->dma_mask = &dev->coherent_dma_mask; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 3068c2ecf20Sopenharmony_ci if (dev_is_pci(dev)) { 3078c2ecf20Sopenharmony_ci dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */ 3088c2ecf20Sopenharmony_ci dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce); 3098c2ecf20Sopenharmony_ci return 0; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci#endif 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci dev->coherent_dma_mask = DMA_BIT_MASK(32); 3148c2ecf20Sopenharmony_ci return 0; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ciint dma_set_coherent_mask(struct device *dev, u64 mask) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci if (dev_is_pci(dev)) 3208c2ecf20Sopenharmony_ci mask &= DMA_BIT_MASK(28); /* 64 MB */ 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) { 3238c2ecf20Sopenharmony_ci dev->coherent_dma_mask = mask; 3248c2ecf20Sopenharmony_ci return 0; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci return -EIO; /* device wanted sub-64MB mask */ 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dma_set_coherent_mask); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci#ifdef CONFIG_IXP4XX_INDIRECT_PCI 3328c2ecf20Sopenharmony_ci/* 3338c2ecf20Sopenharmony_ci * In the case of using indirect PCI, we simply return the actual PCI 3348c2ecf20Sopenharmony_ci * address and our read/write implementation use that to drive the 3358c2ecf20Sopenharmony_ci * access registers. If something outside of PCI is ioremap'd, we 3368c2ecf20Sopenharmony_ci * fallback to the default. 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistatic void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size, 3408c2ecf20Sopenharmony_ci unsigned int mtype, void *caller) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci if (!is_pci_memory(addr)) 3438c2ecf20Sopenharmony_ci return __arm_ioremap_caller(addr, size, mtype, caller); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return (void __iomem *)addr; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic void ixp4xx_iounmap(volatile void __iomem *addr) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci if (!is_pci_memory((__force u32)addr)) 3518c2ecf20Sopenharmony_ci __iounmap(addr); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci#endif 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_civoid __init ixp4xx_init_early(void) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci platform_notify = ixp4xx_platform_notify; 3588c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 3598c2ecf20Sopenharmony_ci platform_notify_remove = ixp4xx_platform_notify_remove; 3608c2ecf20Sopenharmony_ci#endif 3618c2ecf20Sopenharmony_ci#ifdef CONFIG_IXP4XX_INDIRECT_PCI 3628c2ecf20Sopenharmony_ci arch_ioremap_caller = ixp4xx_ioremap_caller; 3638c2ecf20Sopenharmony_ci arch_iounmap = ixp4xx_iounmap; 3648c2ecf20Sopenharmony_ci#endif 3658c2ecf20Sopenharmony_ci} 366