Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc4 406 lines 11 kB view raw
1/* 2 * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $) 3 * 4 * Copyright (c) 2002, 2005 Ducrot Bruno 5 * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation version 2. 10 */ 11 12#include <linux/version.h> 13#include <linux/module.h> 14#include <linux/slab.h> 15#include <linux/kernel.h> 16#include <linux/stddef.h> 17#include <linux/sched.h> 18#include <linux/init.h> 19#include <linux/i2c.h> 20#include <linux/acpi.h> 21#include <linux/delay.h> 22 23#include "i2c_ec.h" 24 25#define xudelay(t) udelay(t) 26#define xmsleep(t) msleep(t) 27 28#define ACPI_EC_HC_COMPONENT 0x00080000 29#define ACPI_EC_HC_CLASS "ec_hc_smbus" 30#define ACPI_EC_HC_HID "ACPI0001" 31#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver" 32#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus" 33 34#define _COMPONENT ACPI_EC_HC_COMPONENT 35 36ACPI_MODULE_NAME("acpi_smbus") 37 38static int acpi_ec_hc_add(struct acpi_device *device); 39static int acpi_ec_hc_remove(struct acpi_device *device, int type); 40 41static struct acpi_driver acpi_ec_hc_driver = { 42 .name = ACPI_EC_HC_DRIVER_NAME, 43 .class = ACPI_EC_HC_CLASS, 44 .ids = ACPI_EC_HC_HID, 45 .ops = { 46 .add = acpi_ec_hc_add, 47 .remove = acpi_ec_hc_remove, 48 }, 49}; 50 51/* Various bit mask for EC_SC (R) */ 52#define OBF 0x01 53#define IBF 0x02 54#define CMD 0x08 55#define BURST 0x10 56#define SCI_EVT 0x20 57#define SMI_EVT 0x40 58 59/* Commands for EC_SC (W) */ 60#define RD_EC 0x80 61#define WR_EC 0x81 62#define BE_EC 0x82 63#define BD_EC 0x83 64#define QR_EC 0x84 65 66/* 67 * ACPI 2.0 chapter 13 SMBus 2.0 EC register model 68 */ 69 70#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */ 71#define ACPI_EC_SMB_STS 0x01 /* status */ 72#define ACPI_EC_SMB_ADDR 0x02 /* address */ 73#define ACPI_EC_SMB_CMD 0x03 /* command */ 74#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */ 75#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */ 76#define ACPI_EC_SMB_ALRM_A 0x25 /* alarm address */ 77#define ACPI_EC_SMB_ALRM_D 0x26 /* 2 bytes alarm data */ 78 79#define ACPI_EC_SMB_STS_DONE 0x80 80#define ACPI_EC_SMB_STS_ALRM 0x40 81#define ACPI_EC_SMB_STS_RES 0x20 82#define ACPI_EC_SMB_STS_STATUS 0x1f 83 84#define ACPI_EC_SMB_STATUS_OK 0x00 85#define ACPI_EC_SMB_STATUS_FAIL 0x07 86#define ACPI_EC_SMB_STATUS_DNAK 0x10 87#define ACPI_EC_SMB_STATUS_DERR 0x11 88#define ACPI_EC_SMB_STATUS_CMD_DENY 0x12 89#define ACPI_EC_SMB_STATUS_UNKNOWN 0x13 90#define ACPI_EC_SMB_STATUS_ACC_DENY 0x17 91#define ACPI_EC_SMB_STATUS_TIMEOUT 0x18 92#define ACPI_EC_SMB_STATUS_NOTSUP 0x19 93#define ACPI_EC_SMB_STATUS_BUSY 0x1A 94#define ACPI_EC_SMB_STATUS_PEC 0x1F 95 96#define ACPI_EC_SMB_PRTCL_WRITE 0x00 97#define ACPI_EC_SMB_PRTCL_READ 0x01 98#define ACPI_EC_SMB_PRTCL_QUICK 0x02 99#define ACPI_EC_SMB_PRTCL_BYTE 0x04 100#define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06 101#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08 102#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a 103#define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c 104#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d 105#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a 106#define ACPI_EC_SMB_PRTCL_PEC 0x80 107 108/* Length of pre/post transaction sleep (msec) */ 109#define ACPI_EC_SMB_TRANSACTION_SLEEP 1 110#define ACPI_EC_SMB_ACCESS_SLEEP1 1 111#define ACPI_EC_SMB_ACCESS_SLEEP2 10 112 113static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data) 114{ 115 u8 val; 116 int err; 117 118 err = ec_read(smbus->base + address, &val); 119 if (!err) { 120 *data = val; 121 } 122 xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP); 123 return (err); 124} 125 126static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data) 127{ 128 int err; 129 130 err = ec_write(smbus->base + address, data); 131 return (err); 132} 133 134static int 135acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, 136 char read_write, u8 command, int size, 137 union i2c_smbus_data *data) 138{ 139 struct acpi_ec_smbus *smbus = adap->algo_data; 140 unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 }; 141 int i; 142 143 if (read_write == I2C_SMBUS_READ) { 144 protocol = ACPI_EC_SMB_PRTCL_READ; 145 } else { 146 protocol = ACPI_EC_SMB_PRTCL_WRITE; 147 } 148 pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0; 149 150 switch (size) { 151 152 case I2C_SMBUS_QUICK: 153 protocol |= ACPI_EC_SMB_PRTCL_QUICK; 154 read_write = I2C_SMBUS_WRITE; 155 break; 156 157 case I2C_SMBUS_BYTE: 158 if (read_write == I2C_SMBUS_WRITE) { 159 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte); 160 } 161 protocol |= ACPI_EC_SMB_PRTCL_BYTE; 162 break; 163 164 case I2C_SMBUS_BYTE_DATA: 165 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 166 if (read_write == I2C_SMBUS_WRITE) { 167 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte); 168 } 169 protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA; 170 break; 171 172 case I2C_SMBUS_WORD_DATA: 173 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 174 if (read_write == I2C_SMBUS_WRITE) { 175 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word); 176 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, 177 data->word >> 8); 178 } 179 protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec; 180 break; 181 182 case I2C_SMBUS_BLOCK_DATA: 183 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 184 if (read_write == I2C_SMBUS_WRITE) { 185 len = min_t(u8, data->block[0], 32); 186 acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); 187 for (i = 0; i < len; i++) 188 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, 189 data->block[i + 1]); 190 } 191 protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec; 192 break; 193 194 case I2C_SMBUS_I2C_BLOCK_DATA: 195 len = min_t(u8, data->block[0], 32); 196 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 197 acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); 198 if (read_write == I2C_SMBUS_WRITE) { 199 for (i = 0; i < len; i++) { 200 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, 201 data->block[i + 1]); 202 } 203 } 204 protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA; 205 break; 206 207 case I2C_SMBUS_PROC_CALL: 208 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 209 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word); 210 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8); 211 protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec; 212 read_write = I2C_SMBUS_READ; 213 break; 214 215 case I2C_SMBUS_BLOCK_PROC_CALL: 216 protocol |= pec; 217 len = min_t(u8, data->block[0], 31); 218 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 219 acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); 220 for (i = 0; i < len; i++) 221 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, 222 data->block[i + 1]); 223 protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec; 224 read_write = I2C_SMBUS_READ; 225 break; 226 227 default: 228 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: " 229 "Unsupported transaction %d\n", size)); 230 return (-1); 231 } 232 233 acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1); 234 acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol); 235 236 acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); 237 238 if (~temp[0] & ACPI_EC_SMB_STS_DONE) { 239 xudelay(500); 240 acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); 241 } 242 if (~temp[0] & ACPI_EC_SMB_STS_DONE) { 243 xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2); 244 acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); 245 } 246 if ((~temp[0] & ACPI_EC_SMB_STS_DONE) 247 || (temp[0] & ACPI_EC_SMB_STS_STATUS)) { 248 return (-1); 249 } 250 251 if (read_write == I2C_SMBUS_WRITE) { 252 return (0); 253 } 254 255 switch (size) { 256 257 case I2C_SMBUS_BYTE: 258 case I2C_SMBUS_BYTE_DATA: 259 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte); 260 break; 261 262 case I2C_SMBUS_WORD_DATA: 263 case I2C_SMBUS_PROC_CALL: 264 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0); 265 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1); 266 data->word = (temp[1] << 8) | temp[0]; 267 break; 268 269 case I2C_SMBUS_BLOCK_DATA: 270 case I2C_SMBUS_BLOCK_PROC_CALL: 271 len = 0; 272 acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len); 273 len = min_t(u8, len, 32); 274 case I2C_SMBUS_I2C_BLOCK_DATA: 275 for (i = 0; i < len; i++) 276 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i, 277 data->block + i + 1); 278 data->block[0] = len; 279 break; 280 } 281 282 return (0); 283} 284 285static u32 acpi_ec_smb_func(struct i2c_adapter *adapter) 286{ 287 288 return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 289 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 290 I2C_FUNC_SMBUS_BLOCK_DATA | 291 I2C_FUNC_SMBUS_PROC_CALL | 292 I2C_FUNC_SMBUS_BLOCK_PROC_CALL | 293 I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC); 294} 295 296static struct i2c_algorithm acpi_ec_smbus_algorithm = { 297 .smbus_xfer = acpi_ec_smb_access, 298 .functionality = acpi_ec_smb_func, 299}; 300 301static int acpi_ec_hc_add(struct acpi_device *device) 302{ 303 int status; 304 unsigned long val; 305 struct acpi_ec_hc *ec_hc; 306 struct acpi_ec_smbus *smbus; 307 308 if (!device) { 309 return -EINVAL; 310 } 311 312 ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL); 313 if (!ec_hc) { 314 return -ENOMEM; 315 } 316 memset(ec_hc, 0, sizeof(struct acpi_ec_hc)); 317 318 smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL); 319 if (!smbus) { 320 kfree(ec_hc); 321 return -ENOMEM; 322 } 323 memset(smbus, 0, sizeof(struct acpi_ec_smbus)); 324 325 ec_hc->handle = device->handle; 326 strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME); 327 strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS); 328 acpi_driver_data(device) = ec_hc; 329 330 status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val); 331 if (ACPI_FAILURE(status)) { 332 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n")); 333 kfree(ec_hc->smbus); 334 kfree(smbus); 335 return -EIO; 336 } 337 338 smbus->ec = acpi_driver_data(device->parent); 339 smbus->base = (val & 0xff00ull) >> 8; 340 smbus->alert = val & 0xffull; 341 342 smbus->adapter.owner = THIS_MODULE; 343 smbus->adapter.algo = &acpi_ec_smbus_algorithm; 344 smbus->adapter.algo_data = smbus; 345 346 if (i2c_add_adapter(&smbus->adapter)) { 347 ACPI_DEBUG_PRINT((ACPI_DB_WARN, 348 "EC SMBus adapter: Failed to register adapter\n")); 349 kfree(smbus); 350 kfree(ec_hc); 351 return -EIO; 352 } 353 354 ec_hc->smbus = smbus; 355 356 printk(KERN_INFO PREFIX "%s [%s]\n", 357 acpi_device_name(device), acpi_device_bid(device)); 358 359 return AE_OK; 360} 361 362static int acpi_ec_hc_remove(struct acpi_device *device, int type) 363{ 364 struct acpi_ec_hc *ec_hc; 365 366 if (!device) { 367 return -EINVAL; 368 } 369 ec_hc = acpi_driver_data(device); 370 371 i2c_del_adapter(&ec_hc->smbus->adapter); 372 kfree(ec_hc->smbus); 373 kfree(ec_hc); 374 375 return AE_OK; 376} 377 378static int __init acpi_ec_hc_init(void) 379{ 380 int result; 381 382 result = acpi_bus_register_driver(&acpi_ec_hc_driver); 383 if (result < 0) { 384 return -ENODEV; 385 } 386 return 0; 387} 388 389static void __exit acpi_ec_hc_exit(void) 390{ 391 acpi_bus_unregister_driver(&acpi_ec_hc_driver); 392} 393 394struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device) 395{ 396 return ((struct acpi_ec_hc *)acpi_driver_data(device->parent)); 397} 398 399EXPORT_SYMBOL(acpi_get_ec_hc); 400 401module_init(acpi_ec_hc_init); 402module_exit(acpi_ec_hc_exit); 403 404MODULE_LICENSE("GPL"); 405MODULE_AUTHOR("Ducrot Bruno"); 406MODULE_DESCRIPTION("ACPI EC SMBus driver");