1/* 2 * Freescale STMP37XX platform support 3 * 4 * Embedded Alley Solutions, Inc <source@embeddedalley.com> 5 * 6 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. 7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. 8 */ 9 10/* 11 * The code contained herein is licensed under the GNU General Public 12 * License. You may obtain a copy of the GNU General Public License 13 * Version 2 or later at the following locations: 14 * 15 * http://www.opensource.org/licenses/gpl-license.html 16 * http://www.gnu.org/copyleft/gpl.html 17 */ 18#include <linux/types.h> 19#include <linux/kernel.h> 20#include <linux/init.h> 21#include <linux/device.h> 22#include <linux/platform_device.h> 23#include <linux/irq.h> 24#include <linux/io.h> 25 26#include <asm/setup.h> 27#include <asm/mach-types.h> 28 29#include <asm/mach/arch.h> 30#include <asm/mach/irq.h> 31#include <asm/mach/map.h> 32#include <asm/mach/time.h> 33 34#include <mach/stmp3xxx.h> 35#include <mach/dma.h> 36 37#include <mach/platform.h> 38#include <mach/regs-icoll.h> 39#include <mach/regs-apbh.h> 40#include <mach/regs-apbx.h> 41#include "stmp37xx.h" 42 43/* 44 * IRQ handling 45 */ 46static void stmp37xx_ack_irq(unsigned int irq) 47{ 48 /* Disable IRQ */ 49 stmp3xxx_clearl(0x04 << ((irq % 4) * 8), 50 REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); 51 52 /* ACK current interrupt */ 53 __raw_writel(1, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK); 54 55 /* Barrier */ 56 (void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT); 57} 58 59static void stmp37xx_mask_irq(unsigned int irq) 60{ 61 /* IRQ disable */ 62 stmp3xxx_clearl(0x04 << ((irq % 4) * 8), 63 REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); 64} 65 66static void stmp37xx_unmask_irq(unsigned int irq) 67{ 68 /* IRQ enable */ 69 stmp3xxx_setl(0x04 << ((irq % 4) * 8), 70 REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); 71} 72 73static struct irq_chip stmp37xx_chip = { 74 .ack = stmp37xx_ack_irq, 75 .mask = stmp37xx_mask_irq, 76 .unmask = stmp37xx_unmask_irq, 77}; 78 79void __init stmp37xx_init_irq(void) 80{ 81 stmp3xxx_init_irq(&stmp37xx_chip); 82} 83 84/* 85 * DMA interrupt handling 86 */ 87void stmp3xxx_arch_dma_enable_interrupt(int channel) 88{ 89 switch (STMP3XXX_DMA_BUS(channel)) { 90 case STMP3XXX_BUS_APBH: 91 stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)), 92 REGS_APBH_BASE + HW_APBH_CTRL1); 93 break; 94 95 case STMP3XXX_BUS_APBX: 96 stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)), 97 REGS_APBX_BASE + HW_APBX_CTRL1); 98 break; 99 } 100} 101EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt); 102 103void stmp3xxx_arch_dma_clear_interrupt(int channel) 104{ 105 switch (STMP3XXX_DMA_BUS(channel)) { 106 case STMP3XXX_BUS_APBH: 107 stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), 108 REGS_APBH_BASE + HW_APBH_CTRL1); 109 break; 110 111 case STMP3XXX_BUS_APBX: 112 stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), 113 REGS_APBX_BASE + HW_APBX_CTRL1); 114 break; 115 } 116} 117EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt); 118 119int stmp3xxx_arch_dma_is_interrupt(int channel) 120{ 121 int r = 0; 122 123 switch (STMP3XXX_DMA_BUS(channel)) { 124 case STMP3XXX_BUS_APBH: 125 r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & 126 (1 << STMP3XXX_DMA_CHANNEL(channel)); 127 break; 128 129 case STMP3XXX_BUS_APBX: 130 r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & 131 (1 << STMP3XXX_DMA_CHANNEL(channel)); 132 break; 133 } 134 return r; 135} 136EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt); 137 138void stmp3xxx_arch_dma_reset_channel(int channel) 139{ 140 unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); 141 142 switch (STMP3XXX_DMA_BUS(channel)) { 143 case STMP3XXX_BUS_APBH: 144 /* Reset channel and wait for it to complete */ 145 stmp3xxx_setl(chbit << BP_APBH_CTRL0_RESET_CHANNEL, 146 REGS_APBH_BASE + HW_APBH_CTRL0); 147 while (__raw_readl(REGS_APBH_BASE + HW_APBH_CTRL0) & 148 (chbit << BP_APBH_CTRL0_RESET_CHANNEL)) 149 cpu_relax(); 150 break; 151 152 case STMP3XXX_BUS_APBX: 153 stmp3xxx_setl(chbit << BP_APBX_CTRL0_RESET_CHANNEL, 154 REGS_APBX_BASE + HW_APBX_CTRL0); 155 while (__raw_readl(REGS_APBX_BASE + HW_APBX_CTRL0) & 156 (chbit << BP_APBX_CTRL0_RESET_CHANNEL)) 157 cpu_relax(); 158 break; 159 } 160} 161EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel); 162 163void stmp3xxx_arch_dma_freeze(int channel) 164{ 165 unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); 166 167 switch (STMP3XXX_DMA_BUS(channel)) { 168 case STMP3XXX_BUS_APBH: 169 stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); 170 break; 171 case STMP3XXX_BUS_APBX: 172 stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); 173 break; 174 } 175} 176EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze); 177 178void stmp3xxx_arch_dma_unfreeze(int channel) 179{ 180 unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); 181 182 switch (STMP3XXX_DMA_BUS(channel)) { 183 case STMP3XXX_BUS_APBH: 184 stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); 185 break; 186 case STMP3XXX_BUS_APBX: 187 stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); 188 break; 189 } 190} 191EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze); 192 193/* 194 * The registers are all very closely mapped, so we might as well map them all 195 * with a single mapping 196 * 197 * Logical Physical 198 * f0000000 80000000 On-chip registers 199 * f1000000 00000000 32k on-chip SRAM 200 */ 201static struct map_desc stmp37xx_io_desc[] __initdata = { 202 { 203 .virtual = (u32)STMP3XXX_REGS_BASE, 204 .pfn = __phys_to_pfn(STMP3XXX_REGS_PHBASE), 205 .length = SZ_1M, 206 .type = MT_DEVICE 207 }, 208 { 209 .virtual = (u32)STMP3XXX_OCRAM_BASE, 210 .pfn = __phys_to_pfn(STMP3XXX_OCRAM_PHBASE), 211 .length = STMP3XXX_OCRAM_SIZE, 212 .type = MT_DEVICE, 213 }, 214}; 215 216void __init stmp37xx_map_io(void) 217{ 218 iotable_init(stmp37xx_io_desc, ARRAY_SIZE(stmp37xx_io_desc)); 219} 220