SPI驅動示例

lethe1203發表於2024-03-31

驅動目的:

從eeprom的0x2000地址開始讀出4096byte大小資料

驅動如下:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/debugfs.h>
#include <linux/string.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/kdev_t.h>
#include <linux/regmap.h>
#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <asm/segment.h>
#include <asm/uaccess.h>

struct eeprom_dev *eeprom;
static struct kobject   *eeprom_kobj;
struct eeprom_dev {
    struct regmap             *regmap;
    struct spi_device         *spi;
};

static ssize_t eeprom_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
{
    int rc = 0, i = 0, ret = 0;
    uint8_t txbuf[] = {0x02, 0x00, 0x00, 0x00};
    uint8_t *rxbuf;
    unsigned long level;
    struct file *file;
    
    rxbuf = kmalloc(sizeof(uint8_t)*4096, GFP_KERNEL);
    if (eeprom == NULL) {
        pr_err("%s: invalid eeproms device.\n", __func__);
        return -1;
    }
    rc = kstrtoul(buf, 10, &level);
    rc = spi_write_then_read(eeprom->spi, txbuf, 4, rxbuf, 4096);    // 發出地址給到eeprom

    file = filp_open("/data/eeprom/eeprom_flash.bin", O_RDWR | O_CREAT, 0777);
    i = IS_ERR(file);
    if (i){
        printk("create file error");
        printk("-----ERR===%d----",i);
        goto error;
    }

    ret = vfs_write(file, rxbuf, 4096, &pos);
    if (ret < 0){
        printk("write file error");
        printk("-----write_ERR===%d----",ret);
    }
    filp_close(file,NULL);
    kfree(rxbuf);
error:
    return len;
}
static DEVICE_ATTR(eeprom_pwr, 0666, NULL, eeprom_store);

static struct attribute *eeproms_attrs[] = {
    &dev_attr_eeprom_pwr.attr,
    NULL,
};

static struct attribute_group eeproms_attr_group = {
    .attrs = eeproms_attrs,
};
static int eeprom_probe(struct spi_device *spi)
{
    int rc = 0;
    eeprom = devm_kzalloc(&spi->dev, sizeof(struct eeprom_dev), GFP_KERNEL);
    if (IS_ERR(eeprom)) {
        pr_err("%s: can't alloc memery for eeproms device.\n", __func__);
        return -1;
    }

    dev_set_drvdata(&spi->dev, eeprom);
    eeprom->spi = spi;
    eeprom_kobj = kobject_create_and_add("eeprom_node", kernel_kobj);
    if (!eeprom_kobj) {
        dev_err(&spi->dev, "kobject eeproms ENOMEM\n");
    }

    rc = sysfs_create_group(eeprom_kobj, &eeproms_attr_group);
    if (rc) {
        pr_err("%s: sysfs create failed. rc = %d.\n", __func__, rc);
    }
    return rc;
}
static const struct of_device_id eeprom_match_table[] = {
    {
        .compatible = "eeprom,spi",
    },
    {},
};
static struct spi_driver eeprom_driver = {
    .driver = {
        .name = "eeprom_driver",
        .owner = THIS_MODULE,
        .of_match_table = eeprom_match_table,
    },
    .probe = eeprom_probe,
};
static int __init eeprom_init(void)
{
    pr_err("eeprom_init\n");
    return spi_register_driver(&eeprom_driver);
}
static void __exit eeprom_exit(void)
{
    pr_err("eeprom_exit\n");
    return spi_unregister_driver(&eeprom_driver);
}
module_init(eeprom_init);
module_exit(eeprom_exit);
MODULE_LICENSE("GPL v2");

相關文章