1 /* $NetBSD: gayle.c,v 1.8 2015/01/16 23:34:11 phx Exp $ */ 2 3 /* public domain */ 4 5 #include <sys/cdefs.h> 6 __KERNEL_RCSID(0, "$NetBSD: gayle.c,v 1.8 2015/01/16 23:34:11 phx Exp $"); 7 8 /* 9 * Gayle management - provide functions for use in the drivers that utilise 10 * the chip. 11 * 12 * These overly complicated routines try to deal with a few variants of 13 * Gayle chip that exists. 14 */ 15 #include <sys/bus.h> 16 #include <sys/systm.h> 17 18 #include <machine/cpu.h> 19 20 #include <amiga/amiga/gayle.h> 21 #include <amiga/dev/zbusvar.h> 22 23 /* #define GAYLE_DEBUG 1 */ 24 25 struct gayle_tag { 26 struct bus_space_tag gayle_io_bst; 27 bus_space_tag_t gayle_io_t; 28 bus_space_handle_t gayle_io_h; 29 30 struct bus_space_tag gayle_isr_bst; 31 bus_space_tag_t gayle_isr_t; 32 bus_space_handle_t gayle_isr_h; 33 }; 34 35 typedef struct gayle_tag *gayle_tag_t; 36 37 /* 38 * Having these as static variables is ugly, but they don't fit into 39 * driver's softc, as the chip might be utilised by many different drivers. 40 * And since we can only have one Gayle per system it should be okay. 41 */ 42 static struct gayle_tag gayle; 43 static gayle_tag_t gayle_t = NULL; 44 45 /* 46 * Any module that uses gayle should call gayle_init() before using anything 47 * related to gayle. gayle_init() can be called multiple times. 48 */ 49 void 50 gayle_init(void) { 51 bus_addr_t gayle_vbase; 52 53 if (gayle_t != NULL) 54 return; 55 56 #ifdef GAYLE_DEBUG 57 aprint_normal("gayle: doing init\n"); 58 #endif /* GAYLE_DEBUG */ 59 60 gayle_t = &gayle; 61 62 gayle_vbase = (bus_addr_t) __UNVOLATILE(ztwomap(GAYLE_REGS_BASE)); 63 64 gayle_t->gayle_io_bst.base = gayle_vbase; 65 gayle_t->gayle_io_bst.absm = &amiga_bus_stride_0x1000; 66 gayle_t->gayle_io_t = &(gayle_t->gayle_io_bst); 67 68 bus_space_map(gayle_t->gayle_io_t, 0, 0x4, 0, &gayle_t->gayle_io_h); 69 70 /* 71 * The A4000 variant of Gayle has interrupt status register at offset 72 * +0x1000 from IDE registers. 73 * XXX: in fact, on A4000 we should initialise only this part... 74 */ 75 if (is_a4000()) { 76 gayle_t->gayle_isr_bst.base = (bus_addr_t) __UNVOLATILE(ztwomap( 77 GAYLE_IDE_BASE_A4000+GAYLE_IDE_INTREQ_A4000)); 78 gayle_t->gayle_isr_bst.absm = &amiga_bus_stride_1; 79 gayle_t->gayle_isr_t = &(gayle_t->gayle_isr_bst); 80 81 bus_space_map(gayle_t->gayle_isr_t, 0, 0x1, 0, 82 &(gayle_t->gayle_isr_h)); 83 } else { 84 bus_space_subregion(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 85 GAYLE_INTREQ, 0x1, &(gayle_t->gayle_isr_h)); 86 87 gayle_t->gayle_isr_bst = gayle_t->gayle_io_bst; 88 gayle_t->gayle_isr_t = gayle_t->gayle_io_t; 89 } 90 91 } 92 93 uint8_t 94 gayle_intr_status(void) 95 { 96 uint8_t rv; 97 98 rv = bus_space_read_1(gayle_t->gayle_isr_t, gayle_t->gayle_isr_h, 0); 99 #ifdef GAYLE_DEBUG 100 aprint_normal("gayle: intr status %x\n", rv); 101 #endif /* GAYLE_DEBUG */ 102 103 return rv; 104 } 105 106 uint8_t 107 gayle_intr_enable_read(void) 108 { 109 uint8_t rv; 110 111 rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 112 GAYLE_INTENA); 113 #ifdef GAYLE_DEBUG 114 aprint_normal("gayle: intr enable register read %x\n", rv); 115 #endif /* GAYLE_DEBUG */ 116 117 return rv; 118 } 119 120 void 121 gayle_intr_enable_write(uint8_t val) 122 { 123 #ifdef GAYLE_DEBUG 124 aprint_normal("gayle: intr enable register write %x\n", val); 125 #endif /* GAYLE_DEBUG */ 126 bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 127 GAYLE_INTENA, val); 128 } 129 130 void 131 gayle_intr_enable_set(uint8_t bits) 132 { 133 uint8_t val; 134 val = gayle_intr_enable_read(); 135 gayle_intr_enable_write(val | bits); 136 } 137 138 void 139 gayle_intr_ack(uint8_t val) 140 { 141 #ifdef GAYLE_DEBUG 142 aprint_normal("gayle: intr ack write %x\n", val); 143 #endif /* GAYLE_DEBUG */ 144 bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 145 GAYLE_INTREQ, val); 146 } 147 148 uint8_t 149 gayle_pcmcia_status_read(void) 150 { 151 uint8_t rv; 152 153 rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 154 GAYLE_PCC_STATUS); 155 #ifdef GAYLE_DEBUG 156 aprint_normal("gayle: pcmcia status read %x\n", rv); 157 #endif /* GAYLE_DEBUG */ 158 159 return rv; 160 } 161 162 void 163 gayle_pcmcia_status_write(uint8_t val) 164 { 165 #ifdef GAYLE_DEBUG 166 aprint_normal("gayle: pcmcia status write %x\n", val); 167 #endif /* GAYLE_DEBUG */ 168 bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 169 GAYLE_PCC_STATUS, val); 170 } 171 172 void 173 gayle_pcmcia_config_write(uint8_t val) 174 { 175 #ifdef GAYLE_DEBUG 176 aprint_normal("gayle: pcmcia config write %x\n", val); 177 #endif /* GAYLE_DEBUG */ 178 bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 179 GAYLE_PCC_CONFIG, val); 180 } 181 182 uint8_t 183 gayle_pcmcia_config_read(void) 184 { 185 uint8_t rv; 186 187 rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, 188 GAYLE_PCC_CONFIG); 189 #ifdef GAYLE_DEBUG 190 aprint_normal("gayle: pcmcia config read %x\n", rv); 191 #endif /* GAYLE_DEBUG */ 192 193 return rv; 194 } 195 196