From patchwork Sun May 29 21:53:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 68805 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp1113532qge; Sun, 29 May 2016 14:56:15 -0700 (PDT) X-Received: by 10.66.249.74 with SMTP id ys10mr40815568pac.16.1464558974979; Sun, 29 May 2016 14:56:14 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w6si45798854pac.26.2016.05.29.14.56.14; Sun, 29 May 2016 14:56:14 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932728AbcE2V4K (ORCPT + 30 others); Sun, 29 May 2016 17:56:10 -0400 Received: from mail-wm0-f50.google.com ([74.125.82.50]:35487 "EHLO mail-wm0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932592AbcE2VyZ (ORCPT ); Sun, 29 May 2016 17:54:25 -0400 Received: by mail-wm0-f50.google.com with SMTP id a136so61562447wme.0 for ; Sun, 29 May 2016 14:54:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nCzAO+k5SurZ54+MhHXiDs/1AJGd8RVIsJl81P3hzKs=; b=rDyNVA0tyZ0JCxIJ9HVcL/UbCopWwpuCh6HXvsgz9Ca3sPZRvh+HXod9jUhHvXL7c9 4IOK2/fJ1uwEo0UtCVGW5GGDeVTCH56StZ4q8nDSqgiWjdy1Bu7cnl7/WqdAChMvN2ZF YXJSyConOkMPSl9m3ULg9ohWhutyppMWrsUonhhkXBhVeY5xke9tEZ7cw7qG1ewOA9HP JdeWrHuAXono2KM4w7zHuqTLN+8uF7bBZVPoIdJTBJV/OraVMgg5ltYRYH3lfV4T9MFK r5XE2wD4b7HltAu5iRuGmgncgaozxbqFAY0dDg+otJf7SwrE1MzGWKyaWgJCs+g3xhdg LAqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nCzAO+k5SurZ54+MhHXiDs/1AJGd8RVIsJl81P3hzKs=; b=YvVI2mGhC8UIRDxUfxBg05HX6p/BHg3wR7iPUU7AZPXyDy+LP56ZXRhNLVH/KOWRIl tfWF2NbCTSv7oyk1fN9ZMnJgXXI3vLQgmamdAL9d+5BZXjuehBkRLHLnD3fFblfh1HP0 HWcJPWBtwqiyj5PoL/GCk+B+2cXbJqRAo9474qXD27LhrsPe3zHT7UvILAjydwxvV3Dq gBvVv9T+2cbbPuojucM/shtOnRM0tQk04Xt1VhyGtdrm5gSJ2yiA6rI8/q2HOuLnckb7 Iy1JlnZZaRxOgKYEJBjQbTCOf0GvK6ZcWIeq/0fBAtpLm+Ef5SzZ4OLMDTCCgugfmp5Y yiTw== X-Gm-Message-State: ALyK8tL8PLbsKgvzcgetLdUzhYRm2FKE+t9pJBqJUQyHMvUezhfedfVC8r9Efl1MrnWWPq9V X-Received: by 10.28.29.200 with SMTP id d191mr4740412wmd.91.1464558863509; Sun, 29 May 2016 14:54:23 -0700 (PDT) Received: from bgdev-debian.lan (jua06-1-82-242-157-225.fbx.proxad.net. [82.242.157.225]) by smtp.gmail.com with ESMTPSA id a128sm20490367wme.16.2016.05.29.14.54.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 29 May 2016 14:54:23 -0700 (PDT) From: Bartosz Golaszewski To: Wolfram Sang , linux-i2c , LKML , Andrew Lunn , Srinivas Kandagatla , Maxime Ripard , GregKH Cc: Bartosz Golaszewski Subject: [PATCH 10/14] eeprom: at24: support reading the serial number Date: Sun, 29 May 2016 23:53:48 +0200 Message-Id: <1464558832-2262-11-git-send-email-bgolaszewski@baylibre.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464558832-2262-1-git-send-email-bgolaszewski@baylibre.com> References: <1464558832-2262-1-git-send-email-bgolaszewski@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The at24cs series EEPROM chips have an additional read-only memory area containing a factory pre-programmed serial number. In order to access it, one has to perform a dummy write before reading the serial number bytes. Add a function that allows to access the serial number and assign it to at24->read_func if the chip allows serial number read operations and the driver was passed the relevant flag for this device. Signed-off-by: Bartosz Golaszewski --- drivers/misc/eeprom/at24.c | 62 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) -- 2.7.4 diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 6acf35a..29bbdad 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -276,6 +276,59 @@ static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf, return -ETIMEDOUT; } +static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + struct i2c_msg msg[2]; + u8 addrbuf[2]; + int status; + + client = at24_translate_offset(at24, &offset); + + memset(msg, 0, sizeof(msg)); + msg[0].addr = client->addr; + msg[0].buf = addrbuf; + + /* + * The address pointer of the device is shared between the regular + * EEPROM array and the serial number block. The dummy write (part of + * the sequential read protocol) ensures the address pointer is reset + * to the desired position. + */ + if (at24->chip.flags & AT24_FLAG_ADDR16) { + /* + * For 16 bit address pointers, the word address must contain + * a '10' sequence in bits 11 and 10 regardless of the + * intended position of the address pointer. + */ + addrbuf[0] = 0x08; + addrbuf[1] = offset; + msg[0].len = 2; + } else { + /* + * Otherwise the word address must begin with a '10' sequence, + * regardless of the intended address. + */ + addrbuf[0] = 0x80 + offset; + msg[0].len = 1; + } + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + loop_until_timeout(timeout, read_time) { + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + return count; + } + + return -ETIMEDOUT; +} + /* * Note that if the hardware write-protect pin is pulled high, the whole * chip is normally write protected. But there are plenty of product @@ -577,8 +630,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) at24->chip = chip; at24->num_addresses = num_addresses; - at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus - : at24_eeprom_read_i2c; + if (chip.flags & AT24_FLAG_SERIAL) { + at24->read_func = at24_eeprom_read_serial; + } else { + at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus + : at24_eeprom_read_i2c; + } + if (at24->use_smbus) { if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA) at24->write_func = at24_eeprom_write_smbus_block;