e05ce444e9
Provide a read function reading the otp zone. The otp zone can be used for storing serial numbers. The otp zone, as also data zone, are only accessible if the chip was locked before. Locking the chip is a post production customization and has to be done manually i.e. not by this driver. Without this step the chip is pretty much not usable, where putting or not putting data into the otp zone is optional. Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
193 lines
6.1 KiB
C
193 lines
6.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2017, Microchip Technology Inc.
|
|
* Author: Tudor Ambarus
|
|
*/
|
|
|
|
#ifndef __ATMEL_I2C_H__
|
|
#define __ATMEL_I2C_H__
|
|
|
|
#include <linux/hw_random.h>
|
|
#include <linux/types.h>
|
|
|
|
#define ATMEL_ECC_PRIORITY 300
|
|
|
|
#define COMMAND 0x03 /* packet function */
|
|
#define SLEEP_TOKEN 0x01
|
|
#define WAKE_TOKEN_MAX_SIZE 8
|
|
|
|
/* Definitions of Data and Command sizes */
|
|
#define WORD_ADDR_SIZE 1
|
|
#define COUNT_SIZE 1
|
|
#define CRC_SIZE 2
|
|
#define CMD_OVERHEAD_SIZE (COUNT_SIZE + CRC_SIZE)
|
|
|
|
/* size in bytes of the n prime */
|
|
#define ATMEL_ECC_NIST_P256_N_SIZE 32
|
|
#define ATMEL_ECC_PUBKEY_SIZE (2 * ATMEL_ECC_NIST_P256_N_SIZE)
|
|
|
|
#define STATUS_RSP_SIZE 4
|
|
#define ECDH_RSP_SIZE (32 + CMD_OVERHEAD_SIZE)
|
|
#define GENKEY_RSP_SIZE (ATMEL_ECC_PUBKEY_SIZE + \
|
|
CMD_OVERHEAD_SIZE)
|
|
#define READ_RSP_SIZE (4 + CMD_OVERHEAD_SIZE)
|
|
#define RANDOM_RSP_SIZE (32 + CMD_OVERHEAD_SIZE)
|
|
#define MAX_RSP_SIZE GENKEY_RSP_SIZE
|
|
|
|
/**
|
|
* atmel_i2c_cmd - structure used for communicating with the device.
|
|
* @word_addr: indicates the function of the packet sent to the device. This
|
|
* byte should have a value of COMMAND for normal operation.
|
|
* @count : number of bytes to be transferred to (or from) the device.
|
|
* @opcode : the command code.
|
|
* @param1 : the first parameter; always present.
|
|
* @param2 : the second parameter; always present.
|
|
* @data : optional remaining input data. Includes a 2-byte CRC.
|
|
* @rxsize : size of the data received from i2c client.
|
|
* @msecs : command execution time in milliseconds
|
|
*/
|
|
struct atmel_i2c_cmd {
|
|
u8 word_addr;
|
|
u8 count;
|
|
u8 opcode;
|
|
u8 param1;
|
|
__le16 param2;
|
|
u8 data[MAX_RSP_SIZE];
|
|
u8 msecs;
|
|
u16 rxsize;
|
|
} __packed;
|
|
|
|
/* Status/Error codes */
|
|
#define STATUS_SIZE 0x04
|
|
#define STATUS_NOERR 0x00
|
|
#define STATUS_WAKE_SUCCESSFUL 0x11
|
|
|
|
/* Definitions for eeprom organization */
|
|
#define CONFIGURATION_ZONE 0
|
|
#define OTP_ZONE 1
|
|
|
|
/* Definitions for eeprom zone sizes */
|
|
#define OTP_ZONE_SIZE 64
|
|
|
|
/* Definitions for Indexes common to all commands */
|
|
#define RSP_DATA_IDX 1 /* buffer index of data in response */
|
|
#define DATA_SLOT_2 2 /* used for ECDH private key */
|
|
|
|
/* Definitions for the device lock state */
|
|
#define DEVICE_LOCK_ADDR 0x15
|
|
#define LOCK_VALUE_IDX (RSP_DATA_IDX + 2)
|
|
#define LOCK_CONFIG_IDX (RSP_DATA_IDX + 3)
|
|
|
|
/*
|
|
* Wake High delay to data communication (microseconds). SDA should be stable
|
|
* high for this entire duration.
|
|
*/
|
|
#define TWHI_MIN 1500
|
|
#define TWHI_MAX 1550
|
|
|
|
/* Wake Low duration */
|
|
#define TWLO_USEC 60
|
|
|
|
/* Command execution time (milliseconds) */
|
|
#define MAX_EXEC_TIME_ECDH 58
|
|
#define MAX_EXEC_TIME_GENKEY 115
|
|
#define MAX_EXEC_TIME_READ 1
|
|
#define MAX_EXEC_TIME_RANDOM 50
|
|
|
|
/* Command opcode */
|
|
#define OPCODE_ECDH 0x43
|
|
#define OPCODE_GENKEY 0x40
|
|
#define OPCODE_READ 0x02
|
|
#define OPCODE_RANDOM 0x1b
|
|
|
|
/* Definitions for the READ Command */
|
|
#define READ_COUNT 7
|
|
|
|
/* Definitions for the RANDOM Command */
|
|
#define RANDOM_COUNT 7
|
|
|
|
/* Definitions for the GenKey Command */
|
|
#define GENKEY_COUNT 7
|
|
#define GENKEY_MODE_PRIVATE 0x04
|
|
|
|
/* Definitions for the ECDH Command */
|
|
#define ECDH_COUNT 71
|
|
#define ECDH_PREFIX_MODE 0x00
|
|
|
|
/* Used for binding tfm objects to i2c clients. */
|
|
struct atmel_ecc_driver_data {
|
|
struct list_head i2c_client_list;
|
|
spinlock_t i2c_list_lock;
|
|
} ____cacheline_aligned;
|
|
|
|
/**
|
|
* atmel_i2c_client_priv - i2c_client private data
|
|
* @client : pointer to i2c client device
|
|
* @i2c_client_list_node: part of i2c_client_list
|
|
* @lock : lock for sending i2c commands
|
|
* @wake_token : wake token array of zeros
|
|
* @wake_token_sz : size in bytes of the wake_token
|
|
* @tfm_count : number of active crypto transformations on i2c client
|
|
* @hwrng : hold the hardware generated rng
|
|
*
|
|
* Reads and writes from/to the i2c client are sequential. The first byte
|
|
* transmitted to the device is treated as the byte size. Any attempt to send
|
|
* more than this number of bytes will cause the device to not ACK those bytes.
|
|
* After the host writes a single command byte to the input buffer, reads are
|
|
* prohibited until after the device completes command execution. Use a mutex
|
|
* when sending i2c commands.
|
|
*/
|
|
struct atmel_i2c_client_priv {
|
|
struct i2c_client *client;
|
|
struct list_head i2c_client_list_node;
|
|
struct mutex lock;
|
|
u8 wake_token[WAKE_TOKEN_MAX_SIZE];
|
|
size_t wake_token_sz;
|
|
atomic_t tfm_count ____cacheline_aligned;
|
|
struct hwrng hwrng;
|
|
};
|
|
|
|
/**
|
|
* atmel_i2c_work_data - data structure representing the work
|
|
* @ctx : transformation context.
|
|
* @cbk : pointer to a callback function to be invoked upon completion of this
|
|
* request. This has the form:
|
|
* callback(struct atmel_i2c_work_data *work_data, void *areq, u8 status)
|
|
* where:
|
|
* @work_data: data structure representing the work
|
|
* @areq : optional pointer to an argument passed with the original
|
|
* request.
|
|
* @status : status returned from the i2c client device or i2c error.
|
|
* @areq: optional pointer to a user argument for use at callback time.
|
|
* @work: describes the task to be executed.
|
|
* @cmd : structure used for communicating with the device.
|
|
*/
|
|
struct atmel_i2c_work_data {
|
|
void *ctx;
|
|
struct i2c_client *client;
|
|
void (*cbk)(struct atmel_i2c_work_data *work_data, void *areq,
|
|
int status);
|
|
void *areq;
|
|
struct work_struct work;
|
|
struct atmel_i2c_cmd cmd;
|
|
};
|
|
|
|
int atmel_i2c_probe(struct i2c_client *client);
|
|
|
|
void atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data,
|
|
void (*cbk)(struct atmel_i2c_work_data *work_data,
|
|
void *areq, int status),
|
|
void *areq);
|
|
void atmel_i2c_flush_queue(void);
|
|
|
|
int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd *cmd);
|
|
|
|
void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd);
|
|
int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr);
|
|
void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd);
|
|
void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid);
|
|
int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
|
|
struct scatterlist *pubkey);
|
|
|
|
#endif /* __ATMEL_I2C_H__ */
|