C6333

Posted 码农编程录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C6333相关的知识,希望对你有一定的参考价值。

mc24lc64t.c

/*================================================================
 *   Copyright (C) 2020,Huaqin Technology Co.,Ltd.
 *                 All rights reserved.
 *   Building 10, No, 399, Keyuan Road, Pudong, Shanghai
 *
 *
 *   File Name   : mc24lc64t.c
 *   Author      : carl.wang (carl.wang@huaqin.com)
 *   Created Time: Thu Dec 14 16:12:51 2020
 *   Description : mc24lc64t.c -- the driver for Microchip 24LC64T.
 *   Copyright (C) 2020 Huaqin Corp.
 *
 *   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 0 of the License, Or (at
 *   your option) any later version.      eeprom驱动
 *
 ================================================================*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/jiffies.h>

#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes.

struct mc24lc64t_data 
    struct mutex update_lock;
;

static ssize_t mc24lc64t_read(
    struct file *filp,
    struct kobject *kobj,
    struct bin_attribute *bin_attr,
    char *buf,
    loff_t off,
    size_t count)

    struct i2c_client *client = kobj_to_i2c_client(kobj);
    struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
    size_t timeout, read_time, i = 0;
    int32_t status;

    if (drvdata == NULL)
        return -ENODEV;

    if (i2c_smbus_write_byte_data(client, off >> 8, off)) 
        status = -EIO;
        goto exit;
    
    msleep(1);

    mutex_lock(&drvdata->update_lock);

begin:
    if (i < count) 
        timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
        do 
            read_time = jiffies;
            status = i2c_smbus_read_byte(client);
            if (status >= 0) 
                buf[i++] = status;
                goto begin;
            
         while (time_before(read_time, timeout));
        status = -ETIMEDOUT;
        goto exit;
    
    status = count;
exit:

    mutex_unlock(&drvdata->update_lock);
    return status;


static ssize_t mc24lc64t_write(
    struct file *filp,
    struct kobject *kobj,
    struct bin_attribute *bin_attr,
    char *buf,
    loff_t off,
    size_t count)

    struct i2c_client *client = kobj_to_i2c_client(kobj);
    struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
    size_t timeout, write_time, i = 0;
    int32_t status;
    u16 value;

    if (drvdata == NULL)
        return -ENODEV;

    mutex_lock(&drvdata->update_lock);

begin:
    if (i < count) 
        timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
        value = (buf[i] << 8 | (off & 0xff));
        do 
            write_time = jiffies;
            status = i2c_smbus_write_word_data(client, off >> 8, value);
            if (status == 0) 
                /* increase offset */
                off++;
                /* increase buffer index */
                i++;
                goto begin;
            
         while (time_before(write_time, timeout));
        status = -ETIMEDOUT;
        goto exit;
    
    status = count;

exit:

    mutex_unlock(&drvdata->update_lock);
    return status;


static struct bin_attribute mc24lc64t_bit_attr =    //eeprom节点,/sys/bus/i2c-1
    .attr = 
        .name = "eeprom",
        .mode = S_IRUGO | S_IWUGO,
    ,
    .size = EEPROM_SIZE,
    .read = mc24lc64t_read,
    .write = mc24lc64t_write,
;

static int32_t mc24lc64t_probe(struct i2c_client *client, const struct i2c_device_id *id)

    struct i2c_adapter *adapter = client->adapter;
    struct mc24lc64t_data *drvdata;
    int32_t err;

    if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_READ_BYTE))
        return -EPFNOSUPPORT;

    if (!(drvdata = devm_kzalloc(&client->dev, sizeof(struct mc24lc64t_data), GFP_KERNEL)))
        return -ENOMEM;

    i2c_set_clientdata(client, drvdata);
    mutex_init(&drvdata->update_lock);

    err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
    return err;


static int32_t mc24lc64t_remove(struct i2c_client *client)

    sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
    return 0;


static const struct i2c_device_id mc24lc64t_id[] = "24lc64t", 0, ;
MODULE_DEVICE_TABLE(i2c, mc24lc64t_id);

static struct i2c_driver mc24lc64t_driver = 
    .driver = 
        .name = "mc24lc64t",  //wusuowei
        .owner = THIS_MODULE,
    ,
    .probe = mc24lc64t_probe,
    .remove = mc24lc64t_remove,
    .id_table = mc24lc64t_id,
;

module_i2c_driver(mc24lc64t_driver);

MODULE_AUTHOR("Huaqin Technology Co.,Ltd.");
MODULE_DESCRIPTION("Hua Qin 24LC64T Driver");
MODULE_VERSION("0.0.1");
MODULE_LICENSE("GPL");

i2c-ocores.h

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * i2c-ocores.h - definitions for the i2c-ocores interface
 *
 * Peter Korsgaard <peter@korsgaard.com>
 */

#ifndef _LINUX_I2C_OCORES_H
#define _LINUX_I2C_OCORES_H

struct ocores_i2c_platform_data 
    uint32_t reg_shift;                   /* register offset shift value */
    uint32_t reg_io_width;                /* register io read/write width */
    uint32_t clock_khz;                   /* input clock in kHz */
    uint32_t bus_khz;                     /* bus clock in kHz */
    bool big_endian;                      /* registers are big endian */
    uint8_t num_devices;                  /* number of devices in the devices list */
    struct i2c_board_info const *devices; /* devices connected to the bus */
;

#endif /* _LINUX_I2C_OCORES_H */

i2c-ocores.c

// SPDX-License-Identifier: GPL-2.0
/*
 * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
 * (https://opencores.org/project/i2c/overview)
 *
 * Peter Korsgaard <peter@korsgaard.com>
 *
 * Support for the GRLIB port of the controller by
 * Andreas Larsson <andreas@gaisler.com>    节点:i2c-1,控制器属性
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
//#include <linux/platform_data/i2c-ocores.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include "i2c-ocores.h"

#define OCORES_FLAG_POLL BIT(0)

/*
 * 'process_lock' exists because ocores_process() and ocores_process_timeout()
 * can't run in parallel.
 */
struct ocores_i2c 
    void __iomem *base;
    int32_t iobase;
    uint32_t reg_shift;
    uint32_t reg_io_width;
    size_t flags;
    wait_queue_head_t wait;
    struct i2c_adapter adap;
    struct i2c_msg *msg;
    int32_t pos;
    int32_t nmsgs;
    int32_t state; /* see STATE_ */
    int32_t nack_retry;
    spinlock_t process_lock;
    struct clk *clk;
    int32_t ip_clock_khz;
    int32_t bus_clock_khz;
    void (*setreg)(struct ocores_i2c *i2c, int32_t reg, uint8_t value);
    uint8_t (*getreg)(struct ocores_i2c *i2c, int32_t reg);
;

/* registers */
#define OCI2C_PRELOW        0
#define OCI2C_PREHIGH       1
#define OCI2C_CONTROL       2
#define OCI2C_DATA          3
#define OCI2C_CMD           4 /* write only */
#define OCI2C_STATUS        4 /* read only, same address as OCI2C_CMD */

#define OCI2C_CTRL_IEN      0x40
#define OCI2C_CTRL_EN       0x80

#define OCI2C_CMD_START     0x91
#define OCI2C_CMD_STOP      0x41
#define OCI2C_CMD_READ      0x21
#define OCI2C_CMD_WRITE     0x11
#define OCI2C_CMD_READ_ACK  0x21
#define OCI2C_CMD_READ_NACK 0x29
#define OCI2C_CMD_IACK      0x01

#define OCI2C_STAT_IF       0x01
#define OCI2C_STAT_TIP      0x02
#define OCI2C_STAT_ARBLOST  0x20
#define OCI2C_STAT_BUSY     0x40
#define OCI2C_STAT_NACK     0x80

#define STATE_DONE          0
#define STATE_START         1
#define STATE_WRITE         2
#define STATE_READ          3
#define STATE_ERROR         4

#define TYPE_OCORES         0
#define TYPE_GRLIB          1
#define I2C_CTRL            0x8
#define I2C_CMD_STA0        0x10

#define PORT_XCVR_REGISTER_SIZE 0x3e0

static void oc_setreg_8(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    iowrite8(value, i2c->base + (reg << i2c->reg_shift));


static void oc_setreg_16(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    iowrite16(value, i2c->base + (reg << i2c->reg_shift));


static void oc_setreg_32(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    iowrite32(value, i2c->base + (reg << i2c->reg_shift));


static void oc_setreg_16be(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    iowrite16be(value, i2c->base + (reg << i2c->reg_shift));


static void oc_setreg_32be(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    iowrite32be(value, i2c->base + (reg << i2c->reg_shift));


static inline uint8_t oc_getreg_8(struct ocores_i2c *i2c, int32_t reg)

    return ioread8(i2c->base + (reg << i2c->reg_shift));


static inline uint8_t oc_getreg_16(struct ocores_i2c *i2c, int32_t reg)

    return ioread16(i2c->base + (reg << i2c->reg_shift));


static inline uint8_t oc_getreg_32(struct ocores_i2c *i2c, int32_t reg)

    return ioread32(i2c->base + (reg << i2c->reg_shift));


static inline uint8_t oc_getreg_16be(struct ocores_i2c *i2c, int32_t reg)

    return ioread16be(i2c->base + (reg << i2c->reg_shift));


static inline uint8_t oc_getreg_32be(struct ocores_i2c *i2c, int32_t reg)

    return ioread32be(i2c->base + (reg << i2c->reg_shift));


static void oc_setreg_io_8(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    outb(value, i2c->iobase + reg);


static inline uint8_t oc_getreg_io_8(struct ocores_i2c *i2c, int32_t reg)

    return inb(i2c->iobase + reg);


static inline void oc_setreg(struct ocores_i2c *i2c, int32_t reg, uint8_t value)

    i2c->setreg(i2c, reg, value);


static inline uint8_t oc_getreg(struct ocores_i2c *i2c, int32_t reg)

    return i2c->getreg(i2c, reg);


static void ocores_process(struct ocores_i2c *i2c, uint8_t stat)

    struct i2c_msg *msg = i2c->msg;
    size_t flags;

    /*
	 * If we spin here is because we are in timeout, so we are going
	 * to be in STATE_ERROR. See ocores_process_timeout()
	 */
    spin_lock_irqsave(&i2c->process_lock, flags);

    dev_dbg(&i2c->adap.dev, "STATE: %d\\n", i2c->state);

    if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) 
        /* stop has been sent */
        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
        wake_up(&i2c->wait);
        goto out;
    

    /* error? */
    if (stat & OCI2C_STAT_ARBLOST) 
        i2c->state = STATE_START;
        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
        dev_dbg(&i2c->adap.dev, "ERR: AL\\n");
        goto out;
    

    if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) 
        i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;

        if (stat & OCI2C_STAT_NACK) 
            dev_dbg(&i2c->adap.dev, rs485转TTL电平的芯片

上升沿和下降沿

请分析一下这个图,oc门电平转换是具体如何实现的,电压是如何被拉高的

GPIO_OType

100分求助,LVTTL和TTL电平之间如何转换?

C6333