Re: [PATCH v6] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-10-14 Thread Max Schwarz
Hi Addy,

On Tuesday 14 October 2014 at 14:09:21, Addy Ke wrote:
> As show in I2C specification:
> - Standard-mode: the minimum HIGH period of the scl clock is 4.0us
>  the minimum LOW period of the scl clock is 4.7us
> - Fast-mode: the minimum HIGH period of the scl clock is 0.6us
>  the minimum LOW period of the scl clock is 1.3us
> 
> I have measured i2c SCL waveforms in fast-mode by oscilloscope
> on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
> It is so critical that we must adjust LOW division to increase
> the LOW period of the scl clock.
> 
> Thanks Doug for the suggestion about division formulas.
> 
> Tested-by: Heiko Stuebner 
> Reviewed-by: Doug Anderson 
> Tested-by: Doug Anderson 
> Signed-off-by: Addy Ke 

Reviewed-by: Max Schwarz 
Tested-by: Max Schwarz 

Cheers,
  Max
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH v2 3/3] i2c: show and change bus frequency via sysfs

2014-10-14 Thread Guenter Roeck
On Tue, Oct 14, 2014 at 05:48:14PM +0300, Octavian Purdila wrote:
> This patch adds three new sysfs files: bus_frequency,
> bus_min_frequency and bus_max_frequency which allows the user to view
> or change the bus frequency on a per bus level.
> 
> This is required for the case where multiple busses have the same
> adapter driver and where a module parameter does not allow controlling
> the bus speed individually (e.g. USB I2C adapters).
> 
> Signed-off-by: Octavian Purdila 
> ---
>  Documentation/ABI/testing/sysfs-bus-i2c | 30 +++
>  drivers/i2c/i2c-core.c  | 94 
> +
>  include/linux/i2c.h | 16 ++
>  3 files changed, 140 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-i2c 
> b/Documentation/ABI/testing/sysfs-bus-i2c
> index 8075585..4a7f8e7 100644
> --- a/Documentation/ABI/testing/sysfs-bus-i2c
> +++ b/Documentation/ABI/testing/sysfs-bus-i2c
> @@ -43,3 +43,33 @@ Contact:   linux-i2c@vger.kernel.org
>  Description:
>   An i2c device attached to bus X that is enumerated via
>   ACPI. Y is the ACPI device name and its format is "%s".
> +
> +What:/sys/bus/i2c/devices/i2c-X/bus_frequency
> +KernelVersion:   3.19
> +Contact: linux-i2c@vger.kernel.org
> +Description:
> + The current bus frequency for bus X. Can be updated if
> + the bus supports it. The unit is HZ and format is
> + "%d\n".
> + If the bus does not support changing the frequency
> + then this entry will be read-only.
> + If the bus does not support showing the frequency than
> + this entry will not be visible.
> + When updating the bus frequency that value must be in
> + the range defined by bus_frequency_min and
> + bus_frequency_max otherwise writing to this entry will
> + fail with -EINVAL.
> + The bus may not support all of the frequencies in the
> + min-max range and may round the frequency to the
> + closest supported one. The user must read the entry
> + after writing it to retrieve the actual set frequency.
> +
> +What:/sys/bus/i2c/devices/i2c-X/bus_min_frequency
> +What:/sys/bus/i2c/devices/i2c-X/bus_max_frequency
> +KernelVersion:   3.19
> +Contact: linux-i2c@vger.kernel.org
> +Description:
> + Minimum and maximum frequencies for bus X. The unit is
> + HZ and format is "%d\n".
> + If the bus does not support changing the frequency
> + these entries will not be visible.
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index 632057a..ab77f7f 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -940,15 +940,101 @@ static DEVICE_ATTR(new_device, S_IWUSR, NULL, 
> i2c_sysfs_new_device);
>  static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL,
>  i2c_sysfs_delete_device);
>  
> +static ssize_t
> +i2c_sysfs_freq_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct i2c_adapter *adap = to_i2c_adapter(dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", adap->freq);
> +}
> +
> +static ssize_t
> +i2c_sysfs_freq_store(struct device *dev, struct device_attribute *attr,
> +  const char *buf, size_t count)
> +{
> + struct i2c_adapter *adap = to_i2c_adapter(dev);
> + unsigned int freq;
> + int ret;
> +
> + if (kstrtouint(buf, 0, &freq) || freq < adap->min_freq ||
> + freq > adap->max_freq)
> + return -EINVAL;
> +
> + i2c_lock_adapter(adap);
> + ret = adap->set_freq(adap, &freq);
> + i2c_unlock_adapter(adap);
> +
> + if (ret)
> + return ret;
> +
> + adap->freq = freq;
> +
> + return count;
> +}
> +
> +static DEVICE_ATTR(bus_frequency, S_IRUGO, i2c_sysfs_freq_show,
> +i2c_sysfs_freq_store);

Consider using DEVICE_ATTR_RO here. Also, extra empty line.

> +
> +
> +static ssize_t
> +i2c_sysfs_min_freq_show(struct device *dev, struct device_attribute *attr,
> +   char *buf)
> +{
> + struct i2c_adapter *adap = to_i2c_adapter(dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", adap->min_freq);
> +}
> +
> +static DEVICE_ATTR(bus_min_frequency, S_IRUGO, i2c_sysfs_min_freq_show, 
> NULL);
> +

Consider using DEVICE_ATTR_RO.

> +static ssize_t
> +i2c_sysfs_max_freq_show(struct device *dev, struct device_attribute *attr,
> +   char *buf)
> +{
> + struct i2c_adapter *adap = to_i2c_adapter(dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", adap->max_freq);
> +}
> +
> +static DEVICE_ATTR(bus_max_frequency, S_IRUGO, i2c_sysfs_max_freq_show, 
> NULL);
> +
Consider using DEVICE_ATTR_RO.

Overall, it seems to me that the bus_ in front of the attrribute names
is really

[RFC PATCH v2 1/3] i2c: document the existing i2c sysfs ABI

2014-10-14 Thread Octavian Purdila
This patch adds Documentation/ABI/testing/sysfs-bus-i2c which
documents the existing i2c sysfs ABI.

Signed-off-by: Octavian Purdila 
---
 Documentation/ABI/testing/sysfs-bus-i2c | 45 +
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c

diff --git a/Documentation/ABI/testing/sysfs-bus-i2c 
b/Documentation/ABI/testing/sysfs-bus-i2c
new file mode 100644
index 000..8075585
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-i2c
@@ -0,0 +1,45 @@
+What:  /sys/bus/i2c/devices/i2c-X
+KernelVersion: since at least 2.6.12
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   This entry represents a registered i2c bus. X is the
+   bus number and its format is "%d".
+
+What:  /sys/bus/i2c/devices/i2c-X/Y
+What:  /sys/bus/i2c/devices/Y
+KernelVersion: since at least 2.6.12
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   An i2c device attached to bus X. Format of Y is
+   "%d-%04x" where the first number is the bus number (X)
+   and the second number is the device i2c address.
+
+What:  /sys/bus/i2c/devices/i2c-X/new_device
+KernelVersion: 2.6.31
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   Write only entry that allows instantiating a
+   new i2c device on bus X. This is to be used when
+   enumeration mechanism such as ACPI or DT are not
+   present or not used for this device.
+   Format: "%s %hi\n" where the first argument is the
+   device name (no spaces allowed) and the second is the
+   i2c address of the device.
+
+What:  /sys/bus/i2c/devices/i2c-X/delete_device
+KernelVersion: 2.6.31
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   Write only entry that allows the removal of an i2c
+   device from bus X.
+   Format: "%s %hi\n" where the first argument is the
+   device name (no spaces allowed) and the second is the
+   i2c address of the device.
+
+What:  /sys/bus/i2c/devices/i2c-X/i2c-Y
+What:  /sys/bus/i2c/devices/i2c-Y
+KernelVersion: 3.13
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   An i2c device attached to bus X that is enumerated via
+   ACPI. Y is the ACPI device name and its format is "%s".
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH v2 3/3] i2c: show and change bus frequency via sysfs

2014-10-14 Thread Octavian Purdila
This patch adds three new sysfs files: bus_frequency,
bus_min_frequency and bus_max_frequency which allows the user to view
or change the bus frequency on a per bus level.

This is required for the case where multiple busses have the same
adapter driver and where a module parameter does not allow controlling
the bus speed individually (e.g. USB I2C adapters).

Signed-off-by: Octavian Purdila 
---
 Documentation/ABI/testing/sysfs-bus-i2c | 30 +++
 drivers/i2c/i2c-core.c  | 94 +
 include/linux/i2c.h | 16 ++
 3 files changed, 140 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-i2c 
b/Documentation/ABI/testing/sysfs-bus-i2c
index 8075585..4a7f8e7 100644
--- a/Documentation/ABI/testing/sysfs-bus-i2c
+++ b/Documentation/ABI/testing/sysfs-bus-i2c
@@ -43,3 +43,33 @@ Contact: linux-i2c@vger.kernel.org
 Description:
An i2c device attached to bus X that is enumerated via
ACPI. Y is the ACPI device name and its format is "%s".
+
+What:  /sys/bus/i2c/devices/i2c-X/bus_frequency
+KernelVersion: 3.19
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   The current bus frequency for bus X. Can be updated if
+   the bus supports it. The unit is HZ and format is
+   "%d\n".
+   If the bus does not support changing the frequency
+   then this entry will be read-only.
+   If the bus does not support showing the frequency than
+   this entry will not be visible.
+   When updating the bus frequency that value must be in
+   the range defined by bus_frequency_min and
+   bus_frequency_max otherwise writing to this entry will
+   fail with -EINVAL.
+   The bus may not support all of the frequencies in the
+   min-max range and may round the frequency to the
+   closest supported one. The user must read the entry
+   after writing it to retrieve the actual set frequency.
+
+What:  /sys/bus/i2c/devices/i2c-X/bus_min_frequency
+What:  /sys/bus/i2c/devices/i2c-X/bus_max_frequency
+KernelVersion: 3.19
+Contact:   linux-i2c@vger.kernel.org
+Description:
+   Minimum and maximum frequencies for bus X. The unit is
+   HZ and format is "%d\n".
+   If the bus does not support changing the frequency
+   these entries will not be visible.
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 632057a..ab77f7f 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -940,15 +940,101 @@ static DEVICE_ATTR(new_device, S_IWUSR, NULL, 
i2c_sysfs_new_device);
 static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL,
   i2c_sysfs_delete_device);
 
+static ssize_t
+i2c_sysfs_freq_show(struct device *dev, struct device_attribute *attr,
+   char *buf)
+{
+   struct i2c_adapter *adap = to_i2c_adapter(dev);
+
+   return snprintf(buf, PAGE_SIZE, "%d\n", adap->freq);
+}
+
+static ssize_t
+i2c_sysfs_freq_store(struct device *dev, struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct i2c_adapter *adap = to_i2c_adapter(dev);
+   unsigned int freq;
+   int ret;
+
+   if (kstrtouint(buf, 0, &freq) || freq < adap->min_freq ||
+   freq > adap->max_freq)
+   return -EINVAL;
+
+   i2c_lock_adapter(adap);
+   ret = adap->set_freq(adap, &freq);
+   i2c_unlock_adapter(adap);
+
+   if (ret)
+   return ret;
+
+   adap->freq = freq;
+
+   return count;
+}
+
+static DEVICE_ATTR(bus_frequency, S_IRUGO, i2c_sysfs_freq_show,
+  i2c_sysfs_freq_store);
+
+
+static ssize_t
+i2c_sysfs_min_freq_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+   struct i2c_adapter *adap = to_i2c_adapter(dev);
+
+   return snprintf(buf, PAGE_SIZE, "%d\n", adap->min_freq);
+}
+
+static DEVICE_ATTR(bus_min_frequency, S_IRUGO, i2c_sysfs_min_freq_show, NULL);
+
+static ssize_t
+i2c_sysfs_max_freq_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+   struct i2c_adapter *adap = to_i2c_adapter(dev);
+
+   return snprintf(buf, PAGE_SIZE, "%d\n", adap->max_freq);
+}
+
+static DEVICE_ATTR(bus_max_frequency, S_IRUGO, i2c_sysfs_max_freq_show, NULL);
+
+umode_t i2c_adapter_visible_attr(struct kobject *kobj,
+struct attribute *attr, int idx)
+{
+   struct device *dev = container_of(kobj, struct device, kobj);
+   struct i2c_adapter *adap = to_i2c_adapter(dev);
+   umode_t mode = attr->mode;
+
+   if (attr == &dev_attr_bus_min_frequency.attr)
+   return adap->min_freq ? mode : 0;
+
+   if (attr == &dev_attr_bus_max_frequency.attr)
+ 

[RFC PATCH v2 2/3] i2c: document struct i2c_adapter

2014-10-14 Thread Octavian Purdila
Document the i2c_adapter fields that must be initialized before
calling i2c_add_adapter().

Signed-off-by: Octavian Purdila 
---
 include/linux/i2c.h | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index a95efeb..36041e2 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -418,9 +418,19 @@ int i2c_recover_bus(struct i2c_adapter *adap);
 int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
 int i2c_generic_scl_recovery(struct i2c_adapter *adap);
 
-/*
- * i2c_adapter is the structure used to identify a physical i2c bus along
- * with the access algorithms necessary to access it.
+/**
+ * struct i2c_adapter - represents an I2C physical bus
+ *
+ * The following members must be set by the adapter driver before
+ * calling i2c_add_adapter():
+ *
+ * @owner: the module owner, usually THIS_MODULE
+ * @class: bitmask of I2C_CLASS_*
+ * @algo: see struct i2c_algorithm
+ * @dev.parent: set this to the struct device of the driver (e.g. pci_dev->dev,
+ * usb->interface->dev, platform_device->dev etc.)
+ * @name: name of this i2c bus
+ * @bus_recovery_info: see struct i2c_bus_recovery_info. Optional.
  */
 struct i2c_adapter {
struct module *owner;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH v2 0/3] i2c: show and change bus frequency via sysfs

2014-10-14 Thread Octavian Purdila
This second version gets rid of the frequency table and introduces a
min and max range. It also changes the ABI to allow the driver to
round the given frequency to one that is supported, since many drivers
seems to work this way (i2c-stu300, i2c-s3c2410, i2c-kempld).

Octavian Purdila (3):
  i2c: document the existing i2c sysfs ABI
  i2c: document struct i2c_adapter
  i2c: show and change bus frequency via sysfs

 Documentation/ABI/testing/sysfs-bus-i2c | 75 ++
 drivers/i2c/i2c-core.c  | 94 +
 include/linux/i2c.h | 32 +--
 3 files changed, 198 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] misc: eeprom: add driver for Cypress FRAM

2014-10-14 Thread Jiri Prchal
This patch adds driver for Cypress FRAMs on SPI bus, such as FM25V05, FM25V10
etc.
Reworked from at25 driver:
- simplified writing since data are written without erasing and waiting to
finish write cycle
- add reading device ID and choose size and addr len from it
- add serial number reading and exporting it to sysfs

Signed-off-by: Jiri Prchal 
---
v2: changed upon Varka Bhadram coments

 drivers/misc/eeprom/Kconfig  |  11 +
 drivers/misc/eeprom/Makefile |   1 +
 drivers/misc/eeprom/fm25.c   | 499 +++
 3 files changed, 511 insertions(+)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..aee6a73 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -38,6 +38,17 @@ config EEPROM_AT25
  This driver can also be built as a module.  If so, the module
  will be called at25.

+config FRAM_FM25
+   tristate "SPI Cypress FRAM"
+   depends on SPI && SYSFS
+   help
+ Enable this driver to get read/write support to SPI FRAMs,
+ after you configure the board init code to know about each fram
+ on your target board.
+
+ This driver can also be built as a module.  If so, the module
+ will be called fm25.
+
 config EEPROM_LEGACY
tristate "Old I2C EEPROM reader"
depends on I2C && SYSFS
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..6738752 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_EEPROM_AT24)  += at24.o
 obj-$(CONFIG_EEPROM_AT25)  += at25.o
+obj-$(CONFIG_FRAM_FM25)+= fm25.o
 obj-$(CONFIG_EEPROM_LEGACY)+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)   += max6875.o
 obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/eeprom/fm25.c b/drivers/misc/eeprom/fm25.c
new file mode 100644
index 000..c30c523
--- /dev/null
+++ b/drivers/misc/eeprom/fm25.c
@@ -0,0 +1,499 @@
+/*
+ * fm25.c -- support SPI FRAMs, such as Cypress FM25 models
+ *
+ * Copyright (C) 2014 Jiri Prchal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+struct fm25_data {
+   struct spi_device   *spi;
+   struct memory_accessor  mem;
+   struct mutexlock;
+   struct spi_eeprom   chip;
+   struct bin_attributebin;
+   unsignedaddrlen;
+   int has_sernum;
+};
+
+#defineFM25_WREN   0x06/* latch the write enable */
+#defineFM25_WRDI   0x04/* reset the write enable */
+#defineFM25_RDSR   0x05/* read status register */
+#defineFM25_WRSR   0x01/* write status register */
+#defineFM25_READ   0x03/* read byte(s) */
+#defineFM25_WRITE  0x02/* write byte(s)/sector */
+#defineFM25_SLEEP  0xb9/* enter sleep mode */
+#defineFM25_RDID   0x9f/* read device ID */
+#defineFM25_RDSN   0xc3/* read S/N */
+
+#defineFM25_SR_WEN 0x02/* write enable (latched) */
+#defineFM25_SR_BP0 0x04/* BP for software writeprotect 
*/
+#defineFM25_SR_BP1 0x08
+#defineFM25_SR_WPEN0x80/* writeprotect enable */
+
+#defineFM25_ID_LEN 9   /* ID lenght */
+#defineFM25_SN_LEN 8   /* serial number lenght */
+
+#defineFM25_MAXADDRLEN 3   /* 24 bit addresses */
+
+#defineio_limitPAGE_SIZE   /* bytes */
+
+static ssize_t
+fm25_data_read(
+   struct fm25_data*fm25,
+   char*buf,
+   unsignedoffset,
+   size_t  count
+)
+{
+   u8  command[FM25_MAXADDRLEN + 1];
+   u8  *cp;
+   ssize_t status;
+   struct spi_transfer t[2];
+   struct spi_message  m;
+   u8  instr;
+
+   if (unlikely(offset >= fm25->bin.size))
+   return 0;
+   if ((offset + count) > fm25->bin.size)
+   count = fm25->bin.size - offset;
+   if (unlikely(!count))
+   return count;
+
+   cp = command;
+
+   instr = FM25_READ;
+   *cp++ = instr;
+
+   /* 8/16/24-bit address is written MSB first */
+   switch (fm25->addrlen) {
+   default:/* case 3 */
+   *cp++ = offset >> 16;
+   case 2:
+   *cp++ = offset >> 8;
+   case 1:
+   case 

Re: [PATCH] misc: eeprom: add driver for Cypress FRAM

2014-10-14 Thread Varka Bhadram

On 10/14/2014 02:53 PM, Jiri Prchal wrote:

This patch adds driver for Cypress FRAMs on SPI bus, such as FM25V05, FM25V10
etc.
Reworked from at25 driver:
- simplified writing since data are written without erasing and waiting to
finish write cycle
- add reading device ID and choose size and addr len from it
- add serial number reading and exporting it to sysfs


(...)


+static int fm25_probe(struct spi_device *spi)
+{
+   struct fm25_data*fm25 = NULL;
+   struct spi_eeprom   chip;
+   struct device_node  *np = spi->dev.of_node;
+   int err;
+   charid[FM25_ID_LEN];
+
+   /* Chip description */
+   if (!spi->dev.platform_data) {
+   if (np) {
+   err = fm25_np_to_chip(&spi->dev, np, &chip);
+   if (err)
+   return err;
+   } else {
+   dev_err(&spi->dev, "Error: no chip description\n");
+   return -ENODEV;
+   }
+   } else
+   chip = *(struct spi_eeprom *)spi->dev.platform_data;
+
+   fm25 = devm_kzalloc(&spi->dev, sizeof(struct fm25_data), GFP_KERNEL);
+   if (!fm25)
+   return -ENOMEM;


sizeof(*fm25)..?


+
+   mutex_init(&fm25->lock);
+   fm25->chip = chip;
+   fm25->spi = spi_dev_get(spi);
+   spi_set_drvdata(spi, fm25);
+
+   /* Get ID of chip */
+   fm25_id_read(fm25, id);
+   if (id[6] != 0xc2) {
+   dev_err(&spi->dev, "Error: no Cypress FRAM (id %02x)\n", id[6]);
+   return -ENODEV;
+   }
+   /* set size found in ID */
+   switch (id[7]) {
+   case 0x21:
+   fm25->chip.byte_len = 16 * 1024;
+   break;
+   case 0x22:
+   fm25->chip.byte_len = 32 * 1024;
+   break;
+   case 0x23:
+   fm25->chip.byte_len = 64 * 1024;
+   break;
+   case 0x24:
+   fm25->chip.byte_len = 128 * 1024;
+   break;
+   case 0x25:
+   fm25->chip.byte_len = 256 * 1024;
+   break;
+   default:
+   dev_err(&spi->dev,
+   "Error: unsupported size (id %02x)\n", id[7]);
+   return -ENODEV;
+   break;
+   }


The preferred way of using 
switchhttp://lxr.free-electrons.com/source/Documentation/CodingStyle#L38


+
+   if (fm25->chip.byte_len > 64 * 1024) {
+   fm25->addrlen = 3;
+   fm25->chip.flags |= EE_ADDR3;
+   }
+   else {
+   fm25->addrlen = 2;
+   fm25->chip.flags |= EE_ADDR2;
+   }
+
+   if (id[8])
+   fm25->has_sernum = 1;
+   else
+   fm25->has_sernum = 0;
+
+   /* Export the EEPROM bytes through sysfs, since that's convenient.
+* And maybe to other kernel code; it might hold a board's Ethernet
+* address, or board-specific calibration data generated on the
+* manufacturing floor.
+*
+* Default to root-only access to the data; EEPROMs often hold data
+* that's sensitive for read and/or write, like ethernet addresses,
+* security codes, board-specific manufacturing calibrations, etc.
+*/
+   sysfs_bin_attr_init(&fm25->bin);
+   fm25->bin.attr.name = "fram";
+   fm25->bin.attr.mode = S_IRUGO;
+   fm25->bin.read = fm25_bin_read;
+   fm25->mem.read = fm25_mem_read;
+
+   fm25->bin.size = fm25->chip.byte_len;
+   if (!(chip.flags & EE_READONLY)) {
+   fm25->bin.write = fm25_bin_write;
+   fm25->bin.attr.mode |= S_IWUSR | S_IWGRP;
+   fm25->mem.write = fm25_mem_write;
+   }
+
+   err = sysfs_create_bin_file(&spi->dev.kobj, &fm25->bin);
+   if (err)
+   return err;
+
+   /* Export the FM25 serial number */
+   if (fm25->has_sernum) {
+   err = device_create_file(&spi->dev, &dev_attr_sernum);
+   if (err)
+   return err;
+   }
+
+   if (chip.setup)
+   chip.setup(&fm25->mem, chip.context);
+
+   dev_info(&spi->dev, "%Zd %s %s fram%s\n",
+   (fm25->bin.size < 1024)
+   ? fm25->bin.size
+   : (fm25->bin.size / 1024),
+   (fm25->bin.size < 1024) ? "Byte" : "KByte",
+   fm25->chip.name,
+   (chip.flags & EE_READONLY) ? " (readonly)" : "");
+   return 0;
+}
+
+static int fm25_remove(struct spi_device *spi)
+{
+   struct fm25_data*fm25;
+
+   fm25 = spi_get_drvdata(spi);


Both statements can be combine.

struct fm25_datd *fm25 = spi_get_drvdata(spi);


+   sysfs_remove_bin_file(&spi->dev.kobj, &fm25->bin);
+   if (fm25->h

[PATCH] misc: eeprom: add driver for Cypress FRAM

2014-10-14 Thread Jiri Prchal
This patch adds driver for Cypress FRAMs on SPI bus, such as FM25V05, FM25V10
etc.
Reworked from at25 driver:
- simplified writing since data are written without erasing and waiting to
finish write cycle
- add reading device ID and choose size and addr len from it
- add serial number reading and exporting it to sysfs

Signed-off-by: Jiri Prchal 
---
 drivers/misc/eeprom/Kconfig  |  11 +
 drivers/misc/eeprom/Makefile |   1 +
 drivers/misc/eeprom/fm25.c   | 500 +++
 3 files changed, 512 insertions(+)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..aee6a73 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -38,6 +38,17 @@ config EEPROM_AT25
  This driver can also be built as a module.  If so, the module
  will be called at25.
 
+config FRAM_FM25
+   tristate "SPI Cypress FRAM"
+   depends on SPI && SYSFS
+   help
+ Enable this driver to get read/write support to SPI FRAMs,
+ after you configure the board init code to know about each fram
+ on your target board.
+
+ This driver can also be built as a module.  If so, the module
+ will be called fm25.
+
 config EEPROM_LEGACY
tristate "Old I2C EEPROM reader"
depends on I2C && SYSFS
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..6738752 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_EEPROM_AT24)  += at24.o
 obj-$(CONFIG_EEPROM_AT25)  += at25.o
+obj-$(CONFIG_FRAM_FM25)+= fm25.o
 obj-$(CONFIG_EEPROM_LEGACY)+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)   += max6875.o
 obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/eeprom/fm25.c b/drivers/misc/eeprom/fm25.c
new file mode 100644
index 000..6a33b4d
--- /dev/null
+++ b/drivers/misc/eeprom/fm25.c
@@ -0,0 +1,500 @@
+/*
+ * fm25.c -- support SPI FRAMs, such as Cypress FM25 models
+ *
+ * Copyright (C) 2014 Jiri Prchal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+struct fm25_data {
+   struct spi_device   *spi;
+   struct memory_accessor  mem;
+   struct mutexlock;
+   struct spi_eeprom   chip;
+   struct bin_attributebin;
+   unsignedaddrlen;
+   int has_sernum;
+};
+
+#defineFM25_WREN   0x06/* latch the write enable */
+#defineFM25_WRDI   0x04/* reset the write enable */
+#defineFM25_RDSR   0x05/* read status register */
+#defineFM25_WRSR   0x01/* write status register */
+#defineFM25_READ   0x03/* read byte(s) */
+#defineFM25_WRITE  0x02/* write byte(s)/sector */
+#defineFM25_SLEEP  0xb9/* enter sleep mode */
+#defineFM25_RDID   0x9f/* read device ID */
+#defineFM25_RDSN   0xc3/* read S/N */
+
+#defineFM25_SR_WEN 0x02/* write enable (latched) */
+#defineFM25_SR_BP0 0x04/* BP for software writeprotect 
*/
+#defineFM25_SR_BP1 0x08
+#defineFM25_SR_WPEN0x80/* writeprotect enable */
+
+#define FM25_ID_LEN9   /* ID lenght */
+#define FM25_SN_LEN8   /* serial number lenght */
+
+#define FM25_MAXADDRLEN3   /* 24 bit addresses */
+
+#defineio_limitPAGE_SIZE   /* bytes */
+
+static ssize_t
+fm25_data_read(
+   struct fm25_data*fm25,
+   char*buf,
+   unsignedoffset,
+   size_t  count
+)
+{
+   u8  command[FM25_MAXADDRLEN + 1];
+   u8  *cp;
+   ssize_t status;
+   struct spi_transfer t[2];
+   struct spi_message  m;
+   u8  instr;
+
+   if (unlikely(offset >= fm25->bin.size))
+   return 0;
+   if ((offset + count) > fm25->bin.size)
+   count = fm25->bin.size - offset;
+   if (unlikely(!count))
+   return count;
+
+   cp = command;
+
+   instr = FM25_READ;
+   *cp++ = instr;
+
+   /* 8/16/24-bit address is written MSB first */
+   switch (fm25->addrlen) {
+   default:/* case 3 */
+   *cp++ = offset >> 16;
+   case 2:
+   *cp++ = offset >> 8;
+   case 1:
+   case 0: /* can't happen: for better codegen */
+

Re: [RFC PATCH 3/3] i2c: show and change bus frequency via sysfs

2014-10-14 Thread Octavian Purdila
On Tue, Oct 14, 2014 at 4:53 AM, Mark Roszko  wrote:
>
> > If this limitations exists
> >they are not introduced by this patch. This patch just exposes the
> >frequency so that it can be read or changed in userspace.
>
> Ah, well right now you can have an i2c bus with driver 1 and 2. Say
> the i2c bus is configured for 60khz in kernel space which normally
> can't be changed. Driver 1 talks to a slave that cannot go above
> 100khz. Now the userspace interface is added to the i2c bus. Some
> userspace application decides to reconfigure the bus for 400khz and do
> its communication to some slave device. Now the kernel tries to do
> some background talking to the drive 1 slave and suddenly finds it can
> no longer communicate with it. Right now with the kernel space only
> configuration, the system is safe from being messed up easily. It's
> more of a sanity of configuration issue.

You need privileges to change the bus frequency, so this is a
configuration issue. Which you still have today, since can still set
the i2c frequency on some busses via a module parameter.

>
>
> >On a different not, I have noticed that a fixed set of frequencies
> >might not be the best API, since multiple drivers rather support a
> >rather large set of frequencies in a range. A better API might be to
> >expose a min-max range and let the bus driver adjust the requested
> >frequency. I will follow up with a second version that does that.
>
> I was actually thinking you could eliminate the table of supported
> frequencies and just have the bus driver handle the set frequency
> decision itself and just return an error code if it's invalid. There
> are legitiamate drivers that cannot do more than a list of frequencies
> already as well. One example is here:
> http://lxr.free-electrons.com/source/drivers/i2c/busses/i2c-bcm-kona.c#L717

Yes, I will do that for v2 and in addition I will also add min and max
attributes to make it easier to determine if a bus supports fast mode,
fast plus, high, etc.
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html