drivers/1wire/1wire_ds2xxx.h: add the driver for DS2XXX eeproms.

Supports these Maxim/Analog Devices eeproms with a scratchpad:
DS2430,2431,2432,2433,28E04,28E07,28EC20.

For each type of an eeprom, you create a new driver.
Other than that, the driver is file oriented and supports seeks,
for example.

Signed-off-by: Stepan Pressl <pressl.stepan@gmail.com>
This commit is contained in:
Stepan Pressl
2025-10-09 19:21:18 +02:00
committed by Alin Jerpelea
parent d1e1643b84
commit 84b0492fbd
5 changed files with 949 additions and 0 deletions

View File

@@ -0,0 +1,829 @@
/****************************************************************************
* drivers/1wire/1wire_ds2xxx.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Author: Stepan Pressl <pressl.stepan@gmail.com>
* <pressste@fel.cvut.cz>
*
****************************************************************************/
/* This is a driver for 1Wire Maxim Integrated DS2xxx EEPROMs.
* Currently, the driver was tested against the DS2431 EEPROM but other
* EEPROMs listed in 1wire_ds2xxx.h
*/
/****************************************************************************
* Included Files
****************************************************************************/
#include <assert.h>
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <inttypes.h>
#include <debug.h>
#include <nuttx/fs/fs.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include <nuttx/1wire/1wire.h>
#include <nuttx/1wire/1wire_crc.h>
#include <nuttx/1wire/1wire_ds2xxx.h>
#include <nuttx/1wire/1wire_master.h>
#include <nuttx/arch.h>
#include "1wire_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_ENDIAN_BIG
# define onewire_leuint64(x) (x)
# define onewire_leuint32(x) (x)
#endif
#define WS_HEADER_OFFSET ((uint8_t)3)
#define RS_HEADER_SIZE ((uint8_t)3)
#define CS_HEADER_SIZE ((uint8_t)4)
#define HELPBUF_MARGIN ((uint8_t)5)
#define MATCHROM_BUF_SIZE ((uint8_t)9)
#define DS2XXX_TPROG_US ((useconds_t)12000)
/****************************************************************************
* Priavate Types
****************************************************************************/
struct ds2xxx_dev_s
{
FAR struct onewire_master_s *master;
uint64_t romcode; /* Romcode to be addressed on the bus */
int devtype; /* See enum ds2xxx_eeproms_e */
uint8_t *helpbuf; /* Helpful memory to avoid alloc on stack */
uint8_t refs; /* Opened references to ds2xxx */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int ds2xxx_open(FAR struct file *filep);
static int ds2xxx_close(FAR struct file *filep);
static int ds2xxx_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
static ssize_t ds2xxx_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t ds2xxx_read_internal(FAR struct ds2xxx_dev_s *priv,
off_t eeprom_addr,
FAR uint8_t *buffer, size_t buflen);
static ssize_t ds2xxx_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
static ssize_t ds2xxx_write_internal(FAR struct ds2xxx_dev_s *priv,
off_t eeprom_addr,
FAR uint8_t *buffer, size_t buflen);
static off_t ds2xxx_seek(FAR struct file *filep, off_t offset, int whence);
static int ds2xxx_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
/* Mapping from ds2xxx_types_e to eeprom sizes, pages and family codes.
* The driver is fully generic for all supported DS2XXX memories with
* a write scratchpad.
*/
static size_t g_eeprom_sizes[EEPROM_DS_COUNT] =
{
32,
128,
128,
512,
512,
128,
2560
};
static size_t g_eeprom_scratchpad_sizes[EEPROM_DS_COUNT] =
{
8,
8,
8,
32,
32,
8,
32
};
static int g_eeprom_familycodes[EEPROM_DS_COUNT] =
{
0x14,
0x2d,
0xb3,
0x23,
0x1c,
0x2d,
0x43
};
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations g_ds2xxx_fops =
{
.open = ds2xxx_open,
.close = ds2xxx_close,
.read = ds2xxx_read,
.write = ds2xxx_write,
.seek = ds2xxx_seek,
.ioctl = ds2xxx_ioctl,
};
/****************************************************************************
* Private Functions
****************************************************************************/
#ifdef CONFIG_ENDIAN_BIG
static inline uint64_t onewire_leuint64(uint64_t x)
{
return (((x & 0xff00000000000000ull) >> 56) |
((x & 0x00ff000000000000ull) >> 40) |
((x & 0x0000ff0000000000ull) >> 24) |
((x & 0x000000ff00000000ull) >> 8) |
((x & 0x00000000ff000000ull) << 8) |
((x & 0x0000000000ff0000ull) << 24) |
((x & 0x000000000000ff00ull) << 40) |
((x & 0x00000000000000ffull) << 56));
}
#endif
#ifdef CONFIG_ENDIAN_BIG
static inline uint32_t onewire_leuint32(uint32_t x)
{
return (((x & 0xff000000) >> 24) |
((x & 0x00ff0000) >> 8) |
((x & 0x0000ff00) << 8) |
((x & 0x000000ff) << 24));
}
#endif
/****************************************************************************
* Name: ds2xxx_startcomm
*
* Description:
* Performs the Match Rom command on the bus.
*
****************************************************************************/
static int ds2xxx_startcomm(struct ds2xxx_dev_s *priv, uint8_t *wrbuf)
{
int ret;
uint64_t tmp;
ret = ONEWIRE_RESET(priv->master->dev);
if (ret < 0)
{
return ret;
}
wrbuf[0] = DS2XXX_MATCH_ROM;
tmp = onewire_leuint64(priv->master->selected_rom);
memcpy(&wrbuf[1], &tmp, MATCHROM_BUF_SIZE - 1);
return ONEWIRE_WRITE(priv->master->dev, wrbuf, MATCHROM_BUF_SIZE);
}
/****************************************************************************
* Name: ds2xxx_read_internal
*
* Description:
* Begins communication and reads data from the EEPROM. The read procedure
* is much simpler as data can be read from any address.
*
****************************************************************************/
static ssize_t ds2xxx_read_internal(FAR struct ds2xxx_dev_s *priv,
off_t eeprom_addr,
FAR uint8_t *buffer, size_t buflen)
{
int ret;
/* The process of reading is much simpler.
* The master must issue the Read Memory command followed with 2 bytes
* of address to be read from. The address is sent in little endian order.
*/
/* Initialize the communication */
ret = ds2xxx_startcomm(priv, buffer);
if (ret < 0)
{
return ret;
}
priv->helpbuf[0] = DS2XXX_READ_MEMORY;
priv->helpbuf[1] = eeprom_addr & 0xff;
priv->helpbuf[2] = eeprom_addr >> 8;
ret = ONEWIRE_WRITE(priv->master->dev, priv->helpbuf, 3);
if (ret < 0)
{
return ret;
}
/* Now read real data. */
ret = ONEWIRE_READ(priv->master->dev, (uint8_t *)buffer, buflen);
return ret;
}
/****************************************************************************
* Name: ds2xxx_write_internal
*
* Description:
* Begins communication and reads data from the EEPROM. The write procedure
* is not that straightforward. It is assumed the writes by this function
* are aligned. It is assumed buflen is at most the size of the scratchpad.
*
****************************************************************************/
static ssize_t ds2xxx_write_internal(FAR struct ds2xxx_dev_s *priv,
off_t eeprom_addr,
FAR uint8_t *buffer, size_t buflen)
{
ssize_t ret;
uint8_t buf[32 + HELPBUF_MARGIN];
uint16_t crc;
uint16_t reccrc;
i2cinfo("writing %zu bytes to %ld", buflen, eeprom_addr);
ret = ds2xxx_startcomm(priv, buf);
if (ret < 0)
{
return ret;
}
/* Now issue the write scratchpad command. Also calculate
* CRC16 which must be compared with the received one.
*/
buf[0] = DS2XXX_WRITE_SCRATCHPAD;
buf[1] = eeprom_addr & 0xff;
buf[2] = eeprom_addr >> 8;
crc = onewire_crc16(buf, 3, 0);
ret = ONEWIRE_WRITE(priv->master->dev, buf, 3);
if (ret < 0)
{
return ret;
}
crc = onewire_crc16(buffer, buflen, crc);
ret = ONEWIRE_WRITE(priv->master->dev, buffer, buflen);
if (ret < 0)
{
return ret;
}
/* We now need to receive the CRC. The order is little endian. */
ret = ONEWIRE_READ(priv->master->dev, buf, 2);
if (ret < 0)
{
return ret;
}
reccrc = buf[0] | (buf[1] << 8);
if (reccrc != (uint16_t) ~crc)
{
return -EPROTO;
}
/* We have successfully performed the Write Scratchpad command.
* Now issue read scratchpad.
*/
ret = ds2xxx_startcomm(priv, buf);
if (ret < 0)
{
return ret;
}
buf[0] = DS2XXX_READ_SCRATCHPAD;
ret = ONEWIRE_WRITE(priv->master->dev, buf, 1);
if (ret < 0)
{
return ret;
}
crc = onewire_crc16(buf, 1, 0);
/* TA-E/S + buflen + ~CRC16 => buflen + 5 */
ret = ONEWIRE_READ(priv->master->dev, buf,
buflen + HELPBUF_MARGIN);
if (ret < 0)
{
return ret;
}
crc = onewire_crc16(buf, buflen + RS_HEADER_SIZE, crc);
reccrc = buf[RS_HEADER_SIZE + buflen] |
buf[RS_HEADER_SIZE + buflen + 1] << 8;
if (reccrc != (uint16_t) ~crc)
{
return -EPROTO;
}
/* Memcheck should be performed, but imho CRC16 is already a good check.
* Commit the scratchpad into the eeprom.
*/
priv->helpbuf[0] = DS2XXX_COPY_SCRATCHPAD;
priv->helpbuf[1] = buf[0];
priv->helpbuf[2] = buf[1];
priv->helpbuf[3] = buf[2];
ret = ds2xxx_startcomm(priv, buf);
if (ret < 0)
{
return ret;
}
ret = ONEWIRE_WRITE(priv->master->dev, priv->helpbuf, CS_HEADER_SIZE);
if (ret < 0)
{
return ret;
}
/* Impose a delay. Across all supported devices, the maximum delay is 12 ms
* for a page.
*/
up_udelay(DS2XXX_TPROG_US);
i2cinfo("aligned write of %zu bytes successful", buflen);
return OK;
}
/****************************************************************************
* Name: ds2xxx_open
*
* Description:
* The open callback function.
*
****************************************************************************/
static int ds2xxx_open(FAR struct file *filep)
{
FAR struct ds2xxx_dev_s *priv;
FAR struct inode *inode = filep->f_inode;
int ret = OK;
DEBUGASSERT(inode->i_private);
priv = inode->i_private;
ret = nxrmutex_lock(&priv->master->devlock);
if (ret < 0)
{
return ret;
}
if ((priv->refs + 1) == 0)
{
ret = -EMFILE;
}
else
{
priv->refs++;
}
nxrmutex_unlock(&priv->master->devlock);
return OK;
}
/****************************************************************************
* Name: ds2xxx_write
*
* Description:
* The write callback function. As writes into the EEPROM must be aligned
* with the scratchpad, all nonaligned writes must first read the aligned
* part, change some bytes and then commit the aligned part to the
* scratchpad. This function takes care of this.
*
****************************************************************************/
static int ds2xxx_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen)
{
FAR struct ds2xxx_dev_s *priv;
FAR struct inode *inode = filep->f_inode;
off_t addr;
off_t misalign;
size_t to_write;
size_t scratchpad_size;
size_t buflen_save = buflen;
int ret = OK;
DEBUGASSERT(inode->i_private);
priv = inode->i_private;
scratchpad_size = g_eeprom_scratchpad_sizes[priv->devtype];
i2cwarn("writing %zu bytes to ptr %" PRIdOFF, buflen, filep->f_pos);
if (filep->f_pos >= g_eeprom_sizes[priv->devtype])
{
return -EFBIG;
}
if ((filep->f_pos + buflen) >= g_eeprom_sizes[priv->devtype])
{
buflen = g_eeprom_sizes[priv->devtype] - filep->f_pos;
buflen_save = buflen;
}
ret = nxrmutex_lock(&priv->master->devlock);
if (ret < 0)
{
goto done;
}
/* The process of writing to 1WIRE EEPROMs involves the usage
* of the scratchpad. Firstly, the Write Scratchpad command
* must be issued, the payload is as follows:
* 2 bytes ADDR (Little Endian) | DATA,
* where ADDR must be aligned to the scratchpad size
* (DS2431's scratchpad is 8 bytes, DS2433's scratchpad is 32 bytes
* and the DATA is maximally 8 bytes or 32 bytes, depending on the EEPROM.
*
* Since writes are not generally row aligned, we must read
* the corresponding unaligned ends beforehand, modifying respective parts
* and writing this back.
*
* To check the transaction has completed successfully, Read Scratchpad
* command is issued, returning the 3-byte authorization pattern, also.
*
* The writing procedure is ended with issuing the Copy Scratchpad
* command.
*/
/* Calculate the misalignment in the beginning. And the starting address. */
misalign = (filep->f_pos) % scratchpad_size;
addr = (filep->f_pos / scratchpad_size) * scratchpad_size;
/* The pointer points at the beginning of a page, decide if we skip. */
if (misalign == 0)
{
goto no_misalign_begin;
}
ret = ds2xxx_read_internal(priv, addr, priv->helpbuf, scratchpad_size);
if (ret < 0)
{
goto done;
}
/* Fill in the misaligned data. But decide on the length of the write. */
if (buflen >= scratchpad_size - misalign)
{
to_write = scratchpad_size - misalign;
}
else
{
to_write = buflen;
}
memcpy(priv->helpbuf + misalign, buffer, to_write);
ret = ds2xxx_write_internal(priv, addr, priv->helpbuf, scratchpad_size);
if (ret < 0)
{
goto done;
}
/* Move all the pointers */
buffer += to_write;
buflen -= to_write;
addr += scratchpad_size;
no_misalign_begin:
/* Now loop over all aligned writes. If everything was already
* written in the misaligned write or the next write is also misaligned,
* this loop won't run.
*/
while (buflen >= scratchpad_size)
{
ret = ds2xxx_write_internal(priv, addr, (uint8_t *)buffer,
scratchpad_size);
if (ret < 0)
{
goto done;
}
buffer += scratchpad_size;
buflen -= scratchpad_size;
addr += scratchpad_size;
}
/* There's no rest. */
if (buflen == 0)
{
goto success;
}
/* Finish this with the last read. The read is aligned but needs to be
* of the same size as the scratchpad.
*/
ret = ds2xxx_read_internal(priv, addr, priv->helpbuf, scratchpad_size);
if (ret < 0)
{
goto done;
}
memcpy(priv->helpbuf, buffer, buflen);
ret = ds2xxx_write_internal(priv, addr, priv->helpbuf, scratchpad_size);
if (ret < 0)
{
goto done;
}
/* Everything went well. Move the pointer */
success:
i2cwarn("success writing %d bytes", buflen_save);
filep->f_pos += buflen_save;
ret = buflen_save;
done:
nxrmutex_unlock(&priv->master->devlock);
return ret;
}
/****************************************************************************
* Name: ds2xxx_read
*
* Description:
* The read callback function. First, it checks the boundaries and then
* calls the ds2xxx_read_internal function.
*
****************************************************************************/
static ssize_t ds2xxx_read(FAR struct file *filep, FAR char *buffer,
size_t len)
{
FAR struct ds2xxx_dev_s *priv;
FAR struct inode *inode = filep->f_inode;
int ret = OK;
DEBUGASSERT(inode->i_private);
priv = inode->i_private;
ret = nxrmutex_lock(&priv->master->devlock);
if (ret < 0)
{
return ret;
}
/* The pointer is outside the "file" */
if (filep->f_pos >= g_eeprom_sizes[priv->devtype])
{
goto done;
}
/* Trim the length */
if ((filep->f_pos + len) > g_eeprom_sizes[priv->devtype])
{
len = g_eeprom_sizes[priv->devtype] - filep->f_pos;
}
ret = ds2xxx_read_internal(priv, filep->f_pos, (uint8_t *)buffer, len);
if (ret < 0)
{
goto done;
}
ret = len;
filep->f_pos += len;
i2cinfo("DS2XXX read OK, curpos=%" PRIdOFF, filep->f_pos);
done:
nxrmutex_unlock(&priv->master->devlock);
return ret;
}
/****************************************************************************
* Name: ds2xxx_close
*
* Description:
* The close callback function.
*
****************************************************************************/
static int ds2xxx_close(FAR struct file *filep)
{
FAR struct ds2xxx_dev_s *priv;
FAR struct inode *inode = filep->f_inode;
int ret = OK;
DEBUGASSERT(inode->i_private);
priv = inode->i_private;
ret = nxrmutex_lock(&priv->master->devlock);
if (ret < 0)
{
return ret;
}
if (priv->refs == 0)
{
ret = -EIO;
}
else
{
priv->refs--;
}
nxrmutex_unlock(&priv->master->devlock);
return ret;
}
/****************************************************************************
* Name: ds2xxx_seek
*
* Description:
* The seek callback function. Practically the same as in i2c_xx24xx.c.
*
****************************************************************************/
static off_t ds2xxx_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct ds2xxx_dev_s *priv;
FAR struct inode *inode = filep->f_inode;
int ret;
off_t newpos;
DEBUGASSERT(inode->i_private);
priv = inode->i_private;
ret = nxrmutex_lock(&priv->master->devlock);
if (ret < 0)
{
return ret;
}
switch (whence)
{
case SEEK_CUR:
newpos = filep->f_pos + offset;
break;
case SEEK_SET:
newpos = offset;
break;
case SEEK_END:
newpos = g_eeprom_sizes[priv->devtype] + offset;
break;
default:
nxrmutex_unlock(&priv->master->devlock);
return -EINVAL;
}
/* Opengroup.org:
*
* "The lseek() function shall allow the file offset to be set beyond the
* end of the existing data in the file. If data is later written at
* this point, subsequent reads of data in the gap shall return bytes
* with the value 0 until data is actually written into the gap."
*
* We can conform to the first part, but not the second. But return -EINVAL
* if
*
* "...the resulting file offset would be negative for a regular file,
* block special file, or directory."
*/
if (newpos >= 0)
{
filep->f_pos = newpos;
ret = newpos;
i2cinfo("ds2xxx_seek: newpos %" PRIdOFF, newpos);
}
else
{
ret = -EINVAL;
}
nxrmutex_unlock(&priv->master->devlock);
return ret;
}
/****************************************************************************
* Name: ds2xxx_ioctl
*
* Description:
* The ioctl callback function. The target romcode is specified here.
*
****************************************************************************/
static int ds2xxx_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct ds2xxx_dev_s *priv;
FAR struct inode *inode = filep->f_inode;
int ret = OK;
DEBUGASSERT(inode->i_private);
priv = inode->i_private;
nxrmutex_lock(&priv->master->devlock);
switch (cmd)
{
case ONEWIREIOC_SETROM:
/* The issue is that unsigned long is 32bits on most architectures.
* That means we should not pass the romcode as a value.
*/
i2cinfo("Rom to be set is 0x%" PRIx64, *((uint64_t *)arg));
ret = onewire_ioctl_setrom(priv->master, *((uint64_t *)arg));
break;
case ONEWIREIOC_GETFAMILYROMS:
ret = onewire_ioctl_getfamilyroms(priv->master,
(FAR struct onewire_availroms_s *)arg,
g_eeprom_familycodes[priv->devtype]);
break;
default:
ret = -ENOTTY;
}
nxrmutex_unlock(&priv->master->devlock);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int ds2xxx_initialize(FAR struct onewire_dev_s *dev,
enum ds2xxx_eeproms_e devtype, FAR char *devname)
{
FAR struct ds2xxx_dev_s *priv;
if (devtype < 0 || devtype > EEPROM_DS_COUNT)
{
return -EINVAL;
}
priv = kmm_zalloc(sizeof(struct ds2xxx_dev_s));
if (priv == NULL)
{
return -ENOMEM;
}
priv->master = onewire_initialize(dev, CONFIG_1WIRE_EE_DS2XXX_MEMSONBUS);
if (priv->master == NULL)
{
kmm_free(priv);
return -ENOMEM;
}
/* We need extra 5 bytes for the Copy Scratchpad command. */
priv->helpbuf = kmm_zalloc(HELPBUF_MARGIN +
g_eeprom_scratchpad_sizes[devtype]);
if (priv->helpbuf == NULL)
{
kmm_free(priv->master);
kmm_free(priv);
return -ENOMEM;
}
nxrmutex_init(&priv->master->devlock);
priv->master->dev = dev;
priv->devtype = devtype;
return register_driver(devname, &g_ds2xxx_fops, 0666, priv);
}

View File

@@ -27,5 +27,10 @@ if(CONFIG_1WIRE)
list(APPEND SRCS ds28e17.c)
endif()
# Include the 1WIRE driver for DS2XXX EEPROMs
if(CONFIG_1WIRE_EE_DS2XXX)
list(APPEND SRCS 1wire_ds2xxx.c)
endif()
target_sources(drivers PRIVATE ${SRCS})
endif()

View File

@@ -18,4 +18,27 @@ config 1WIRE_DS28E17
---help---
Enable support for the Maxim DS28E17 1-wire to I2C converter
config 1WIRE_EE_DS2XXX
bool "Support for Maxim/Analog Devices 1wire DS2XXX EEPROM devices"
default n
depends on 1WIRE
---help---
Enable support for 1WIRE DS2XXX EEPROMs.
The list of supported devices:
DS2430: 32 bytes, 1 page
DS2431: 128 bytes, 4 pages
DS2432: 128 bytes, 4 pages
DS2433: 512 bytes, 16 pages
DS28E04: 512 bytes, 16 pages
DS28E07: 128 bytes, 4 pages
DS28EC20: 2560 bytes, 32 pages
if 1WIRE_EE_DS2XXX
config 1WIRE_EE_DS2XXX_MEMSONBUS
int "Maximum number of DS2XXX eeproms on the same bus"
default 10
endif # 1WIRE_EE_DS2XXX
endif # 1WIRE

View File

@@ -28,6 +28,10 @@ ifeq ($(CONFIG_1WIRE_DS28E17),y)
CSRCS += ds28e17.c
endif
ifeq ($(CONFIG_1WIRE_EE_DS2XXX),y)
CSRCS += 1wire_ds2xxx.c
endif
# Include 1wire device driver build support
DEPPATH += --dep-path 1wire

View File

@@ -0,0 +1,88 @@
/****************************************************************************
* include/nuttx/1wire/1wire_ds2xxx.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Author: Stepan Pressl <pressl.stepan@gmail.com>
* <pressste@fel.cvut.cz>
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_EEPROM_1WIRE_DS2XXX_H
#define __INCLUDE_NUTTX_EEPROM_1WIRE_DS2XXX_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <nuttx/1wire/1wire.h>
/****************************************************************************
* Public Types
****************************************************************************/
/* All device specific commands for the scratchpad are luckily the same
* for all the devices.
*/
#define DS2XXX_WRITE_SCRATCHPAD 0x0f
#define DS2XXX_READ_SCRATCHPAD 0xaa
#define DS2XXX_COPY_SCRATCHPAD 0x55
#define DS2XXX_READ_MEMORY 0xf0
/* There are other commands, also. For example, the common commands
* have a different code than specified in drivers/1wire/1wire.c.
*/
#define DS2XXX_MATCH_ROM 0x55
/* DS28E05 has a different architecture,
* as it does not use a scratchpad. Let's keep this device out of here.
*/
enum ds2xxx_eeproms_e
{
EEPROM_DS2430 = 0,
EEPROM_DS2431,
EEPROM_DS2432,
EEPROM_DS2433,
EEPROM_DS28E04,
EEPROM_DS28E07,
EEPROM_DS28EC20,
EEPROM_DS_COUNT
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: ds2xxx_initialize
*
* Description: Bind a onewire_master_s struct to this driver,
* capable of interfacing DS2XXX 1Wire EEPROMs. The user must specify
* the device type and also the name of the device (e.g. /dev/ds2xxx).
*
****************************************************************************/
int ds2xxx_initialize(FAR struct onewire_dev_s *dev,
enum ds2xxx_eeproms_e devtype, FAR char *devname);
#endif /* __INCLUDE_NUTTX_EEPROM_1WIRE_DS2XXX_H */