1/* 2 * Copyright (C) 2001 Broadcom Corporation 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19/* Derived loosely from ide-pmac.c, so: 20 * 21 * Copyright (C) 1998 Paul Mackerras. 22 * Copyright (C) 1995-1998 Mark Lord 23 */ 24#include <linux/config.h> 25#include <linux/types.h> 26#include <linux/kernel.h> 27#include <linux/sched.h> 28#include <linux/init.h> 29#include <linux/delay.h> 30#include <linux/ide.h> 31 32#include <asm/irq.h> 33#include <asm/io.h> 34#include <asm/sibyte/sb1250_regs.h> 35#include <asm/sibyte/sb1250_int.h> 36#include <asm/sibyte/sb1250_genbus.h> 37#include <asm/sibyte/64bit.h> 38#include <asm/sibyte/board.h> 39 40/* Note: this should be general for any board using IDE on GenBus */ 41 42extern struct ide_ops std_ide_ops; 43 44static ide_hwif_t *sb_ide_hwif = NULL; 45static unsigned long ide_base; 46 47#define SIBYTE_IDE_BASE (KSEG1ADDR(ide_base)-mips_io_port_base) 48#define SIBYTE_IDE_REG(pcaddr) (SIBYTE_IDE_BASE + ((pcaddr)<<5)) 49 50/* 51 * We are limiting the number of PCI-IDE devices to leave room for 52 * GenBus IDE (and possibly PCMCIA/CF?) 53 */ 54static int sibyte_ide_default_irq(ide_ioreg_t base) 55{ 56 return 0; 57} 58 59static ide_ioreg_t sibyte_ide_default_io_base(int index) 60{ 61 return 0; 62} 63 64static void sibyte_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, 65 ide_ioreg_t ctrl_port, int *irq) 66{ 67 std_ide_ops.ide_init_hwif_ports(hw, data_port, ctrl_port, irq); 68} 69 70static int sibyte_ide_request_irq(unsigned int irq, 71 void (*handler)(int,void *, struct pt_regs *), 72 unsigned long flags, const char *device, 73 void *dev_id) 74{ 75 return request_irq(irq, handler, flags, device, dev_id); 76} 77 78static void sibyte_ide_free_irq(unsigned int irq, void *dev_id) 79{ 80 free_irq(irq, dev_id); 81} 82 83static inline int is_sibyte_ide(ide_ioreg_t from) 84{ 85 return (sb_ide_hwif && 86 ((from == sb_ide_hwif->io_ports[IDE_DATA_OFFSET]) || 87 (from == sb_ide_hwif->io_ports[IDE_ERROR_OFFSET]) || 88 (from == sb_ide_hwif->io_ports[IDE_NSECTOR_OFFSET]) || 89 (from == sb_ide_hwif->io_ports[IDE_SECTOR_OFFSET]) || 90 (from == sb_ide_hwif->io_ports[IDE_LCYL_OFFSET]) || 91 (from == sb_ide_hwif->io_ports[IDE_HCYL_OFFSET]) || 92 (from == sb_ide_hwif->io_ports[IDE_SELECT_OFFSET]) || 93 (from == sb_ide_hwif->io_ports[IDE_STATUS_OFFSET]) || 94 (from == sb_ide_hwif->io_ports[IDE_CONTROL_OFFSET]))); 95} 96 97static int sibyte_ide_check_region(ide_ioreg_t from, unsigned int extent) 98{ 99 /* Figure out if it's the SiByte IDE; if so, don't do anything 100 since our I/O space is in a weird place. */ 101 if (is_sibyte_ide(from)) 102 return 0; 103 else 104#ifdef CONFIG_BLK_DEV_IDE 105 return std_ide_ops.ide_check_region(from, extent); 106#else 107 return 0; 108#endif 109} 110 111static void sibyte_ide_request_region(ide_ioreg_t from, unsigned int extent, 112 const char *name) 113{ 114#ifdef CONFIG_BLK_DEV_IDE 115 if (!is_sibyte_ide(from)) 116 std_ide_ops.ide_request_region(from, extent, name); 117#endif 118} 119 120static void sibyte_ide_release_region(ide_ioreg_t from, unsigned int extent) 121{ 122#ifdef CONFIG_BLK_DEV_IDE 123 if (!is_sibyte_ide(from)) 124 std_ide_ops.ide_release_region(from, extent); 125#endif 126} 127 128struct ide_ops sibyte_ide_ops = { 129 &sibyte_ide_default_irq, 130 &sibyte_ide_default_io_base, 131 &sibyte_ide_init_hwif_ports, 132 &sibyte_ide_request_irq, 133 &sibyte_ide_free_irq, 134 &sibyte_ide_check_region, 135 &sibyte_ide_request_region, 136 &sibyte_ide_release_region 137}; 138 139/* 140 * I/O operations. The FPGA for SiByte generic bus IDE deals with 141 * byte-swapping for us, so we can't share the I/O macros with other 142 * IDE (e.g. PCI-IDE) devices. 143 */ 144 145#define sibyte_outb(val,port) \ 146do { \ 147 *(volatile u8 *)(mips_io_port_base + (port)) = val; \ 148} while(0) 149 150#define sibyte_outw(val,port) \ 151do { \ 152 *(volatile u16 *)(mips_io_port_base + (port)) = val; \ 153} while(0) 154 155#define sibyte_outl(val,port) \ 156do { \ 157 *(volatile u32 *)(mips_io_port_base + (port)) = val; \ 158} while(0) 159 160static inline unsigned char sibyte_inb(unsigned long port) 161{ 162 return (*(volatile u8 *)(mips_io_port_base + (port))); 163} 164 165static inline unsigned short sibyte_inw(unsigned long port) 166{ 167 return (*(volatile u16 *)(mips_io_port_base + (port))); 168} 169 170static inline unsigned int sibyte_inl(unsigned long port) 171{ 172 return (*(volatile u32 *)(mips_io_port_base + (port))); 173} 174 175 176static inline void sibyte_outsb(unsigned long port, void *addr, unsigned int count) 177{ 178 while (count--) { 179 sibyte_outb(*(u8 *)addr, port); 180 addr++; 181 } 182} 183 184static inline void sibyte_insb(unsigned long port, void *addr, unsigned int count) 185{ 186 while (count--) { 187 *(u8 *)addr = sibyte_inb(port); 188 addr++; 189 } 190} 191 192static inline void sibyte_outsw(unsigned long port, void *addr, unsigned int count) 193{ 194 while (count--) { 195 sibyte_outw(*(u16 *)addr, port); 196 addr += 2; 197 } 198} 199 200static inline void sibyte_insw(unsigned long port, void *addr, unsigned int count) 201{ 202 while (count--) { 203 *(u16 *)addr = sibyte_inw(port); 204 addr += 2; 205 } 206} 207 208static inline void sibyte_outsl(unsigned long port, void *addr, unsigned int count) 209{ 210 while (count--) { 211 sibyte_outl(*(u32 *)addr, port); 212 addr += 4; 213 } 214} 215 216static inline void sibyte_insl(unsigned long port, void *addr, unsigned int count) 217{ 218 while (count--) { 219 *(u32 *)addr = sibyte_inl(port); 220 addr += 4; 221 } 222} 223 224static void sibyte_ideproc(ide_ide_action_t action, ide_drive_t *drive, 225 void *buffer, unsigned int count) 226{ 227 /* slow? vlb_sync? */ 228 switch (action) { 229 case ideproc_ide_input_data: 230 if (drive->io_32bit) { 231 sibyte_insl(IDE_DATA_REG, buffer, count); 232 } else { 233 sibyte_insw(IDE_DATA_REG, buffer, count<<1); 234 } 235 break; 236 case ideproc_ide_output_data: 237 if (drive->io_32bit) { 238 sibyte_outsl(IDE_DATA_REG, buffer, count); 239 } else { 240 sibyte_outsw(IDE_DATA_REG, buffer, count<<1); 241 } 242 break; 243 case ideproc_atapi_input_bytes: 244 count++; 245 if (drive->io_32bit) { 246 sibyte_insl(IDE_DATA_REG, buffer, count>>2); 247 } else { 248 sibyte_insw(IDE_DATA_REG, buffer, count>>1); 249 } 250 if ((count & 3) >= 2) 251 sibyte_insw(IDE_DATA_REG, (char *)buffer + (count & ~3), 1); 252 break; 253 case ideproc_atapi_output_bytes: 254 count++; 255 if (drive->io_32bit) { 256 sibyte_outsl(IDE_DATA_REG, buffer, count>>2); 257 } else { 258 sibyte_outsw(IDE_DATA_REG, buffer, count>>1); 259 } 260 if ((count & 3) >= 2) 261 sibyte_outsw(IDE_DATA_REG, (char *)buffer + (count & ~3), 1); 262 break; 263 } 264} 265 266/* 267 * selectproc and intrproc aren't really necessary, since 268 * byte-swapping doesn't affect byte ops; they are included for 269 * consistency. 270 */ 271static void sibyte_selectproc(ide_drive_t *drive) 272{ 273 sibyte_outb(drive->select.all, IDE_SELECT_REG); 274} 275 276static void sibyte_intrproc(ide_drive_t *drive) 277{ 278 sibyte_outb(drive->ctl|2, IDE_CONTROL_REG); 279} 280 281void __init sibyte_ide_probe(void) 282{ 283 int i; 284 ide_hwif_t *hwif; 285 /* 286 * Find the first untaken slot in hwifs 287 */ 288 for (i = 0; i < MAX_HWIFS; i++) { 289 if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) { 290 break; 291 } 292 } 293 if (i == MAX_HWIFS) { 294 printk("No space for SiByte onboard IDE driver in ide_hwifs[]. Not enabled.\n"); 295 return; 296 } 297 298 /* Find memory base address */ 299#ifdef __MIPSEL__ 300 if (sb1250_pass == K_SYS_REVISION_PASS1) 301 ide_base = G_IO_START_ADDR(csr_in32(4+(IO_SPACE_BASE|A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS))))) << S_IO_ADDRBASE; 302 else 303#endif 304 ide_base = G_IO_START_ADDR(csr_in32(IO_SPACE_BASE|A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)))) << S_IO_ADDRBASE; 305 306 /* 307 * Set up our stuff; we're a little odd because our io_ports 308 * aren't in the usual place, and byte-swapping isn't 309 * necessary. 310 */ 311 hwif = &ide_hwifs[i]; 312 hwif->hw.io_ports[IDE_DATA_OFFSET] = SIBYTE_IDE_REG(0x1f0); 313 hwif->hw.io_ports[IDE_ERROR_OFFSET] = SIBYTE_IDE_REG(0x1f1); 314 hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = SIBYTE_IDE_REG(0x1f2); 315 hwif->hw.io_ports[IDE_SECTOR_OFFSET] = SIBYTE_IDE_REG(0x1f3); 316 hwif->hw.io_ports[IDE_LCYL_OFFSET] = SIBYTE_IDE_REG(0x1f4); 317 hwif->hw.io_ports[IDE_HCYL_OFFSET] = SIBYTE_IDE_REG(0x1f5); 318 hwif->hw.io_ports[IDE_SELECT_OFFSET] = SIBYTE_IDE_REG(0x1f6); 319 hwif->hw.io_ports[IDE_STATUS_OFFSET] = SIBYTE_IDE_REG(0x1f7); 320 hwif->hw.io_ports[IDE_CONTROL_OFFSET] = SIBYTE_IDE_REG(0x3f6); 321 hwif->hw.irq = K_INT_GB_IDE; 322 hwif->irq = K_INT_GB_IDE; 323 hwif->noprobe = 0; 324 /* Use our own non-byte-swapping routines */ 325 hwif->ideproc = sibyte_ideproc; 326 hwif->selectproc = sibyte_selectproc; 327 hwif->intrproc = sibyte_intrproc; 328 329 memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); 330 printk("SiByte onboard IDE configured as device %i\n", i); 331 sb_ide_hwif = hwif; 332} 333