1/* 2 Mantis PCI bridge driver 3 4 Copyright (C) Manu Abraham (abraham.manu@gmail.com) 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "mantis_common.h" 22#include "mantis_core.h" 23#include "mantis_vp1033.h" 24#include "mantis_vp1034.h" 25#include "mantis_vp1041.h" 26#include "mantis_vp2033.h" 27#include "mantis_vp2040.h" 28#include "mantis_vp3030.h" 29 30static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) 31{ 32 int err; 33 struct i2c_msg msg[] = { 34 { 35 .addr = 0x50, 36 .flags = 0, 37 .buf = data, 38 .len = 1 39 }, { 40 .addr = 0x50, 41 .flags = I2C_M_RD, 42 .buf = data, 43 .len = length 44 }, 45 }; 46 47 err = i2c_transfer(&mantis->adapter, msg, 2); 48 if (err < 0) { 49 dprintk(verbose, MANTIS_ERROR, 1, 50 "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", 51 err, data[0], data[1]); 52 53 return err; 54 } 55 56 return 0; 57} 58 59static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) 60{ 61 int err; 62 63 struct i2c_msg msg = { 64 .addr = 0x50, 65 .flags = 0, 66 .buf = data, 67 .len = length 68 }; 69 70 err = i2c_transfer(&mantis->adapter, &msg, 1); 71 if (err < 0) { 72 dprintk(verbose, MANTIS_ERROR, 1, 73 "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", 74 err, length, data[0], data[1]); 75 76 return err; 77 } 78 79 return 0; 80} 81 82static int get_mac_address(struct mantis_pci *mantis) 83{ 84 int err; 85 86 mantis->mac_address[0] = 0x08; 87 err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); 88 if (err < 0) { 89 dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); 90 91 return err; 92 } 93 dprintk(verbose, MANTIS_ERROR, 0, 94 " MAC Address=[%pM]\n", mantis->mac_address); 95 96 return 0; 97} 98 99#define MANTIS_MODEL_UNKNOWN "UNKNOWN" 100#define MANTIS_DEV_UNKNOWN "UNKNOWN" 101 102struct mantis_hwconfig unknown_device = { 103 .model_name = MANTIS_MODEL_UNKNOWN, 104 .dev_type = MANTIS_DEV_UNKNOWN, 105}; 106 107static void mantis_load_config(struct mantis_pci *mantis) 108{ 109 switch (mantis->subsystem_device) { 110 case MANTIS_VP_1033_DVB_S: /* VP-1033 */ 111 mantis->hwconfig = &vp1033_mantis_config; 112 break; 113 case MANTIS_VP_1034_DVB_S: /* VP-1034 */ 114 mantis->hwconfig = &vp1034_mantis_config; 115 break; 116 case MANTIS_VP_1041_DVB_S2: /* VP-1041 */ 117 case TECHNISAT_SKYSTAR_HD2: 118 mantis->hwconfig = &vp1041_mantis_config; 119 break; 120 case MANTIS_VP_2033_DVB_C: /* VP-2033 */ 121 mantis->hwconfig = &vp2033_mantis_config; 122 break; 123 case MANTIS_VP_2040_DVB_C: /* VP-2040 */ 124 case CINERGY_C: /* VP-2040 clone */ 125 case TECHNISAT_CABLESTAR_HD2: 126 mantis->hwconfig = &vp2040_mantis_config; 127 break; 128 case MANTIS_VP_3030_DVB_T: /* VP-3030 */ 129 mantis->hwconfig = &vp3030_mantis_config; 130 break; 131 default: 132 mantis->hwconfig = &unknown_device; 133 break; 134 } 135} 136 137int mantis_core_init(struct mantis_pci *mantis) 138{ 139 int err = 0; 140 141 mantis_load_config(mantis); 142 dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", 143 mantis->hwconfig->model_name, mantis->hwconfig->dev_type, 144 mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn)); 145 dprintk(verbose, MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", 146 mantis->revision, 147 mantis->subsystem_vendor, mantis->subsystem_device); 148 dprintk(verbose, MANTIS_ERROR, 0, 149 "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", 150 mantis->pdev->irq, mantis->latency, 151 mantis->mantis_addr, mantis->mantis_mmio); 152 153 err = mantis_i2c_init(mantis); 154 if (err < 0) { 155 dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); 156 return err; 157 } 158 err = get_mac_address(mantis); 159 if (err < 0) { 160 dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); 161 return err; 162 } 163 err = mantis_dma_init(mantis); 164 if (err < 0) { 165 dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); 166 return err; 167 } 168 err = mantis_dvb_init(mantis); 169 if (err < 0) { 170 dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); 171 return err; 172 } 173 err = mantis_uart_init(mantis); 174 if (err < 0) { 175 dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed"); 176 return err; 177 } 178 179 return 0; 180} 181 182int mantis_core_exit(struct mantis_pci *mantis) 183{ 184 mantis_dma_stop(mantis); 185 dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); 186 187 mantis_uart_exit(mantis); 188 dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed"); 189 190 if (mantis_dma_exit(mantis) < 0) 191 dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); 192 if (mantis_dvb_exit(mantis) < 0) 193 dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed"); 194 if (mantis_i2c_exit(mantis) < 0) 195 dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed"); 196 197 return 0; 198} 199 200/* Turn the given bit on or off. */ 201void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) 202{ 203 u32 cur; 204 205 cur = mmread(MANTIS_GPIF_ADDR); 206 if (value) 207 mantis->gpio_status = cur | (1 << bitpos); 208 else 209 mantis->gpio_status = cur & (~(1 << bitpos)); 210 211 mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); 212 mmwrite(0x00, MANTIS_GPIF_DOUT); 213 udelay(100); 214} 215 216/* direction = 0 , no CI passthrough ; 1 , CI passthrough */ 217void mantis_set_direction(struct mantis_pci *mantis, int direction) 218{ 219 u32 reg; 220 221 reg = mmread(0x28); 222 dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); 223 if (direction == 0x01) { 224 /* to CI */ 225 reg |= 0x04; 226 mmwrite(reg, 0x28); 227 reg &= 0xff - 0x04; 228 mmwrite(reg, 0x28); 229 } else { 230 reg &= 0xff - 0x04; 231 mmwrite(reg, 0x28); 232 reg |= 0x04; 233 mmwrite(reg, 0x28); 234 } 235} 236