forked from Imagelibrary/rtems
Add NXP PCA9548A 8-channel switch I2C driver
This commit is contained in:
@@ -9,6 +9,7 @@ include_dev_i2c_HEADERS =
|
|||||||
include_dev_i2c_HEADERS += include/dev/i2c/eeprom.h
|
include_dev_i2c_HEADERS += include/dev/i2c/eeprom.h
|
||||||
include_dev_i2c_HEADERS += include/dev/i2c/gpio-nxp-pca9535.h
|
include_dev_i2c_HEADERS += include/dev/i2c/gpio-nxp-pca9535.h
|
||||||
include_dev_i2c_HEADERS += include/dev/i2c/i2c.h
|
include_dev_i2c_HEADERS += include/dev/i2c/i2c.h
|
||||||
|
include_dev_i2c_HEADERS += include/dev/i2c/switch-nxp-pca9548a.h
|
||||||
|
|
||||||
include_linuxdir = $(includedir)/linux
|
include_linuxdir = $(includedir)/linux
|
||||||
include_linux_HEADERS =
|
include_linux_HEADERS =
|
||||||
@@ -22,6 +23,7 @@ libdev_a_SOURCES += i2c/eeprom.c
|
|||||||
libdev_a_SOURCES += i2c/gpio-nxp-pca9535.c
|
libdev_a_SOURCES += i2c/gpio-nxp-pca9535.c
|
||||||
libdev_a_SOURCES += i2c/i2c-bus.c
|
libdev_a_SOURCES += i2c/i2c-bus.c
|
||||||
libdev_a_SOURCES += i2c/i2c-dev.c
|
libdev_a_SOURCES += i2c/i2c-dev.c
|
||||||
|
libdev_a_SOURCES += i2c/switch-nxp-pca9548a.c
|
||||||
|
|
||||||
include $(srcdir)/preinstall.am
|
include $(srcdir)/preinstall.am
|
||||||
include $(top_srcdir)/automake/local.am
|
include $(top_srcdir)/automake/local.am
|
||||||
|
|||||||
99
cpukit/dev/i2c/switch-nxp-pca9548a.c
Normal file
99
cpukit/dev/i2c/switch-nxp-pca9548a.c
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief Switch NXP PCA9548A Driver Implementation
|
||||||
|
*
|
||||||
|
* @ingroup I2CSWITCHNXPPCA9548A
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
|
||||||
|
*
|
||||||
|
* embedded brains GmbH
|
||||||
|
* Dornierstr. 4
|
||||||
|
* 82178 Puchheim
|
||||||
|
* Germany
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.rtems.org/license/LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <dev/i2c/switch-nxp-pca9548a.h>
|
||||||
|
|
||||||
|
static int switch_nxp_pca9548a_do_get_control(
|
||||||
|
i2c_dev *dev,
|
||||||
|
uint8_t *val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
i2c_msg msg = {
|
||||||
|
.addr = dev->address,
|
||||||
|
.flags = I2C_M_RD,
|
||||||
|
.len = (uint16_t) sizeof(*val),
|
||||||
|
.buf = val
|
||||||
|
};
|
||||||
|
|
||||||
|
return i2c_bus_transfer(dev->bus, &msg, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int switch_nxp_pca9548a_do_set_control(
|
||||||
|
i2c_dev *dev,
|
||||||
|
uint8_t val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
i2c_msg msg = {
|
||||||
|
.addr = dev->address,
|
||||||
|
.flags = 0,
|
||||||
|
.len = (uint16_t) sizeof(val),
|
||||||
|
.buf = &val
|
||||||
|
};
|
||||||
|
|
||||||
|
return i2c_bus_transfer(dev->bus, &msg, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int switch_nxp_pca9548a_ioctl(
|
||||||
|
i2c_dev *dev,
|
||||||
|
ioctl_command_t command,
|
||||||
|
void *arg
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint8_t v8 = (uint8_t)(uintptr_t) arg;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case SWITCH_NXP_PCA9548A_GET_CONTROL:
|
||||||
|
err = switch_nxp_pca9548a_do_get_control(dev, arg);
|
||||||
|
break;
|
||||||
|
case SWITCH_NXP_PCA9548A_SET_CONTROL:
|
||||||
|
err = switch_nxp_pca9548a_do_set_control(dev, v8);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -ENOTTY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2c_dev_register_switch_nxp_pca9548a(
|
||||||
|
const char *bus_path,
|
||||||
|
const char *dev_path,
|
||||||
|
uint16_t address
|
||||||
|
)
|
||||||
|
{
|
||||||
|
i2c_dev *dev;
|
||||||
|
|
||||||
|
dev = i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address);
|
||||||
|
if (dev == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->ioctl = switch_nxp_pca9548a_ioctl;
|
||||||
|
|
||||||
|
return i2c_dev_register(dev, dev_path);
|
||||||
|
}
|
||||||
68
cpukit/dev/include/dev/i2c/switch-nxp-pca9548a.h
Normal file
68
cpukit/dev/include/dev/i2c/switch-nxp-pca9548a.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief Switch NXP PCA9548A Driver API
|
||||||
|
*
|
||||||
|
* @ingroup I2CSWITCHNXPPCA9548A
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
|
||||||
|
*
|
||||||
|
* embedded brains GmbH
|
||||||
|
* Dornierstr. 4
|
||||||
|
* 82178 Puchheim
|
||||||
|
* Germany
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.rtems.org/license/LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DEV_I2C_SWITCH_NXP_PCA9548A_H
|
||||||
|
#define _DEV_I2C_SWITCH_NXP_PCA9548A_H
|
||||||
|
|
||||||
|
#include <dev/i2c/i2c.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup I2CSWITCHNXPPCA9548A Switch NXP PCA9535 Driver
|
||||||
|
*
|
||||||
|
* @ingroup I2CDevice
|
||||||
|
*
|
||||||
|
* @brief Driver for NXP PCA9548A 8-channel switch device.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
int i2c_dev_register_switch_nxp_pca9548a(
|
||||||
|
const char *bus_path,
|
||||||
|
const char *dev_path,
|
||||||
|
uint16_t address
|
||||||
|
);
|
||||||
|
|
||||||
|
#define SWITCH_NXP_PCA9548A_GET_CONTROL (I2C_DEV_IO_CONTROL + 0)
|
||||||
|
|
||||||
|
#define SWITCH_NXP_PCA9548A_SET_CONTROL (I2C_DEV_IO_CONTROL + 1)
|
||||||
|
|
||||||
|
static inline int switch_nxp_pca9548a_get_control(int fd, uint8_t *val)
|
||||||
|
{
|
||||||
|
return ioctl(fd, SWITCH_NXP_PCA9548A_GET_CONTROL, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int switch_nxp_pca9548a_set_control(int fd, uint8_t val)
|
||||||
|
{
|
||||||
|
return ioctl(fd, SWITCH_NXP_PCA9548A_SET_CONTROL, (void *)(uintptr_t) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* _DEV_I2C_SWITCH_NXP_PCA9548A_H */
|
||||||
@@ -35,6 +35,10 @@ $(PROJECT_INCLUDE)/dev/i2c/i2c.h: include/dev/i2c/i2c.h $(PROJECT_INCLUDE)/dev/i
|
|||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/i2c.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/i2c.h
|
||||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/i2c.h
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/i2c.h
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE)/dev/i2c/switch-nxp-pca9548a.h: include/dev/i2c/switch-nxp-pca9548a.h $(PROJECT_INCLUDE)/dev/i2c/$(dirstamp)
|
||||||
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/switch-nxp-pca9548a.h
|
||||||
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/switch-nxp-pca9548a.h
|
||||||
|
|
||||||
$(PROJECT_INCLUDE)/linux/$(dirstamp):
|
$(PROJECT_INCLUDE)/linux/$(dirstamp):
|
||||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/linux
|
@$(MKDIR_P) $(PROJECT_INCLUDE)/linux
|
||||||
@: > $(PROJECT_INCLUDE)/linux/$(dirstamp)
|
@: > $(PROJECT_INCLUDE)/linux/$(dirstamp)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <dev/i2c/i2c.h>
|
#include <dev/i2c/i2c.h>
|
||||||
#include <dev/i2c/eeprom.h>
|
#include <dev/i2c/eeprom.h>
|
||||||
#include <dev/i2c/gpio-nxp-pca9535.h>
|
#include <dev/i2c/gpio-nxp-pca9535.h>
|
||||||
|
#include <dev/i2c/switch-nxp-pca9548a.h>
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -42,6 +43,8 @@ const char rtems_test_name[] = "I2C 1";
|
|||||||
|
|
||||||
#define DEVICE_GPIO_NXP_PCA9535 (2UL << SPARE_ADDRESS_BITS)
|
#define DEVICE_GPIO_NXP_PCA9535 (2UL << SPARE_ADDRESS_BITS)
|
||||||
|
|
||||||
|
#define DEVICE_SWITCH_NXP_PCA9548A (3UL << SPARE_ADDRESS_BITS)
|
||||||
|
|
||||||
#define EEPROM_SIZE 512
|
#define EEPROM_SIZE 512
|
||||||
|
|
||||||
typedef struct test_device test_device;
|
typedef struct test_device test_device;
|
||||||
@@ -72,13 +75,19 @@ typedef struct {
|
|||||||
uint8_t data[EEPROM_SIZE];
|
uint8_t data[EEPROM_SIZE];
|
||||||
} test_device_eeprom;
|
} test_device_eeprom;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
test_device base;
|
||||||
|
uint8_t control;
|
||||||
|
} test_device_switch_nxp_pca9548a;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
i2c_bus base;
|
i2c_bus base;
|
||||||
unsigned long clock;
|
unsigned long clock;
|
||||||
test_device *devices[3];
|
test_device *devices[4];
|
||||||
test_device_simple_read_write simple_read_write;
|
test_device_simple_read_write simple_read_write;
|
||||||
test_device_gpio_nxp_pca9535 gpio_nxp_pca9535;
|
test_device_gpio_nxp_pca9535 gpio_nxp_pca9535;
|
||||||
test_device_eeprom eeprom;
|
test_device_eeprom eeprom;
|
||||||
|
test_device_switch_nxp_pca9548a switch_nxp_pca9548a;
|
||||||
} test_bus;
|
} test_bus;
|
||||||
|
|
||||||
static const char bus_path[] = "/dev/i2c-0";
|
static const char bus_path[] = "/dev/i2c-0";
|
||||||
@@ -87,6 +96,9 @@ static const char gpio_nxp_pca9535_path[] = "/dev/i2c-0.gpio-nxp-pc9535-0";
|
|||||||
|
|
||||||
static const char eeprom_path[] = "/dev/i2c-0.eeprom-0";
|
static const char eeprom_path[] = "/dev/i2c-0.eeprom-0";
|
||||||
|
|
||||||
|
static const char switch_nxp_pca9548a_path[] =
|
||||||
|
"/dev/i2c-0.switch-nxp-pca9548a-0";
|
||||||
|
|
||||||
static void cyclic_inc(unsigned *val, unsigned cycle)
|
static void cyclic_inc(unsigned *val, unsigned cycle)
|
||||||
{
|
{
|
||||||
unsigned v = *val;
|
unsigned v = *val;
|
||||||
@@ -217,6 +229,34 @@ static int test_eeprom_transfer(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_switch_nxp_pca9548a_transfer(
|
||||||
|
i2c_bus *bus,
|
||||||
|
i2c_msg *msgs,
|
||||||
|
uint32_t msg_count,
|
||||||
|
test_device *base
|
||||||
|
)
|
||||||
|
{
|
||||||
|
test_device_switch_nxp_pca9548a *dev = (test_device_switch_nxp_pca9548a *) base;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < msg_count; ++i) {
|
||||||
|
i2c_msg *msg = &msgs[i];
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if ((msg->flags & I2C_M_RD) != 0) {
|
||||||
|
for (j = 0; j < msg->len; ++j) {
|
||||||
|
msg->buf[j] = dev->control;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (j = 0; j < msg->len; ++j) {
|
||||||
|
dev->control = msg->buf[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int test_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
|
static int test_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
|
||||||
{
|
{
|
||||||
test_bus *bus = (test_bus *) base;
|
test_bus *bus = (test_bus *) base;
|
||||||
@@ -438,6 +478,40 @@ static void test_eeprom(void)
|
|||||||
rtems_test_assert(rv == 0);
|
rtems_test_assert(rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_switch_nxp_pca9548a(void)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int fd;
|
||||||
|
uint8_t val;
|
||||||
|
|
||||||
|
rv = i2c_dev_register_switch_nxp_pca9548a(
|
||||||
|
&bus_path[0],
|
||||||
|
&switch_nxp_pca9548a_path[0],
|
||||||
|
DEVICE_SWITCH_NXP_PCA9548A
|
||||||
|
);
|
||||||
|
rtems_test_assert(rv == 0);
|
||||||
|
|
||||||
|
fd = open(&switch_nxp_pca9548a_path[0], O_RDWR);
|
||||||
|
rtems_test_assert(fd >= 0);
|
||||||
|
|
||||||
|
rv = switch_nxp_pca9548a_get_control(fd, &val);
|
||||||
|
rtems_test_assert(rv == 0);
|
||||||
|
rtems_test_assert(val == 0);
|
||||||
|
|
||||||
|
rv = switch_nxp_pca9548a_set_control(fd, 0xa5);
|
||||||
|
rtems_test_assert(rv == 0);
|
||||||
|
|
||||||
|
rv = switch_nxp_pca9548a_get_control(fd, &val);
|
||||||
|
rtems_test_assert(rv == 0);
|
||||||
|
rtems_test_assert(val == 0xa5);
|
||||||
|
|
||||||
|
rv = close(fd);
|
||||||
|
rtems_test_assert(rv == 0);
|
||||||
|
|
||||||
|
rv = unlink(&switch_nxp_pca9548a_path[0]);
|
||||||
|
rtems_test_assert(rv == 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void test(void)
|
static void test(void)
|
||||||
{
|
{
|
||||||
rtems_resource_snapshot snapshot;
|
rtems_resource_snapshot snapshot;
|
||||||
@@ -465,6 +539,9 @@ static void test(void)
|
|||||||
bus->gpio_nxp_pca9535.base.transfer = test_gpio_nxp_pca9535_transfer;
|
bus->gpio_nxp_pca9535.base.transfer = test_gpio_nxp_pca9535_transfer;
|
||||||
bus->devices[2] = &bus->gpio_nxp_pca9535.base;
|
bus->devices[2] = &bus->gpio_nxp_pca9535.base;
|
||||||
|
|
||||||
|
bus->switch_nxp_pca9548a.base.transfer = test_switch_nxp_pca9548a_transfer;
|
||||||
|
bus->devices[3] = &bus->switch_nxp_pca9548a.base;
|
||||||
|
|
||||||
rv = i2c_bus_register(&bus->base, &bus_path[0]);
|
rv = i2c_bus_register(&bus->base, &bus_path[0]);
|
||||||
rtems_test_assert(rv == 0);
|
rtems_test_assert(rv == 0);
|
||||||
|
|
||||||
@@ -533,6 +610,7 @@ static void test(void)
|
|||||||
test_simple_read_write(bus, fd);
|
test_simple_read_write(bus, fd);
|
||||||
test_eeprom();
|
test_eeprom();
|
||||||
test_gpio_nxp_pca9535();
|
test_gpio_nxp_pca9535();
|
||||||
|
test_switch_nxp_pca9548a();
|
||||||
|
|
||||||
rv = close(fd);
|
rv = close(fd);
|
||||||
rtems_test_assert(rv == 0);
|
rtems_test_assert(rv == 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user