1/* 2 * Freescale STMP378X 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/kernel.h> 19#include <linux/init.h> 20#include <linux/platform_device.h> 21#include <linux/irq.h> 22#include <linux/dma-mapping.h> 23 24#include <asm/dma.h> 25#include <asm/setup.h> 26#include <asm/mach-types.h> 27 28#include <asm/mach/arch.h> 29#include <asm/mach/irq.h> 30#include <asm/mach/map.h> 31#include <asm/mach/time.h> 32 33#include <mach/pins.h> 34#include <mach/pinmux.h> 35#include <mach/dma.h> 36#include <mach/hardware.h> 37#include <mach/system.h> 38#include <mach/platform.h> 39#include <mach/stmp3xxx.h> 40#include <mach/regs-icoll.h> 41#include <mach/regs-apbh.h> 42#include <mach/regs-apbx.h> 43#include <mach/regs-pxp.h> 44#include <mach/regs-i2c.h> 45 46#include "stmp378x.h" 47/* 48 * IRQ handling 49 */ 50static void stmp378x_ack_irq(unsigned int irq) 51{ 52 /* Tell ICOLL to release IRQ line */ 53 __raw_writel(0, REGS_ICOLL_BASE + HW_ICOLL_VECTOR); 54 55 /* ACK current interrupt */ 56 __raw_writel(0x01 /* BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 */, 57 REGS_ICOLL_BASE + HW_ICOLL_LEVELACK); 58 59 /* Barrier */ 60 (void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT); 61} 62 63static void stmp378x_mask_irq(unsigned int irq) 64{ 65 /* IRQ disable */ 66 stmp3xxx_clearl(BM_ICOLL_INTERRUPTn_ENABLE, 67 REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10); 68} 69 70static void stmp378x_unmask_irq(unsigned int irq) 71{ 72 /* IRQ enable */ 73 stmp3xxx_setl(BM_ICOLL_INTERRUPTn_ENABLE, 74 REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10); 75} 76 77static struct irq_chip stmp378x_chip = { 78 .ack = stmp378x_ack_irq, 79 .mask = stmp378x_mask_irq, 80 .unmask = stmp378x_unmask_irq, 81}; 82 83void __init stmp378x_init_irq(void) 84{ 85 stmp3xxx_init_irq(&stmp378x_chip); 86} 87 88/* 89 * DMA interrupt handling 90 */ 91void stmp3xxx_arch_dma_enable_interrupt(int channel) 92{ 93 void __iomem *c1, *c2; 94 95 switch (STMP3XXX_DMA_BUS(channel)) { 96 case STMP3XXX_BUS_APBH: 97 c1 = REGS_APBH_BASE + HW_APBH_CTRL1; 98 c2 = REGS_APBH_BASE + HW_APBH_CTRL2; 99 break; 100 101 case STMP3XXX_BUS_APBX: 102 c1 = REGS_APBX_BASE + HW_APBX_CTRL1; 103 c2 = REGS_APBX_BASE + HW_APBX_CTRL2; 104 break; 105 106 default: 107 return; 108 } 109 stmp3xxx_setl(1 << (16 + STMP3XXX_DMA_CHANNEL(channel)), c1); 110 stmp3xxx_setl(1 << (16 + STMP3XXX_DMA_CHANNEL(channel)), c2); 111} 112EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt); 113 114void stmp3xxx_arch_dma_clear_interrupt(int channel) 115{ 116 void __iomem *c1, *c2; 117 118 switch (STMP3XXX_DMA_BUS(channel)) { 119 case STMP3XXX_BUS_APBH: 120 c1 = REGS_APBH_BASE + HW_APBH_CTRL1; 121 c2 = REGS_APBH_BASE + HW_APBH_CTRL2; 122 break; 123 124 case STMP3XXX_BUS_APBX: 125 c1 = REGS_APBX_BASE + HW_APBX_CTRL1; 126 c2 = REGS_APBX_BASE + HW_APBX_CTRL2; 127 break; 128 129 default: 130 return; 131 } 132 stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), c1); 133 stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), c2); 134} 135EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt); 136 137int stmp3xxx_arch_dma_is_interrupt(int channel) 138{ 139 int r = 0; 140 141 switch (STMP3XXX_DMA_BUS(channel)) { 142 case STMP3XXX_BUS_APBH: 143 r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & 144 (1 << STMP3XXX_DMA_CHANNEL(channel)); 145 break; 146 147 case STMP3XXX_BUS_APBX: 148 r = __raw_readl(REGS_APBX_BASE + HW_APBX_CTRL1) & 149 (1 << STMP3XXX_DMA_CHANNEL(channel)); 150 break; 151 } 152 return r; 153} 154EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt); 155 156void stmp3xxx_arch_dma_reset_channel(int channel) 157{ 158 unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); 159 void __iomem *c0; 160 u32 mask; 161 162 switch (STMP3XXX_DMA_BUS(channel)) { 163 case STMP3XXX_BUS_APBH: 164 c0 = REGS_APBH_BASE + HW_APBH_CTRL0; 165 mask = chbit << BP_APBH_CTRL0_RESET_CHANNEL; 166 break; 167 case STMP3XXX_BUS_APBX: 168 c0 = REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL; 169 mask = chbit << BP_APBX_CHANNEL_CTRL_RESET_CHANNEL; 170 break; 171 default: 172 return; 173 } 174 175 /* Reset channel and wait for it to complete */ 176 stmp3xxx_setl(mask, c0); 177 while (__raw_readl(c0) & mask) 178 cpu_relax(); 179} 180EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel); 181 182void stmp3xxx_arch_dma_freeze(int channel) 183{ 184 unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); 185 u32 mask = 1 << chbit; 186 187 switch (STMP3XXX_DMA_BUS(channel)) { 188 case STMP3XXX_BUS_APBH: 189 stmp3xxx_setl(mask, REGS_APBH_BASE + HW_APBH_CTRL0); 190 break; 191 case STMP3XXX_BUS_APBX: 192 stmp3xxx_setl(mask, REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL); 193 break; 194 } 195} 196EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze); 197 198void stmp3xxx_arch_dma_unfreeze(int channel) 199{ 200 unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); 201 u32 mask = 1 << chbit; 202 203 switch (STMP3XXX_DMA_BUS(channel)) { 204 case STMP3XXX_BUS_APBH: 205 stmp3xxx_clearl(mask, REGS_APBH_BASE + HW_APBH_CTRL0); 206 break; 207 case STMP3XXX_BUS_APBX: 208 stmp3xxx_clearl(mask, REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL); 209 break; 210 } 211} 212EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze); 213 214/* 215 * The registers are all very closely mapped, so we might as well map them all 216 * with a single mapping 217 * 218 * Logical Physical 219 * f0000000 80000000 On-chip registers 220 * f1000000 00000000 32k on-chip SRAM 221 */ 222 223static struct map_desc stmp378x_io_desc[] __initdata = { 224 { 225 .virtual = (u32)STMP3XXX_REGS_BASE, 226 .pfn = __phys_to_pfn(STMP3XXX_REGS_PHBASE), 227 .length = STMP3XXX_REGS_SIZE, 228 .type = MT_DEVICE, 229 }, 230 { 231 .virtual = (u32)STMP3XXX_OCRAM_BASE, 232 .pfn = __phys_to_pfn(STMP3XXX_OCRAM_PHBASE), 233 .length = STMP3XXX_OCRAM_SIZE, 234 .type = MT_DEVICE, 235 }, 236}; 237 238 239static u64 common_dmamask = DMA_BIT_MASK(32); 240 241/* 242 * devices that are present only on stmp378x, not on all 3xxx boards: 243 * PxP 244 * I2C 245 */ 246static struct resource pxp_resource[] = { 247 { 248 .flags = IORESOURCE_MEM, 249 .start = REGS_PXP_PHYS, 250 .end = REGS_PXP_PHYS + REGS_PXP_SIZE, 251 }, { 252 .flags = IORESOURCE_IRQ, 253 .start = IRQ_PXP, 254 .end = IRQ_PXP, 255 }, 256}; 257 258struct platform_device stmp378x_pxp = { 259 .name = "stmp3xxx-pxp", 260 .id = -1, 261 .dev = { 262 .dma_mask = &common_dmamask, 263 .coherent_dma_mask = DMA_BIT_MASK(32), 264 }, 265 .num_resources = ARRAY_SIZE(pxp_resource), 266 .resource = pxp_resource, 267}; 268 269static struct resource i2c_resources[] = { 270 { 271 .flags = IORESOURCE_IRQ, 272 .start = IRQ_I2C_ERROR, 273 .end = IRQ_I2C_ERROR, 274 }, { 275 .flags = IORESOURCE_MEM, 276 .start = REGS_I2C_PHYS, 277 .end = REGS_I2C_PHYS + REGS_I2C_SIZE, 278 }, { 279 .flags = IORESOURCE_DMA, 280 .start = STMP3XXX_DMA(3, STMP3XXX_BUS_APBX), 281 .end = STMP3XXX_DMA(3, STMP3XXX_BUS_APBX), 282 }, 283}; 284 285struct platform_device stmp378x_i2c = { 286 .name = "i2c_stmp3xxx", 287 .id = 0, 288 .dev = { 289 .dma_mask = &common_dmamask, 290 .coherent_dma_mask = DMA_BIT_MASK(32), 291 }, 292 .resource = i2c_resources, 293 .num_resources = ARRAY_SIZE(i2c_resources), 294}; 295 296void __init stmp378x_map_io(void) 297{ 298 iotable_init(stmp378x_io_desc, ARRAY_SIZE(stmp378x_io_desc)); 299} 300