162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Microchip / Atmel ECC (I2C) driver. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2017, Microchip Technology Inc. 662306a36Sopenharmony_ci * Author: Tudor Ambarus 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/bitrev.h> 1062306a36Sopenharmony_ci#include <linux/crc16.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/device.h> 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/errno.h> 1562306a36Sopenharmony_ci#include <linux/i2c.h> 1662306a36Sopenharmony_ci#include <linux/init.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/scatterlist.h> 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci#include <linux/workqueue.h> 2262306a36Sopenharmony_ci#include "atmel-i2c.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic const struct { 2562306a36Sopenharmony_ci u8 value; 2662306a36Sopenharmony_ci const char *error_text; 2762306a36Sopenharmony_ci} error_list[] = { 2862306a36Sopenharmony_ci { 0x01, "CheckMac or Verify miscompare" }, 2962306a36Sopenharmony_ci { 0x03, "Parse Error" }, 3062306a36Sopenharmony_ci { 0x05, "ECC Fault" }, 3162306a36Sopenharmony_ci { 0x0F, "Execution Error" }, 3262306a36Sopenharmony_ci { 0xEE, "Watchdog about to expire" }, 3362306a36Sopenharmony_ci { 0xFF, "CRC or other communication error" }, 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/** 3762306a36Sopenharmony_ci * atmel_i2c_checksum() - Generate 16-bit CRC as required by ATMEL ECC. 3862306a36Sopenharmony_ci * CRC16 verification of the count, opcode, param1, param2 and data bytes. 3962306a36Sopenharmony_ci * The checksum is saved in little-endian format in the least significant 4062306a36Sopenharmony_ci * two bytes of the command. CRC polynomial is 0x8005 and the initial register 4162306a36Sopenharmony_ci * value should be zero. 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * @cmd : structure used for communicating with the device. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_cistatic void atmel_i2c_checksum(struct atmel_i2c_cmd *cmd) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci u8 *data = &cmd->count; 4862306a36Sopenharmony_ci size_t len = cmd->count - CRC_SIZE; 4962306a36Sopenharmony_ci __le16 *__crc16 = (__le16 *)(data + len); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci *__crc16 = cpu_to_le16(bitrev16(crc16(0, data, len))); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_civoid atmel_i2c_init_read_cmd(struct atmel_i2c_cmd *cmd) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci cmd->word_addr = COMMAND; 5762306a36Sopenharmony_ci cmd->opcode = OPCODE_READ; 5862306a36Sopenharmony_ci /* 5962306a36Sopenharmony_ci * Read the word from Configuration zone that contains the lock bytes 6062306a36Sopenharmony_ci * (UserExtra, Selector, LockValue, LockConfig). 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci cmd->param1 = CONFIGURATION_ZONE; 6362306a36Sopenharmony_ci cmd->param2 = cpu_to_le16(DEVICE_LOCK_ADDR); 6462306a36Sopenharmony_ci cmd->count = READ_COUNT; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci atmel_i2c_checksum(cmd); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci cmd->msecs = MAX_EXEC_TIME_READ; 6962306a36Sopenharmony_ci cmd->rxsize = READ_RSP_SIZE; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_init_read_cmd); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_civoid atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci cmd->word_addr = COMMAND; 7662306a36Sopenharmony_ci cmd->opcode = OPCODE_RANDOM; 7762306a36Sopenharmony_ci cmd->param1 = 0; 7862306a36Sopenharmony_ci cmd->param2 = 0; 7962306a36Sopenharmony_ci cmd->count = RANDOM_COUNT; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci atmel_i2c_checksum(cmd); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci cmd->msecs = MAX_EXEC_TIME_RANDOM; 8462306a36Sopenharmony_ci cmd->rxsize = RANDOM_RSP_SIZE; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_init_random_cmd); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_civoid atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci cmd->word_addr = COMMAND; 9162306a36Sopenharmony_ci cmd->count = GENKEY_COUNT; 9262306a36Sopenharmony_ci cmd->opcode = OPCODE_GENKEY; 9362306a36Sopenharmony_ci cmd->param1 = GENKEY_MODE_PRIVATE; 9462306a36Sopenharmony_ci /* a random private key will be generated and stored in slot keyID */ 9562306a36Sopenharmony_ci cmd->param2 = cpu_to_le16(keyid); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci atmel_i2c_checksum(cmd); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci cmd->msecs = MAX_EXEC_TIME_GENKEY; 10062306a36Sopenharmony_ci cmd->rxsize = GENKEY_RSP_SIZE; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_init_genkey_cmd); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciint atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, 10562306a36Sopenharmony_ci struct scatterlist *pubkey) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci size_t copied; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci cmd->word_addr = COMMAND; 11062306a36Sopenharmony_ci cmd->count = ECDH_COUNT; 11162306a36Sopenharmony_ci cmd->opcode = OPCODE_ECDH; 11262306a36Sopenharmony_ci cmd->param1 = ECDH_PREFIX_MODE; 11362306a36Sopenharmony_ci /* private key slot */ 11462306a36Sopenharmony_ci cmd->param2 = cpu_to_le16(DATA_SLOT_2); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* 11762306a36Sopenharmony_ci * The device only supports NIST P256 ECC keys. The public key size will 11862306a36Sopenharmony_ci * always be the same. Use a macro for the key size to avoid unnecessary 11962306a36Sopenharmony_ci * computations. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci copied = sg_copy_to_buffer(pubkey, 12262306a36Sopenharmony_ci sg_nents_for_len(pubkey, 12362306a36Sopenharmony_ci ATMEL_ECC_PUBKEY_SIZE), 12462306a36Sopenharmony_ci cmd->data, ATMEL_ECC_PUBKEY_SIZE); 12562306a36Sopenharmony_ci if (copied != ATMEL_ECC_PUBKEY_SIZE) 12662306a36Sopenharmony_ci return -EINVAL; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci atmel_i2c_checksum(cmd); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci cmd->msecs = MAX_EXEC_TIME_ECDH; 13162306a36Sopenharmony_ci cmd->rxsize = ECDH_RSP_SIZE; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_init_ecdh_cmd); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* 13862306a36Sopenharmony_ci * After wake and after execution of a command, there will be error, status, or 13962306a36Sopenharmony_ci * result bytes in the device's output register that can be retrieved by the 14062306a36Sopenharmony_ci * system. When the length of that group is four bytes, the codes returned are 14162306a36Sopenharmony_ci * detailed in error_list. 14262306a36Sopenharmony_ci */ 14362306a36Sopenharmony_cistatic int atmel_i2c_status(struct device *dev, u8 *status) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci size_t err_list_len = ARRAY_SIZE(error_list); 14662306a36Sopenharmony_ci int i; 14762306a36Sopenharmony_ci u8 err_id = status[1]; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci if (*status != STATUS_SIZE) 15062306a36Sopenharmony_ci return 0; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if (err_id == STATUS_WAKE_SUCCESSFUL || err_id == STATUS_NOERR) 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci for (i = 0; i < err_list_len; i++) 15662306a36Sopenharmony_ci if (error_list[i].value == err_id) 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* if err_id is not in the error_list then ignore it */ 16062306a36Sopenharmony_ci if (i != err_list_len) { 16162306a36Sopenharmony_ci dev_err(dev, "%02x: %s:\n", err_id, error_list[i].error_text); 16262306a36Sopenharmony_ci return err_id; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci return 0; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int atmel_i2c_wakeup(struct i2c_client *client) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); 17162306a36Sopenharmony_ci u8 status[STATUS_RSP_SIZE]; 17262306a36Sopenharmony_ci int ret; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* 17562306a36Sopenharmony_ci * The device ignores any levels or transitions on the SCL pin when the 17662306a36Sopenharmony_ci * device is idle, asleep or during waking up. Don't check for error 17762306a36Sopenharmony_ci * when waking up the device. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_ci i2c_transfer_buffer_flags(client, i2c_priv->wake_token, 18062306a36Sopenharmony_ci i2c_priv->wake_token_sz, I2C_M_IGNORE_NAK); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* 18362306a36Sopenharmony_ci * Wait to wake the device. Typical execution times for ecdh and genkey 18462306a36Sopenharmony_ci * are around tens of milliseconds. Delta is chosen to 50 microseconds. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci usleep_range(TWHI_MIN, TWHI_MAX); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci ret = i2c_master_recv(client, status, STATUS_SIZE); 18962306a36Sopenharmony_ci if (ret < 0) 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci return atmel_i2c_status(&client->dev, status); 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic int atmel_i2c_sleep(struct i2c_client *client) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci u8 sleep = SLEEP_TOKEN; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return i2c_master_send(client, &sleep, 1); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* 20362306a36Sopenharmony_ci * atmel_i2c_send_receive() - send a command to the device and receive its 20462306a36Sopenharmony_ci * response. 20562306a36Sopenharmony_ci * @client: i2c client device 20662306a36Sopenharmony_ci * @cmd : structure used to communicate with the device 20762306a36Sopenharmony_ci * 20862306a36Sopenharmony_ci * After the device receives a Wake token, a watchdog counter starts within the 20962306a36Sopenharmony_ci * device. After the watchdog timer expires, the device enters sleep mode 21062306a36Sopenharmony_ci * regardless of whether some I/O transmission or command execution is in 21162306a36Sopenharmony_ci * progress. If a command is attempted when insufficient time remains prior to 21262306a36Sopenharmony_ci * watchdog timer execution, the device will return the watchdog timeout error 21362306a36Sopenharmony_ci * code without attempting to execute the command. There is no way to reset the 21462306a36Sopenharmony_ci * counter other than to put the device into sleep or idle mode and then 21562306a36Sopenharmony_ci * wake it up again. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ciint atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd *cmd) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); 22062306a36Sopenharmony_ci int ret; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci mutex_lock(&i2c_priv->lock); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci ret = atmel_i2c_wakeup(client); 22562306a36Sopenharmony_ci if (ret) 22662306a36Sopenharmony_ci goto err; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci /* send the command */ 22962306a36Sopenharmony_ci ret = i2c_master_send(client, (u8 *)cmd, cmd->count + WORD_ADDR_SIZE); 23062306a36Sopenharmony_ci if (ret < 0) 23162306a36Sopenharmony_ci goto err; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* delay the appropriate amount of time for command to execute */ 23462306a36Sopenharmony_ci msleep(cmd->msecs); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* receive the response */ 23762306a36Sopenharmony_ci ret = i2c_master_recv(client, cmd->data, cmd->rxsize); 23862306a36Sopenharmony_ci if (ret < 0) 23962306a36Sopenharmony_ci goto err; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /* put the device into low-power mode */ 24262306a36Sopenharmony_ci ret = atmel_i2c_sleep(client); 24362306a36Sopenharmony_ci if (ret < 0) 24462306a36Sopenharmony_ci goto err; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci mutex_unlock(&i2c_priv->lock); 24762306a36Sopenharmony_ci return atmel_i2c_status(&client->dev, cmd->data); 24862306a36Sopenharmony_cierr: 24962306a36Sopenharmony_ci mutex_unlock(&i2c_priv->lock); 25062306a36Sopenharmony_ci return ret; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_send_receive); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic void atmel_i2c_work_handler(struct work_struct *work) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct atmel_i2c_work_data *work_data = 25762306a36Sopenharmony_ci container_of(work, struct atmel_i2c_work_data, work); 25862306a36Sopenharmony_ci struct atmel_i2c_cmd *cmd = &work_data->cmd; 25962306a36Sopenharmony_ci struct i2c_client *client = work_data->client; 26062306a36Sopenharmony_ci int status; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci status = atmel_i2c_send_receive(client, cmd); 26362306a36Sopenharmony_ci work_data->cbk(work_data, work_data->areq, status); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic struct workqueue_struct *atmel_wq; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_civoid atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data, 26962306a36Sopenharmony_ci void (*cbk)(struct atmel_i2c_work_data *work_data, 27062306a36Sopenharmony_ci void *areq, int status), 27162306a36Sopenharmony_ci void *areq) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci work_data->cbk = (void *)cbk; 27462306a36Sopenharmony_ci work_data->areq = areq; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci INIT_WORK(&work_data->work, atmel_i2c_work_handler); 27762306a36Sopenharmony_ci queue_work(atmel_wq, &work_data->work); 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_enqueue); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_civoid atmel_i2c_flush_queue(void) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci flush_workqueue(atmel_wq); 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_flush_queue); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic inline size_t atmel_i2c_wake_token_sz(u32 bus_clk_rate) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci u32 no_of_bits = DIV_ROUND_UP(TWLO_USEC * bus_clk_rate, USEC_PER_SEC); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* return the size of the wake_token in bytes */ 29262306a36Sopenharmony_ci return DIV_ROUND_UP(no_of_bits, 8); 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int device_sanity_check(struct i2c_client *client) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci struct atmel_i2c_cmd *cmd; 29862306a36Sopenharmony_ci int ret; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); 30162306a36Sopenharmony_ci if (!cmd) 30262306a36Sopenharmony_ci return -ENOMEM; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci atmel_i2c_init_read_cmd(cmd); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci ret = atmel_i2c_send_receive(client, cmd); 30762306a36Sopenharmony_ci if (ret) 30862306a36Sopenharmony_ci goto free_cmd; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* 31162306a36Sopenharmony_ci * It is vital that the Configuration, Data and OTP zones be locked 31262306a36Sopenharmony_ci * prior to release into the field of the system containing the device. 31362306a36Sopenharmony_ci * Failure to lock these zones may permit modification of any secret 31462306a36Sopenharmony_ci * keys and may lead to other security problems. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci if (cmd->data[LOCK_CONFIG_IDX] || cmd->data[LOCK_VALUE_IDX]) { 31762306a36Sopenharmony_ci dev_err(&client->dev, "Configuration or Data and OTP zones are unlocked!\n"); 31862306a36Sopenharmony_ci ret = -ENOTSUPP; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* fall through */ 32262306a36Sopenharmony_cifree_cmd: 32362306a36Sopenharmony_ci kfree(cmd); 32462306a36Sopenharmony_ci return ret; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ciint atmel_i2c_probe(struct i2c_client *client) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci struct atmel_i2c_client_priv *i2c_priv; 33062306a36Sopenharmony_ci struct device *dev = &client->dev; 33162306a36Sopenharmony_ci int ret; 33262306a36Sopenharmony_ci u32 bus_clk_rate; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 33562306a36Sopenharmony_ci dev_err(dev, "I2C_FUNC_I2C not supported\n"); 33662306a36Sopenharmony_ci return -ENODEV; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci bus_clk_rate = i2c_acpi_find_bus_speed(&client->adapter->dev); 34062306a36Sopenharmony_ci if (!bus_clk_rate) { 34162306a36Sopenharmony_ci ret = device_property_read_u32(&client->adapter->dev, 34262306a36Sopenharmony_ci "clock-frequency", &bus_clk_rate); 34362306a36Sopenharmony_ci if (ret) { 34462306a36Sopenharmony_ci dev_err(dev, "failed to read clock-frequency property\n"); 34562306a36Sopenharmony_ci return ret; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (bus_clk_rate > 1000000L) { 35062306a36Sopenharmony_ci dev_err(dev, "%u exceeds maximum supported clock frequency (1MHz)\n", 35162306a36Sopenharmony_ci bus_clk_rate); 35262306a36Sopenharmony_ci return -EINVAL; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci i2c_priv = devm_kmalloc(dev, sizeof(*i2c_priv), GFP_KERNEL); 35662306a36Sopenharmony_ci if (!i2c_priv) 35762306a36Sopenharmony_ci return -ENOMEM; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci i2c_priv->client = client; 36062306a36Sopenharmony_ci mutex_init(&i2c_priv->lock); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* 36362306a36Sopenharmony_ci * WAKE_TOKEN_MAX_SIZE was calculated for the maximum bus_clk_rate - 36462306a36Sopenharmony_ci * 1MHz. The previous bus_clk_rate check ensures us that wake_token_sz 36562306a36Sopenharmony_ci * will always be smaller than or equal to WAKE_TOKEN_MAX_SIZE. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ci i2c_priv->wake_token_sz = atmel_i2c_wake_token_sz(bus_clk_rate); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci memset(i2c_priv->wake_token, 0, sizeof(i2c_priv->wake_token)); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci atomic_set(&i2c_priv->tfm_count, 0); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci i2c_set_clientdata(client, i2c_priv); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci return device_sanity_check(client); 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ciEXPORT_SYMBOL(atmel_i2c_probe); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic int __init atmel_i2c_init(void) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci atmel_wq = alloc_workqueue("atmel_wq", 0, 0); 38262306a36Sopenharmony_ci return atmel_wq ? 0 : -ENOMEM; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic void __exit atmel_i2c_exit(void) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci destroy_workqueue(atmel_wq); 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cimodule_init(atmel_i2c_init); 39162306a36Sopenharmony_cimodule_exit(atmel_i2c_exit); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ciMODULE_AUTHOR("Tudor Ambarus"); 39462306a36Sopenharmony_ciMODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver"); 39562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 396