1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * PCA9543A SMBus Switch driver File: dev_smbus_switch.c 5 * 6 * This module contains a CFE driver for a PCA9543A SMBus Switch. 7 * 8 * Author: Binh Vo 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 15 * This software is furnished under license and may be used and 16 * copied only in accordance with the following terms and 17 * conditions. Subject to these conditions, you may download, 18 * copy, install, use, modify and distribute modified or unmodified 19 * copies of this software in source and/or binary form. No title 20 * or ownership is transferred hereby. 21 * 22 * 1) Any source code used, modified or distributed must reproduce 23 * and retain this copyright notice and list of conditions 24 * as they appear in the source file. 25 * 26 * 2) No right is granted to use any trade name, trademark, or 27 * logo of Broadcom Corporation. The "Broadcom Corporation" 28 * name may not be used to endorse or promote products derived 29 * from this software without the prior written permission of 30 * Broadcom Corporation. 31 * 32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 44 * THE POSSIBILITY OF SUCH DAMAGE. 45 ********************************************************************* */ 46 47#include "cfe.h" 48#include "cfe_smbus.h" 49 50 51/* ********************************************************************* 52 * Constants 53 ********************************************************************* */ 54 55/* 56 * Register bits 57 */ 58 59#define SWITCH_CHAN0 0x01 /* Channel 0 */ 60#define SWITCH_CHAN1 0x02 /* Channel 1 */ 61 62/* 63 * Register numbers 64 */ 65 66 67/* ********************************************************************* 68 * Forward declarations 69 ********************************************************************* */ 70 71static void switch_probe(cfe_driver_t *drv, 72 unsigned long probe_a, unsigned long probe_b, 73 void *probe_ptr); 74 75static int switch_open(cfe_devctx_t *ctx); 76static int switch_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 77static int switch_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 78static int switch_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 79static int switch_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 80static int switch_close(cfe_devctx_t *ctx); 81 82 83/* ********************************************************************* 84 * Device dispatch 85 ********************************************************************* */ 86 87const static cfe_devdisp_t switch_dispatch = { 88 switch_open, 89 switch_read, 90 switch_inpstat, 91 switch_write, 92 switch_ioctl, 93 switch_close, 94 NULL, 95 NULL 96}; 97 98const cfe_driver_t smbus_switch = { 99 "SMBUS SWITCH", 100 "switch", 101 CFE_DEV_OTHER, 102 &switch_dispatch, 103 switch_probe 104}; 105 106 107/* ********************************************************************* 108 * Structures 109 ********************************************************************* */ 110typedef struct switch_s { 111 cfe_smbus_channel_t *smbus_channel; 112} switch_t; 113 114/* ********************************************************************* 115 * smbus_readbyte(chan,slaveaddr,devaddr) 116 * 117 * Read a byte from the chip. 118 * 119 * Input parameters: 120 * chan - SMBus channel 121 * slaveaddr - SMBus slave address 122 * devaddr - byte within the at24c02 device to read 123 * 124 * Return value: 125 * 0 if ok 126 * else -1 127 ********************************************************************* */ 128 129static int smbus_readbyte(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr) 130{ 131 uint8_t buf[1]; 132 int err; 133 134 /* 135 * Start the command 136 */ 137 138 buf[0] = devaddr; 139 err = SMBUS_WRITE(chan,slaveaddr,buf,1); 140 if (err < 0) return err; 141 142 /* 143 * Read the data byte 144 */ 145 146 err = SMBUS_READ(chan,slaveaddr,buf,1); 147 if (err < 0) return err; 148 149 return buf[0]; 150} 151 152/* ********************************************************************* 153 * smbus_writebyte(chan,slaveaddr,devaddr,b) 154 * 155 * write a byte from the chip. 156 * 157 * Input parameters: 158 * chan - SMBus channel 159 * slaveaddr - SMBus slave address 160 * devaddr - byte within the at24c02 device to read 161 * b - byte to write 162 * 163 * Return value: 164 * 0 if ok 165 * else -1 166 ********************************************************************* */ 167 168static int smbus_writebyte(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr,int b) 169{ 170 uint8_t buf[2]; 171 int err; 172 int64_t timer; 173 174 /* 175 * Write the data to the controller 176 */ 177 178 buf[0] = devaddr; 179 buf[1] = b; 180 181 err = SMBUS_WRITE(chan,slaveaddr,buf,2); 182 183 /* 184 * Pound on the device with a current address read 185 * to poll for the write complete 186 */ 187 188 TIMER_SET(timer,50); 189 err = -1; 190 191 while (!TIMER_EXPIRED(timer)) { 192 POLL(); 193 194 err = SMBUS_READ(chan,slaveaddr,buf,1); 195 if (err == 0) break; 196 } 197 198 return err; 199} 200 201/* ********************************************************************* 202 * switch_probe(drv,a,b,ptr) 203 * 204 * Probe routine for this driver. This routine creates the 205 * local device context and attaches it to the driver list 206 * within CFE. 207 * 208 * Input parameters: 209 * drv - driver handle 210 * a,b - probe hints (longs) 211 * ptr - probe hint (pointer) 212 * 213 * Return value: 214 * nothing 215 ********************************************************************* */ 216 217static void switch_probe(cfe_driver_t *drv, 218 unsigned long probe_a, unsigned long probe_b, 219 void *probe_ptr) 220{ 221 switch_t *softc; 222 char descr[80]; 223 224 softc = (switch_t *) KMALLOC(sizeof(switch_t),0); 225 226 /* 227 * Probe_a is the SMBus channel number 228 * Probe_b is the SMBus device address 229 * Probe_ptr is unused. 230 */ 231 232 softc->smbus_channel = SMBUS_CHANNEL((int)probe_a); 233 234 xsprintf(descr,"%s on SMBus channel %d dev 0x%02X", 235 drv->drv_description,probe_a,probe_b); 236 cfe_attach(drv,softc,NULL,descr); 237 238} 239 240/* ********************************************************************* 241 * switch_open(ctx) 242 * 243 * Open this device. For the M41T81, we do a quick test 244 * read to be sure the device is out there. 245 * 246 * Input parameters: 247 * ctx - device context (can obtain our softc here) 248 * 249 * Return value: 250 * 0 if ok 251 * else error code 252 ********************************************************************* */ 253 254static int switch_open(cfe_devctx_t *ctx) 255{ 256 switch_t *softc = ctx->dev_softc; 257 int b = -1; 258 259 b = smbus_readbyte(softc->smbus_channel, 260 0, 261 0); 262 b = smbus_writebyte(softc->smbus_channel, 263 0, 264 0, 265 0x01); 266 267 return (b < 0) ? -1 : 0; 268} 269 270/* ********************************************************************* 271 * switch_read(ctx,buffer) 272 * 273 * Read from switch. 274 * 275 * Input parameters: 276 * ctx - device context (can obtain our softc here) 277 * buffer - buffer descriptor (target buffer, length, offset) 278 * 279 * Return value: 280 * number of bytes read 281 * -1 if an error occured 282 ********************************************************************* */ 283 284static int switch_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 285{ 286 return 0; 287} 288 289/* ********************************************************************* 290 * switch_write(ctx,buffer) 291 * 292 * Write to switch. 293 * 294 * Input parameters: 295 * ctx - device context (can obtain our softc here) 296 * buffer - buffer descriptor (target buffer, length, offset) 297 * 298 * Return value: 299 * number of bytes written 300 * -1 if an error occured 301 ********************************************************************* */ 302 303static int switch_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 304{ 305 return 0; 306} 307 308/* ********************************************************************* 309 * switch_inpstat(ctx,inpstat) 310 * 311 * Test input (read) status for the device 312 * 313 * Input parameters: 314 * ctx - device context (can obtain our softc here) 315 * inpstat - input status descriptor to receive value 316 * 317 * Return value: 318 * 0 if ok 319 * -1 if an error occured 320 ********************************************************************* */ 321 322static int switch_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 323{ 324 inpstat->inp_status = 1; 325 326 return 0; 327} 328 329/* ********************************************************************* 330 * switch_ioctl(ctx,buffer) 331 * 332 * Perform miscellaneous I/O control operations on the device. 333 * 334 * Input parameters: 335 * ctx - device context (can obtain our softc here) 336 * buffer - buffer descriptor (target buffer, length, offset) 337 * 338 * Return value: 339 * number of bytes read 340 * -1 if an error occured 341 ********************************************************************* */ 342 343static int switch_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 344{ 345 return 0; 346} 347 348/* ********************************************************************* 349 * switch_close(ctx,buffer) 350 * 351 * Close the device. 352 * 353 * Input parameters: 354 * ctx - device context (can obtain our softc here) 355 * 356 * Return value: 357 * 0 if ok 358 * -1 if an error occured 359 ********************************************************************* */ 360 361static int switch_close(cfe_devctx_t *ctx) 362{ 363 return 0; 364} 365 366 367 368 369 370 371 372 373