^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * arch/arm/mach-ixp4xx/common.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Generic code shared across all IXP4XX platforms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Maintainer: Deepak Saxena <dsaxena@plexity.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2002 (c) Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2003-2004 (c) MontaVista, Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/sched_clock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/irqchip/irq-ixp4xx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/platform_data/timer-ixp4xx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/dma-map-ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <mach/udc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <mach/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/exception.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/system_misc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/mach/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <asm/mach/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <asm/mach/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include "irqs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define IXP4XX_TIMER_FREQ 66666000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * IXP4xx chipset I/O mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static struct map_desc ixp4xx_io_desc[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACs, USB .... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .virtual = (unsigned long)IXP4XX_PERIPHERAL_BASE_VIRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .pfn = __phys_to_pfn(IXP4XX_PERIPHERAL_BASE_PHYS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .length = IXP4XX_PERIPHERAL_REGION_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .type = MT_DEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }, { /* Expansion Bus Config Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .virtual = (unsigned long)IXP4XX_EXP_CFG_BASE_VIRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .pfn = __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .length = IXP4XX_EXP_CFG_REGION_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .type = MT_DEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }, { /* PCI Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .virtual = (unsigned long)IXP4XX_PCI_CFG_BASE_VIRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .pfn = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .length = IXP4XX_PCI_CFG_REGION_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .type = MT_DEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void __init ixp4xx_map_io(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void __init ixp4xx_init_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * ixp4xx does not implement the XScale PWRMODE register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * so it must not call cpu_do_idle().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) cpu_idle_poll_ctrl(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) (cpu_is_ixp46x() || cpu_is_ixp43x()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) void __init ixp4xx_timer_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) IRQ_IXP4XX_TIMER1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) IXP4XX_TIMER_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) memcpy(&ixp4xx_udc_info, info, sizeof *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static struct resource ixp4xx_udc_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .start = 0xc800b000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .end = 0xc800bfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .start = IRQ_IXP4XX_USB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .end = IRQ_IXP4XX_USB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .flags = IORESOURCE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static struct resource ixp4xx_gpio_resource[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .start = IXP4XX_GPIO_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .end = IXP4XX_GPIO_BASE_PHYS + 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static struct platform_device ixp4xx_gpio_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .name = "ixp4xx-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .coherent_dma_mask = DMA_BIT_MASK(32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .resource = ixp4xx_gpio_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .num_resources = ARRAY_SIZE(ixp4xx_gpio_resource),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * USB device controller. The IXP4xx uses the same controller as PXA25X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * so we just use the same device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct platform_device ixp4xx_udc_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .name = "pxa25x-udc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .num_resources = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .resource = ixp4xx_udc_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .platform_data = &ixp4xx_udc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static struct resource ixp4xx_npe_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .start = IXP4XX_NPEA_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .end = IXP4XX_NPEA_BASE_PHYS + 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .start = IXP4XX_NPEB_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .end = IXP4XX_NPEB_BASE_PHYS + 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .start = IXP4XX_NPEC_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .end = IXP4XX_NPEC_BASE_PHYS + 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct platform_device ixp4xx_npe_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .name = "ixp4xx-npe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .num_resources = ARRAY_SIZE(ixp4xx_npe_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .resource = ixp4xx_npe_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static struct resource ixp4xx_qmgr_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .start = IXP4XX_QMGR_BASE_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .end = IXP4XX_QMGR_BASE_PHYS + 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .start = IRQ_IXP4XX_QM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .end = IRQ_IXP4XX_QM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .flags = IORESOURCE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .start = IRQ_IXP4XX_QM2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .end = IRQ_IXP4XX_QM2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .flags = IORESOURCE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static struct platform_device ixp4xx_qmgr_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .name = "ixp4xx-qmgr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .num_resources = ARRAY_SIZE(ixp4xx_qmgr_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .resource = ixp4xx_qmgr_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static struct platform_device *ixp4xx_devices[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) &ixp4xx_npe_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) &ixp4xx_qmgr_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) &ixp4xx_gpio_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) &ixp4xx_udc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct resource ixp46x_i2c_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .start = 0xc8011000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .end = 0xc801101c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .start = IRQ_IXP4XX_I2C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .end = IRQ_IXP4XX_I2C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .flags = IORESOURCE_IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * I2C controller. The IXP46x uses the same block as the IOP3xx, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * we just use the same device name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static struct platform_device ixp46x_i2c_controller = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .name = "IOP3xx-I2C",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .num_resources = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .resource = ixp46x_i2c_resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static struct platform_device *ixp46x_devices[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) &ixp46x_i2c_controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) unsigned long ixp4xx_exp_bus_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) EXPORT_SYMBOL(ixp4xx_exp_bus_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) void __init ixp4xx_sys_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ixp4xx_exp_bus_size = SZ_16M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (cpu_is_ixp46x()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) platform_add_devices(ixp46x_devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ARRAY_SIZE(ixp46x_devices));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) for (region = 0; region < 7; region++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if((*(IXP4XX_EXP_REG(0x4 * region)) & 0x200)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ixp4xx_exp_bus_size = SZ_32M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) printk("IXP4xx: Using %luMiB expansion bus window size\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ixp4xx_exp_bus_size >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) EXPORT_SYMBOL(ixp4xx_timer_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (mode == REBOOT_SOFT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* Jump into ROM at address 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) soft_restart(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Use on-chip reset capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* set the "key" register to enable access to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * "timer" and "enable" registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *IXP4XX_OSWK = IXP4XX_WDT_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* write 0 to the timer register for an immediate reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *IXP4XX_OSWT = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) *IXP4XX_OSWE = IXP4XX_WDT_RESET_ENABLE | IXP4XX_WDT_COUNT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return (dma_addr + size) > SZ_64M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int ixp4xx_platform_notify_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (dev_is_pci(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dmabounce_unregister_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Setup DMA mask to 64MB on PCI devices and 4 GB on all other things.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int ixp4xx_platform_notify(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dev->dma_mask = &dev->coherent_dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (dev_is_pci(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev->coherent_dma_mask = DMA_BIT_MASK(32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int dma_set_coherent_mask(struct device *dev, u64 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (dev_is_pci(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) mask &= DMA_BIT_MASK(28); /* 64 MB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) dev->coherent_dma_mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return -EIO; /* device wanted sub-64MB mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) EXPORT_SYMBOL(dma_set_coherent_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) #ifdef CONFIG_IXP4XX_INDIRECT_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * In the case of using indirect PCI, we simply return the actual PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * address and our read/write implementation use that to drive the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * access registers. If something outside of PCI is ioremap'd, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * fallback to the default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) unsigned int mtype, void *caller)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (!is_pci_memory(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return __arm_ioremap_caller(addr, size, mtype, caller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return (void __iomem *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static void ixp4xx_iounmap(volatile void __iomem *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (!is_pci_memory((__force u32)addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) __iounmap(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) void __init ixp4xx_init_early(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) platform_notify = ixp4xx_platform_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) platform_notify_remove = ixp4xx_platform_notify_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) #ifdef CONFIG_IXP4XX_INDIRECT_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) arch_ioremap_caller = ixp4xx_ioremap_caller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) arch_iounmap = ixp4xx_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }