0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "ACPI: " fmt
0009
0010 #include <linux/acpi.h>
0011 #include <linux/wait.h>
0012 #include <linux/slab.h>
0013 #include <linux/delay.h>
0014 #include <linux/module.h>
0015 #include <linux/interrupt.h>
0016 #include "sbshc.h"
0017
0018 #define ACPI_SMB_HC_CLASS "smbus_host_ctl"
0019 #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"
0020
0021 struct acpi_smb_hc {
0022 struct acpi_ec *ec;
0023 struct mutex lock;
0024 wait_queue_head_t wait;
0025 u8 offset;
0026 u8 query_bit;
0027 smbus_alarm_callback callback;
0028 void *context;
0029 bool done;
0030 };
0031
0032 static int acpi_smbus_hc_add(struct acpi_device *device);
0033 static int acpi_smbus_hc_remove(struct acpi_device *device);
0034
0035 static const struct acpi_device_id sbs_device_ids[] = {
0036 {"ACPI0001", 0},
0037 {"ACPI0005", 0},
0038 {"", 0},
0039 };
0040
0041 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
0042
0043 static struct acpi_driver acpi_smb_hc_driver = {
0044 .name = "smbus_hc",
0045 .class = ACPI_SMB_HC_CLASS,
0046 .ids = sbs_device_ids,
0047 .ops = {
0048 .add = acpi_smbus_hc_add,
0049 .remove = acpi_smbus_hc_remove,
0050 },
0051 };
0052
0053 union acpi_smb_status {
0054 u8 raw;
0055 struct {
0056 u8 status:5;
0057 u8 reserved:1;
0058 u8 alarm:1;
0059 u8 done:1;
0060 } fields;
0061 };
0062
0063 enum acpi_smb_status_codes {
0064 SMBUS_OK = 0,
0065 SMBUS_UNKNOWN_FAILURE = 0x07,
0066 SMBUS_DEVICE_ADDRESS_NACK = 0x10,
0067 SMBUS_DEVICE_ERROR = 0x11,
0068 SMBUS_DEVICE_COMMAND_ACCESS_DENIED = 0x12,
0069 SMBUS_UNKNOWN_ERROR = 0x13,
0070 SMBUS_DEVICE_ACCESS_DENIED = 0x17,
0071 SMBUS_TIMEOUT = 0x18,
0072 SMBUS_HOST_UNSUPPORTED_PROTOCOL = 0x19,
0073 SMBUS_BUSY = 0x1a,
0074 SMBUS_PEC_ERROR = 0x1f,
0075 };
0076
0077 enum acpi_smb_offset {
0078 ACPI_SMB_PROTOCOL = 0,
0079 ACPI_SMB_STATUS = 1,
0080 ACPI_SMB_ADDRESS = 2,
0081 ACPI_SMB_COMMAND = 3,
0082 ACPI_SMB_DATA = 4,
0083 ACPI_SMB_BLOCK_COUNT = 0x24,
0084 ACPI_SMB_ALARM_ADDRESS = 0x25,
0085 ACPI_SMB_ALARM_DATA = 0x26,
0086 };
0087
0088 static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
0089 {
0090 return ec_read(hc->offset + address, data);
0091 }
0092
0093 static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data)
0094 {
0095 return ec_write(hc->offset + address, data);
0096 }
0097
0098 static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
0099 {
0100 if (wait_event_timeout(hc->wait, hc->done, msecs_to_jiffies(timeout)))
0101 return 0;
0102 return -ETIME;
0103 }
0104
0105 static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
0106 u8 address, u8 command, u8 *data, u8 length)
0107 {
0108 int ret = -EFAULT, i;
0109 u8 temp, sz = 0;
0110
0111 if (!hc) {
0112 pr_err("host controller is not configured\n");
0113 return ret;
0114 }
0115
0116 mutex_lock(&hc->lock);
0117 hc->done = false;
0118 if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
0119 goto end;
0120 if (temp) {
0121 ret = -EBUSY;
0122 goto end;
0123 }
0124 smb_hc_write(hc, ACPI_SMB_COMMAND, command);
0125 if (!(protocol & 0x01)) {
0126 smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length);
0127 for (i = 0; i < length; ++i)
0128 smb_hc_write(hc, ACPI_SMB_DATA + i, data[i]);
0129 }
0130 smb_hc_write(hc, ACPI_SMB_ADDRESS, address << 1);
0131 smb_hc_write(hc, ACPI_SMB_PROTOCOL, protocol);
0132
0133
0134
0135
0136 ret = wait_transaction_complete(hc, 1000);
0137 if (ret || !(protocol & 0x01))
0138 goto end;
0139 switch (protocol) {
0140 case SMBUS_RECEIVE_BYTE:
0141 case SMBUS_READ_BYTE:
0142 sz = 1;
0143 break;
0144 case SMBUS_READ_WORD:
0145 sz = 2;
0146 break;
0147 case SMBUS_READ_BLOCK:
0148 if (smb_hc_read(hc, ACPI_SMB_BLOCK_COUNT, &sz)) {
0149 ret = -EFAULT;
0150 goto end;
0151 }
0152 sz &= 0x1f;
0153 break;
0154 }
0155 for (i = 0; i < sz; ++i)
0156 smb_hc_read(hc, ACPI_SMB_DATA + i, &data[i]);
0157 end:
0158 mutex_unlock(&hc->lock);
0159 return ret;
0160 }
0161
0162 int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
0163 u8 command, u8 *data)
0164 {
0165 return acpi_smbus_transaction(hc, protocol, address, command, data, 0);
0166 }
0167
0168 EXPORT_SYMBOL_GPL(acpi_smbus_read);
0169
0170 int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 address,
0171 u8 command, u8 *data, u8 length)
0172 {
0173 return acpi_smbus_transaction(hc, protocol, address, command, data, length);
0174 }
0175
0176 EXPORT_SYMBOL_GPL(acpi_smbus_write);
0177
0178 int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
0179 smbus_alarm_callback callback, void *context)
0180 {
0181 mutex_lock(&hc->lock);
0182 hc->callback = callback;
0183 hc->context = context;
0184 mutex_unlock(&hc->lock);
0185 return 0;
0186 }
0187
0188 EXPORT_SYMBOL_GPL(acpi_smbus_register_callback);
0189
0190 int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc)
0191 {
0192 mutex_lock(&hc->lock);
0193 hc->callback = NULL;
0194 hc->context = NULL;
0195 mutex_unlock(&hc->lock);
0196 acpi_os_wait_events_complete();
0197 return 0;
0198 }
0199
0200 EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback);
0201
0202 static inline void acpi_smbus_callback(void *context)
0203 {
0204 struct acpi_smb_hc *hc = context;
0205 if (hc->callback)
0206 hc->callback(hc->context);
0207 }
0208
0209 static int smbus_alarm(void *context)
0210 {
0211 struct acpi_smb_hc *hc = context;
0212 union acpi_smb_status status;
0213 u8 address;
0214 if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
0215 return 0;
0216
0217 if (status.fields.done && status.fields.status == SMBUS_OK) {
0218 hc->done = true;
0219 wake_up(&hc->wait);
0220 }
0221 if (!status.fields.alarm)
0222 return 0;
0223 mutex_lock(&hc->lock);
0224 smb_hc_read(hc, ACPI_SMB_ALARM_ADDRESS, &address);
0225 status.fields.alarm = 0;
0226 smb_hc_write(hc, ACPI_SMB_STATUS, status.raw);
0227
0228 switch (address >> 1) {
0229 case ACPI_SBS_CHARGER:
0230 case ACPI_SBS_MANAGER:
0231 case ACPI_SBS_BATTERY:
0232 acpi_os_execute(OSL_NOTIFY_HANDLER,
0233 acpi_smbus_callback, hc);
0234 }
0235 mutex_unlock(&hc->lock);
0236 return 0;
0237 }
0238
0239 typedef int (*acpi_ec_query_func) (void *data);
0240
0241 extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
0242 acpi_handle handle, acpi_ec_query_func func,
0243 void *data);
0244
0245 static int acpi_smbus_hc_add(struct acpi_device *device)
0246 {
0247 int status;
0248 unsigned long long val;
0249 struct acpi_smb_hc *hc;
0250
0251 if (!device)
0252 return -EINVAL;
0253
0254 status = acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
0255 if (ACPI_FAILURE(status)) {
0256 pr_err("error obtaining _EC.\n");
0257 return -EIO;
0258 }
0259
0260 strcpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME);
0261 strcpy(acpi_device_class(device), ACPI_SMB_HC_CLASS);
0262
0263 hc = kzalloc(sizeof(struct acpi_smb_hc), GFP_KERNEL);
0264 if (!hc)
0265 return -ENOMEM;
0266 mutex_init(&hc->lock);
0267 init_waitqueue_head(&hc->wait);
0268
0269 hc->ec = acpi_driver_data(device->parent);
0270 hc->offset = (val >> 8) & 0xff;
0271 hc->query_bit = val & 0xff;
0272 device->driver_data = hc;
0273
0274 acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
0275 dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n",
0276 hc->offset, hc->query_bit);
0277
0278 return 0;
0279 }
0280
0281 extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
0282
0283 static int acpi_smbus_hc_remove(struct acpi_device *device)
0284 {
0285 struct acpi_smb_hc *hc;
0286
0287 if (!device)
0288 return -EINVAL;
0289
0290 hc = acpi_driver_data(device);
0291 acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
0292 acpi_os_wait_events_complete();
0293 kfree(hc);
0294 device->driver_data = NULL;
0295 return 0;
0296 }
0297
0298 module_acpi_driver(acpi_smb_hc_driver);
0299
0300 MODULE_LICENSE("GPL");
0301 MODULE_AUTHOR("Alexey Starikovskiy");
0302 MODULE_DESCRIPTION("ACPI SMBus HC driver");