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