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;
+       char                    id[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->has_sernum)
+               device_remove_file(&spi->dev, &dev_attr_sernum);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct of_device_id fm25_of_match[] = {
+       { .compatible = "cypress,fm25", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, fm25_of_match);
+
+static struct spi_driver fm25_driver = {
+       .driver = {
+               .name           = "fm25",
+               .owner          = THIS_MODULE,

Can remove this filed. It will populate by module_spi_driver().

+               .of_match_table = fm25_of_match,
+       },
+       .probe          = fm25_probe,
+       .remove         = fm25_remove,
+};
+
+module_spi_driver(fm25_driver);
+
+MODULE_DESCRIPTION("Driver for Cypress SPI FRAMs");
+MODULE_AUTHOR("Jiri Prchal");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:fram");

--
Regards,
Varka Bhadram.

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

Reply via email to