1/* $Id: cf-enabler.c,v 1.1.1.1 2007/08/03 18:52:16 Exp $ 2 * 3 * linux/drivers/block/cf-enabler.c 4 * 5 * Copyright (C) 1999 Niibe Yutaka 6 * Copyright (C) 2000 Toshiharu Nozawa 7 * Copyright (C) 2001 A&D Co., Ltd. 8 * 9 * Enable the CF configuration. 10 */ 11 12#include <linux/init.h> 13#include <linux/mm.h> 14#include <linux/vmalloc.h> 15#include <linux/interrupt.h> 16#include <asm/io.h> 17#include <asm/irq.h> 18 19/* 20 * You can connect Compact Flash directly to the bus of SuperH. 21 * This is the enabler for that. 22 * 23 * SIM: How generic is this really? It looks pretty board, or at 24 * least SH sub-type, specific to me. 25 * I know it doesn't work on the Overdrive! 26 */ 27 28/* 29 * 0xB8000000 : Attribute 30 * 0xB8001000 : Common Memory 31 * 0xBA000000 : I/O 32 */ 33#if defined(CONFIG_CPU_SH4) 34/* SH4 can't access PCMCIA interface through P2 area. 35 * we must remap it with appropriate attribute bit of the page set. 36 * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */ 37 38#if defined(CONFIG_CF_AREA6) 39#define slot_no 0 40#else 41#define slot_no 1 42#endif 43 44/* use this pointer to access to directly connected compact flash io area*/ 45void *cf_io_base; 46 47static int __init allocate_cf_area(void) 48{ 49 pgprot_t prot; 50 unsigned long paddrbase, psize; 51 52 /* open I/O area window */ 53 paddrbase = virt_to_phys((void*)CONFIG_CF_BASE_ADDR); 54 psize = PAGE_SIZE; 55 prot = PAGE_KERNEL_PCC(slot_no, _PAGE_PCC_IO16); 56 cf_io_base = p3_ioremap(paddrbase, psize, prot.pgprot); 57 if (!cf_io_base) { 58 printk("allocate_cf_area : can't open CF I/O window!\n"); 59 return -ENOMEM; 60 } 61/* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n", 62 paddrbase, psize, prot.pgprot, cf_io_base);*/ 63 64 65 return 0; 66} 67#endif 68 69static int __init cf_init_default(void) 70{ 71/* You must have enabled the card, and set the level interrupt 72 * before reaching this point. Possibly in boot ROM or boot loader. 73 */ 74#if defined(CONFIG_CPU_SH4) 75 allocate_cf_area(); 76#endif 77#if defined(CONFIG_SH_UNKNOWN) 78 /* This should be done in each board's init_xxx_irq. */ 79 make_imask_irq(14); 80 disable_irq(14); 81#endif 82 return 0; 83} 84 85#if defined(CONFIG_SH_SOLUTION_ENGINE) 86#include <asm/se.h> 87#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE) 88#include <asm/se7722.h> 89#endif 90 91/* 92 * SolutionEngine Seriese 93 * 94 * about MS770xSE 95 * 0xB8400000 : Common Memory 96 * 0xB8500000 : Attribute 97 * 0xB8600000 : I/O 98 * 99 * about MS7722SE 100 * 0xB0400000 : Common Memory 101 * 0xB0500000 : Attribute 102 * 0xB0600000 : I/O 103 */ 104 105#if defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE) 106static int __init cf_init_se(void) 107{ 108 if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0) 109 return 0; /* Not detected */ 110 111 if ((ctrl_inw(MRSHPC_CSR) & 0x0080) == 0) { 112 ctrl_outw(0x0674, MRSHPC_CPWCR); /* Card Vcc is 3.3v? */ 113 } else { 114 ctrl_outw(0x0678, MRSHPC_CPWCR); /* Card Vcc is 5V */ 115 } 116 117 /* 118 * PC-Card window open 119 * flag == COMMON/ATTRIBUTE/IO 120 */ 121 /* common window open */ 122 ctrl_outw(0x8a84, MRSHPC_MW0CR1); 123 if((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) 124 /* common mode & bus width 16bit SWAP = 1*/ 125 ctrl_outw(0x0b00, MRSHPC_MW0CR2); 126 else 127 /* common mode & bus width 16bit SWAP = 0*/ 128 ctrl_outw(0x0300, MRSHPC_MW0CR2); 129 130 /* attribute window open */ 131 ctrl_outw(0x8a85, MRSHPC_MW1CR1); 132 if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) 133 /* attribute mode & bus width 16bit SWAP = 1*/ 134 ctrl_outw(0x0a00, MRSHPC_MW1CR2); 135 else 136 /* attribute mode & bus width 16bit SWAP = 0*/ 137 ctrl_outw(0x0200, MRSHPC_MW1CR2); 138 139 /* I/O window open */ 140 ctrl_outw(0x8a86, MRSHPC_IOWCR1); 141 ctrl_outw(0x0008, MRSHPC_CDCR); /* I/O card mode */ 142 if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) 143 ctrl_outw(0x0a00, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1*/ 144 else 145 ctrl_outw(0x0200, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0*/ 146 147 ctrl_outw(0x2000, MRSHPC_ICR); 148 ctrl_outb(0x00, PA_MRSHPC_MW2 + 0x206); 149 ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200); 150 return 0; 151} 152#else 153static int __init cf_init_se(void) 154{ 155 return -1; 156} 157#endif 158 159int __init cf_init(void) 160{ 161 if( mach_is_se() || mach_is_7722se() ){ 162 return cf_init_se(); 163 } 164 165 return cf_init_default(); 166} 167 168__initcall (cf_init); 169