From 25de27fbcb3e9259387fc2ac3f989effe5751976 Mon Sep 17 00:00:00 2001 From: Korobov Nikita Date: Thu, 13 Jul 2017 17:40:41 +0300 Subject: [PATCH] [MAJOR] The I2C driver become driver for RPI The driver is compatible with the Raspberry Pi. There are only the one I2C driver for each platforms. NOTE! It have not debuged yet. Don't use it! --- distrib/sets/lists/minix-base/md.evbarm | 4 +- minix/drivers/bus/i2c/Makefile | 12 +- minix/drivers/bus/i2c/arch/earm/omap/i2c.conf | 20 - minix/drivers/bus/i2c/arch/earm/rpi/i2c.conf | 12 - minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.c | 725 ++++++------------ minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.h | 2 +- .../bus/i2c/arch/earm/rpi/rpi_i2c_registers.h | 174 ++--- minix/drivers/bus/i2c/i2c.c | 6 + minix/drivers/bus/i2c/i2c.conf | 21 + releasetools/arm_sdimage_rpi.sh | 2 + 10 files changed, 326 insertions(+), 652 deletions(-) delete mode 100644 minix/drivers/bus/i2c/arch/earm/omap/i2c.conf delete mode 100644 minix/drivers/bus/i2c/arch/earm/rpi/i2c.conf create mode 100644 minix/drivers/bus/i2c/i2c.conf diff --git a/distrib/sets/lists/minix-base/md.evbarm b/distrib/sets/lists/minix-base/md.evbarm index b01b7608a..1ccc1c681 100644 --- a/distrib/sets/lists/minix-base/md.evbarm +++ b/distrib/sets/lists/minix-base/md.evbarm @@ -9,6 +9,7 @@ ./etc/rc.capes/BB-BONE-WTHR-01 minix-base ./etc/system.conf.d/bmp085 minix-base ./etc/system.conf.d/gpio minix-base +./etc/system.conf.d/i2c minix-base ./etc/system.conf.d/lan8710a minix-base ./etc/system.conf.d/sht21 minix-base ./etc/system.conf.d/tsl2550 minix-base @@ -17,12 +18,11 @@ ./service/cat24c256 minix-base ./service/fb minix-base ./service/gpio minix-base +./service/i2c minix-base ./service/lan8710a minix-base ./service/mailbox minix-base ./service/omap_emmc minix-base -./service/i2c_omap minix-base ./service/omap_mmc minix-base -./service/i2c_rpi minix-base ./service/rpi_mmc minix-base ./service/random minix-base ./service/sht21 minix-base diff --git a/minix/drivers/bus/i2c/Makefile b/minix/drivers/bus/i2c/Makefile index 4f9302479..400df49b5 100644 --- a/minix/drivers/bus/i2c/Makefile +++ b/minix/drivers/bus/i2c/Makefile @@ -1,16 +1,18 @@ # Makefile for I2C support +PROG= i2c +SRCS+= i2c.c +FILESNAME=i2c +FILES=i2c.conf + .if ${MACHINE_ARCH} == "earm" .for pl in rpi omap .PATH: ${.CURDIR}/arch/earm/${pl} -PROGS+= i2c_${pl} -SRCS.i2c_${pl}+= i2c.c ${pl}_i2c.c ${pl}_i2c.h ${pl}_i2c_registers.h -FILES.i2c_${pl}=i2c_${pl}.conf -FILESNAME=i2c_${pl} +SRCS+= ${pl}_i2c.c ${pl}_i2c.h ${pl}_i2c_registers.h .endfor .else .PATH: ${.CURDIR}/arch/${MACHINE_ARCH} -SRCS.i2c += pci_i2c.c pci_i2c.h pci_i2c_register.h +SRCS+= pci_i2c.c pci_i2c.h pci_i2c_register.h .endif FILESDIR= /etc/system.conf.d diff --git a/minix/drivers/bus/i2c/arch/earm/omap/i2c.conf b/minix/drivers/bus/i2c/arch/earm/omap/i2c.conf deleted file mode 100644 index 6112f91c7..000000000 --- a/minix/drivers/bus/i2c/arch/earm/omap/i2c.conf +++ /dev/null @@ -1,20 +0,0 @@ -service i2c -{ - system - PRIVCTL # 4 - IRQCTL # 19 - PADCONF # 57 - ; - irq - # DM37XX (BeagleBoard-xM) - 56 # I2C module 1 - 57 # I2C module 2 - 61 # I2C module 3 - # AM335X (BeagleBone) - 70 # I2C module 1 - 71 # I2C module 2 - 30 # I2C module 3 - ; - ipc SYSTEM RS DS; -}; - diff --git a/minix/drivers/bus/i2c/arch/earm/rpi/i2c.conf b/minix/drivers/bus/i2c/arch/earm/rpi/i2c.conf deleted file mode 100644 index 441ed4443..000000000 --- a/minix/drivers/bus/i2c/arch/earm/rpi/i2c.conf +++ /dev/null @@ -1,12 +0,0 @@ -service rpi_i2c -{ - system - PRIVCTL # 4 - IRQCTL # 19 - PADCONF # 57 - ; - irq - ; - ipc SYSTEM RS DS; -}; - diff --git a/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.c b/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.c index a67cabe89..f12dd7307 100644 --- a/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.c +++ b/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.c @@ -38,167 +38,65 @@ * to access these registers. The DM37XX TRM Section 17.6 warns that 32-bit * accesses can corrupt the register contents. */ -typedef struct omap_i2c_registers +typedef struct { - vir_bytes I2C_REVNB_LO; /* AM335X Only */ - vir_bytes I2C_REVNB_HI; /* AM335X Only */ - vir_bytes I2C_REV; /* DM37XX Only */ - vir_bytes I2C_IE; /* DM37XX Only */ - vir_bytes I2C_STAT; /* DM37XX Only */ - vir_bytes I2C_SYSC; - vir_bytes I2C_IRQSTATUS_RAW; /* AM335X Only */ - vir_bytes I2C_IRQSTATUS; /* AM335X Only */ - vir_bytes I2C_IRQENABLE_SET; /* AM335X Only */ - vir_bytes I2C_IRQENABLE_CLR; /* AM335X Only */ - vir_bytes I2C_WE; - vir_bytes I2C_DMARXENABLE_SET; /* AM335X Only */ - vir_bytes I2C_DMATXENABLE_SET; /* AM335X Only */ - vir_bytes I2C_DMARXENABLE_CLR; /* AM335X Only */ - vir_bytes I2C_DMATXENABLE_CLR; /* AM335X Only */ - vir_bytes I2C_DMARXWAKE_EN; /* AM335X Only */ - vir_bytes I2C_DMATXWAKE_EN; /* AM335X Only */ - vir_bytes I2C_SYSS; - vir_bytes I2C_BUF; - vir_bytes I2C_CNT; - vir_bytes I2C_DATA; - vir_bytes I2C_CON; - vir_bytes I2C_OA; /* AM335X Only */ - vir_bytes I2C_OA0; /* DM37XX Only */ - vir_bytes I2C_SA; - vir_bytes I2C_PSC; - vir_bytes I2C_SCLL; - vir_bytes I2C_SCLH; - vir_bytes I2C_SYSTEST; - vir_bytes I2C_BUFSTAT; - vir_bytes I2C_OA1; - vir_bytes I2C_OA2; - vir_bytes I2C_OA3; - vir_bytes I2C_ACTOA; - vir_bytes I2C_SBLOCK; -} omap_i2c_regs_t; + vir_bytes CTRL; + vir_bytes ST; + vir_bytes DLEN; + vir_bytes SL_ADDR; + vir_bytes FIFO; + vir_bytes DIV; + vir_bytes DEL; + vir_bytes CLKT; +} rpi_i2c_regs_t; /* generic definition an i2c bus */ -typedef struct omap_i2c_bus +typedef struct rpi_i2c_bus { - enum bus_types - { AM335X_I2C_BUS, DM37XX_I2C_BUS} bus_type; phys_bytes mr_base; phys_bytes mr_size; vir_bytes mapped_addr; - omap_i2c_regs_t *regs; + rpi_i2c_regs_t *regs; uint32_t functional_clock; uint32_t module_clock; uint32_t bus_speed; - uint16_t major; - uint16_t minor; int irq; int irq_hook_id; int irq_hook_kernel_id; -} omap_i2c_bus_t; +} rpi_i2c_bus_t; /* Define the registers for each chip */ -static omap_i2c_regs_t am335x_i2c_regs = { - .I2C_REVNB_LO = AM335X_I2C_REVNB_LO, - .I2C_REVNB_HI = AM335X_I2C_REVNB_HI, - .I2C_SYSC = AM335X_I2C_SYSC, - .I2C_IRQSTATUS_RAW = AM335X_I2C_IRQSTATUS_RAW, - .I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS, - .I2C_IRQENABLE_SET = AM335X_I2C_IRQENABLE_SET, - .I2C_IRQENABLE_CLR = AM335X_I2C_IRQENABLE_CLR, - .I2C_WE = AM335X_I2C_WE, - .I2C_DMARXENABLE_SET = AM335X_I2C_DMARXENABLE_SET, - .I2C_DMATXENABLE_SET = AM335X_I2C_DMATXENABLE_SET, - .I2C_DMARXENABLE_CLR = AM335X_I2C_DMARXENABLE_CLR, - .I2C_DMATXENABLE_CLR = AM335X_I2C_DMATXENABLE_CLR, - .I2C_DMARXWAKE_EN = AM335X_I2C_DMARXWAKE_EN, - .I2C_DMATXWAKE_EN = AM335X_I2C_DMATXWAKE_EN, - .I2C_SYSS = AM335X_I2C_SYSS, - .I2C_BUF = AM335X_I2C_BUF, - .I2C_CNT = AM335X_I2C_CNT, - .I2C_DATA = AM335X_I2C_DATA, - .I2C_CON = AM335X_I2C_CON, - .I2C_OA = AM335X_I2C_OA, - .I2C_SA = AM335X_I2C_SA, - .I2C_PSC = AM335X_I2C_PSC, - .I2C_SCLL = AM335X_I2C_SCLL, - .I2C_SCLH = AM335X_I2C_SCLH, - .I2C_SYSTEST = AM335X_I2C_SYSTEST, - .I2C_BUFSTAT = AM335X_I2C_BUFSTAT, - .I2C_OA1 = AM335X_I2C_OA1, - .I2C_OA2 = AM335X_I2C_OA2, - .I2C_OA3 = AM335X_I2C_OA3, - .I2C_ACTOA = AM335X_I2C_ACTOA, - .I2C_SBLOCK = AM335X_I2C_SBLOCK -}; - -static omap_i2c_regs_t dm37xx_i2c_regs = { - .I2C_REV = DM37XX_I2C_REV, - .I2C_IE = DM37XX_I2C_IE, - .I2C_STAT = DM37XX_I2C_STAT, - .I2C_WE = DM37XX_I2C_WE, - .I2C_SYSS = DM37XX_I2C_SYSS, - .I2C_BUF = DM37XX_I2C_BUF, - .I2C_CNT = DM37XX_I2C_CNT, - .I2C_DATA = DM37XX_I2C_DATA, - .I2C_SYSC = DM37XX_I2C_SYSC, - .I2C_CON = DM37XX_I2C_CON, - .I2C_OA0 = DM37XX_I2C_OA0, - .I2C_SA = DM37XX_I2C_SA, - .I2C_PSC = DM37XX_I2C_PSC, - .I2C_SCLL = DM37XX_I2C_SCLL, - .I2C_SCLH = DM37XX_I2C_SCLH, - .I2C_SYSTEST = DM37XX_I2C_SYSTEST, - .I2C_BUFSTAT = DM37XX_I2C_BUFSTAT, - .I2C_OA1 = DM37XX_I2C_OA1, - .I2C_OA2 = DM37XX_I2C_OA2, - .I2C_OA3 = DM37XX_I2C_OA3, - .I2C_ACTOA = DM37XX_I2C_ACTOA, - .I2C_SBLOCK = DM37XX_I2C_SBLOCK +static rpi_i2c_regs_t bcm283x_i2c_regs = { + .CTRL = BCM283X_CTRL, + .ST = BCM283X_STATUS, + .DLEN = BCM283X_DLEN, + .SL_ADDR = BCM283X_SL_ADDR, + .FIFO = BCM283X_FIFO, + .DIV = BCM283X_DIV, + .DEL = BCM283X_DEL, + .CLKT = BCM283X_CLKT, }; /* Define the buses available on each chip */ -static omap_i2c_bus_t am335x_i2c_buses[] = { - {AM335X_I2C_BUS, AM335X_I2C0_BASE, AM335X_I2C0_SIZE, 0, &am335x_i2c_regs, - AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK, - BUS_SPEED_400KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR, - AM335X_I2C0_IRQ, 1, 1}, - {AM335X_I2C_BUS, AM335X_I2C1_BASE, AM335X_I2C1_SIZE, 0, &am335x_i2c_regs, - AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK, - BUS_SPEED_100KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR, - AM335X_I2C1_IRQ, 2, 3}, - {AM335X_I2C_BUS, AM335X_I2C2_BASE, AM335X_I2C2_SIZE, 0, &am335x_i2c_regs, - AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK, - BUS_SPEED_100KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR, - AM335X_I2C2_IRQ, 3, 3} -}; +static rpi_i2c_bus_t bcm283x_i2c_buses[] = { + {BCM283X_I2C0_BASE, BCM283X_I2C0_SIZE, 0, &bcm283x_i2c_regs, + BCM283X_FUNCTIONAL_CLOCK, BCM283X_MODULE_CLOCK, + BUS_SPEED_400KHz, BCM283X_I2C0_IRQ, 1, 1}, + {BCM283X_I2C1_BASE, BCM283X_I2C1_SIZE, 0, &bcm283x_i2c_regs, + BCM283X_FUNCTIONAL_CLOCK, BCM283X_MODULE_CLOCK, + BUS_SPEED_400KHz, BCM283X_I2C0_IRQ, 2, 3} + }; -#define AM335X_OMAP_NBUSES (sizeof(am335x_i2c_buses) / sizeof(omap_i2c_bus_t)) - -static omap_i2c_bus_t dm37xx_i2c_buses[] = { - {DM37XX_I2C_BUS, DM37XX_I2C0_BASE, DM37XX_I2C0_SIZE, 0, &dm37xx_i2c_regs, - DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK, - BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR, - DM37XX_I2C0_IRQ, 1, 1}, - {DM37XX_I2C_BUS, DM37XX_I2C1_BASE, DM37XX_I2C1_SIZE, 0, &dm37xx_i2c_regs, - DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK, - BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR, - DM37XX_I2C1_IRQ, 2, 2}, - {DM37XX_I2C_BUS, DM37XX_I2C2_BASE, DM37XX_I2C2_SIZE, 0, &dm37xx_i2c_regs, - DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK, - BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR, - DM37XX_I2C2_IRQ, 3, 3} -}; - -#define DM37XX_OMAP_NBUSES (sizeof(dm37xx_i2c_buses) / sizeof(omap_i2c_bus_t)) +#define BCM283X_rpi_NBUSES (sizeof(bcm283x_i2c_buses) / sizeof(rpi_i2c_bus_t)) /* Globals */ -static omap_i2c_bus_t *omap_i2c_buses; /* all available buses for this SoC */ -static omap_i2c_bus_t *omap_i2c_bus; /* the bus selected at start-up */ -static int omap_i2c_nbuses; /* number of buses supported by SoC */ +static rpi_i2c_bus_t *rpi_i2c_buses; /* all available buses for this SoC */ +static rpi_i2c_bus_t *rpi_i2c_bus; /* the bus selected at start-up */ +static int rpi_i2c_nbuses; /* number of buses supported by SoC */ /* logging - use with log_warn(), log_info(), log_debug(), log_trace() */ static struct log log = { @@ -210,29 +108,29 @@ static struct log log = { /* Local Function Prototypes */ /* Implementation of Generic I2C Interface using Bus Specific Code */ -static int omap_i2c_process(minix_i2c_ioctl_exec_t * m); +static int rpi_i2c_process(minix_i2c_ioctl_exec_t * m); /* Bus Specific Code */ -static void omap_i2c_flush(void); -static uint16_t omap_i2c_poll(uint16_t mask); -static int omap_i2c_bus_is_free(void); -static int omap_i2c_soft_reset(void); -static void omap_i2c_bus_init(void); -static void omap_i2c_padconf(int i2c_bus_id); -static void omap_i2c_clkconf(int i2c_bus_id); -static void omap_i2c_intr_enable(void); -static uint16_t omap_i2c_read_status(void); -static void omap_i2c_write_status(uint16_t mask); -static int omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, +static void rpi_i2c_flush(void); +static uint32_t rpi_i2c_poll(uint32_t mask); +static int rpi_i2c_bus_is_free(void); +static int rpi_i2c_soft_reset(void); +static void rpi_i2c_bus_init(void); +static void rpi_i2c_padconf(int i2c_bus_id); +static void rpi_i2c_clkconf(int i2c_bus_id); +static void rpi_i2c_intr_enable(void); +static uint32_t rpi_i2c_read_status(void); +static void rpi_i2c_write_status(uint32_t mask); +static int rpi_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop); -static int omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, +static int rpi_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, int dostop); /* * Performs the action in minix_i2c_ioctl_exec_t. */ static int -omap_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec) +rpi_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec) { int r; @@ -245,37 +143,37 @@ omap_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec) return EINVAL; } - omap_i2c_flush(); /* clear any garbage in the fifo */ + rpi_i2c_flush(); /* clear any garbage in the fifo */ /* Check bus busy flag before using the bus */ - r = omap_i2c_bus_is_free(); + r = rpi_i2c_bus_is_free(); if (r == 0) { log_warn(&log, "Bus is busy\n"); return EBUSY; } if (ioctl_exec->iie_cmdlen > 0) { - r = omap_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_cmd, + r = rpi_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_cmd, ioctl_exec->iie_cmdlen, !(I2C_OP_READ_P(ioctl_exec->iie_op))); if (r != OK) { - omap_i2c_soft_reset(); - omap_i2c_bus_init(); + rpi_i2c_soft_reset(); + rpi_i2c_bus_init(); return r; } } if (I2C_OP_READ_P(ioctl_exec->iie_op)) { - r = omap_i2c_read(ioctl_exec->iie_addr, ioctl_exec->iie_buf, + r = rpi_i2c_read(ioctl_exec->iie_addr, ioctl_exec->iie_buf, ioctl_exec->iie_buflen, I2C_OP_STOP_P(ioctl_exec->iie_op)); } else { - r = omap_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_buf, + r = rpi_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_buf, ioctl_exec->iie_buflen, I2C_OP_STOP_P(ioctl_exec->iie_op)); } if (r != OK) { - omap_i2c_soft_reset(); - omap_i2c_bus_init(); + rpi_i2c_soft_reset(); + rpi_i2c_bus_init(); return r; } @@ -289,20 +187,17 @@ omap_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec) * doing a read. */ static void -omap_i2c_flush(void) +rpi_i2c_flush(void) { int tries; int status; for (tries = 0; tries < 1000; tries++) { - status = omap_i2c_poll(1 << RRDY); - if ((status & (1 << RRDY)) != 0) { /* bytes available for reading */ + status = rpi_i2c_poll(BCM283X_STATUS_RXD); + if ((status & BCM283X_STATUS_RXD) != 0) { /* bytes available for reading */ /* consume the byte and throw it away */ - (void) read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA); - - /* clear the read ready flag */ - omap_i2c_write_status(1 << RRDY); + (void) read32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->FIFO); } else { break; /* buffer drained */ @@ -314,16 +209,16 @@ omap_i2c_flush(void) * Poll the status register checking the bits set in 'mask'. * Returns the status if any bits set or 0x0000 when the timeout is reached. */ -static uint16_t -omap_i2c_poll(uint16_t mask) +static uint32_t +rpi_i2c_poll(uint32_t mask) { spin_t spin; - uint16_t status; + uint32_t status; /* poll for up to 1 s */ spin_init(&spin, 1000000); do { - status = omap_i2c_read_status(); + status = rpi_i2c_read_status(); if ((status & mask) != 0) { /* any bits in mask set */ return status; } @@ -338,7 +233,7 @@ omap_i2c_poll(uint16_t mask) * expires (return 0). */ static int -omap_i2c_bus_is_free(void) +rpi_i2c_bus_is_free(void) { spin_t spin; uint16_t status; @@ -347,8 +242,8 @@ omap_i2c_bus_is_free(void) spin_init(&spin, 1000000); do { - status = omap_i2c_read_status(); - if ((status & (1 << BB)) == 0) { + status = rpi_i2c_read_status(); + if ((status & BCM283X_STATUS_TA) == 0) { return 1; /* bus is free */ } @@ -358,145 +253,95 @@ omap_i2c_bus_is_free(void) } static void -omap_i2c_clkconf(int i2c_bus_id) +rpi_i2c_clkconf(int i2c_bus_id) { clkconf_init(); - if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { - - clkconf_set(CM_ICLKEN1_CORE, BIT((15 + i2c_bus_id)), - 0xffffffff); - clkconf_set(CM_FCLKEN1_CORE, BIT((15 + i2c_bus_id)), - 0xffffffff); - - } else if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - - switch (i2c_bus_id) { - case 0: - clkconf_set(CM_WKUP_I2C0_CLKCTRL, BIT(1), 0xffffffff); - break; - case 1: - clkconf_set(CM_PER_I2C1_CLKCTRL, BIT(1), 0xffffffff); - break; - case 2: - clkconf_set(CM_PER_I2C2_CLKCTRL, BIT(1), 0xffffffff); - break; - default: - log_warn(&log, "Invalid i2c_bus_id\n"); - break; - } + switch (i2c_bus_id) { + case 0: + clkconf_set(CM_WKUP_I2C0_CLKCTRL, BIT(1), 0xffffffff); + break; + case 1: + clkconf_set(CM_PER_I2C1_CLKCTRL, BIT(1), 0xffffffff); + break; + default: + log_warn(&log, "Invalid i2c_bus_id\n"); + break; } clkconf_release(); } static void -omap_i2c_padconf(int i2c_bus_id) +rpi_i2c_padconf(int i2c_bus_id) { int r; u32_t pinopts; - if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - - /* use the options suggested in starterware driver */ - pinopts = - CONTROL_CONF_SLEWCTRL | CONTROL_CONF_RXACTIVE | - CONTROL_CONF_PUTYPESEL; - - switch (i2c_bus_id) { - case 0: - pinopts |= CONTROL_CONF_MUXMODE(0); - - r = sys_padconf(CONTROL_CONF_I2C0_SDA, 0xffffffff, - pinopts); - if (r != OK) { - log_warn(&log, "padconf failed (r=%d)\n", r); - } - - r = sys_padconf(CONTROL_CONF_I2C0_SCL, 0xffffffff, - pinopts); - if (r != OK) { - log_warn(&log, "padconf failed (r=%d)\n", r); - } - - log_debug(&log, "pinopts=0x%x\n", pinopts); - break; - - case 1: - pinopts |= CONTROL_CONF_MUXMODE(2); - - r = sys_padconf(CONTROL_CONF_SPI0_CS0, 0xffffffff, - pinopts); - if (r != OK) { - log_warn(&log, "padconf failed (r=%d)\n", r); - } - - r = sys_padconf(CONTROL_CONF_SPI0_D1, 0xffffffff, - pinopts); - if (r != OK) { - log_warn(&log, "padconf failed (r=%d)\n", r); - } - log_debug(&log, "pinopts=0x%x\n", pinopts); - break; - - case 2: - pinopts |= CONTROL_CONF_MUXMODE(3); - - r = sys_padconf(CONTROL_CONF_UART1_CTSN, 0xffffffff, - pinopts); - if (r != OK) { - log_warn(&log, "padconf failed (r=%d)\n", r); - } - - r = sys_padconf(CONTROL_CONF_UART1_RTSN, - 0xffffffff, pinopts); - if (r != OK) { - log_warn(&log, "padconf failed (r=%d)\n", r); - } - - log_debug(&log, "pinopts=0x%x\n", pinopts); - break; - - default: - log_warn(&log, "Invalid i2c_bus_id\n"); - break; + /* use the options suggested in starterware driver */ + pinopts = + CONTROL_CONF_SLEWCTRL | CONTROL_CONF_RXACTIVE | + CONTROL_CONF_PUTYPESEL; + switch (i2c_bus_id) { + case 0: + pinopts |= CONTROL_CONF_MUXMODE(0); + + r = sys_padconf(CONTROL_CONF_I2C0_SDA, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); } + + r = sys_padconf(CONTROL_CONF_I2C0_SCL, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + log_debug(&log, "pinopts=0x%x\n", pinopts); + break; + + case 1: + pinopts |= CONTROL_CONF_MUXMODE(2); + + r = sys_padconf(CONTROL_CONF_SPI0_CS0, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + r = sys_padconf(CONTROL_CONF_SPI0_D1, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + log_debug(&log, "pinopts=0x%x\n", pinopts); + break; + + default: + log_warn(&log, "Invalid i2c_bus_id\n"); + break; } - - /* nothing to do for the DM37XX */ } static int -omap_i2c_soft_reset(void) +rpi_i2c_soft_reset(void) { - spin_t spin; - /* Disable to do soft reset */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL, 0); micro_delay(50000); - /* Do a soft reset */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1 << SRST)); - /* Have to temporarily enable I2C to read RDONE */ - set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, (1<mapped_addr + rpi_i2c_bus->regs->CTRL, BCM283X_CTRL_I2C_EN | BCM283X_CTRL_CFIFO, + BCM283X_CTRL_I2C_EN | BCM283X_CTRL_CFIFO); micro_delay(50000); - /* wait up to 3 seconds for reset to complete */ - spin_init(&spin, 3000000); - do { - if (read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSS) & (1 << RDONE)) { - return OK; - } - - } while (spin_check(&spin)); - - log_warn(&log, "Tried soft reset, but bus never came back.\n"); - return EIO; + return OK; } static void -omap_i2c_intr_enable(void) +rpi_i2c_intr_enable(void) { int r; uint16_t intmask; @@ -504,8 +349,8 @@ omap_i2c_intr_enable(void) static int enabled = 0; if (!policy_set) { - r = sys_irqsetpolicy(omap_i2c_bus->irq, 0, - &omap_i2c_bus->irq_hook_kernel_id); + r = sys_irqsetpolicy(rpi_i2c_bus->irq, 0, + &rpi_i2c_bus->irq_hook_kernel_id); if (r == OK) { policy_set = 1; } else { @@ -514,12 +359,12 @@ omap_i2c_intr_enable(void) } if (policy_set && !enabled) { - r = sys_irqenable(&omap_i2c_bus->irq_hook_kernel_id); + r = sys_irqenable(&rpi_i2c_bus->irq_hook_kernel_id); if (r == OK) { enabled = 1; } else { log_warn(&log, "Couldn't enable irq %d (hooked)\n", - omap_i2c_bus->irq); + rpi_i2c_bus->irq); } } @@ -527,142 +372,110 @@ omap_i2c_intr_enable(void) * if just using polling (i.e. non-interrupt driver programming). */ intmask = 0; - intmask |= (1 << ROVR); - intmask |= (1 << AERR); - intmask |= (1 << XRDY); - intmask |= (1 << RRDY); - intmask |= (1 << ARDY); - intmask |= (1 << NACK); - intmask |= (1 << AL); + intmask |= BCM283X_CTRL_INTR; + intmask |= BCM283X_CTRL_INTT; + intmask |= BCM283X_CTRL_INTD; - if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQENABLE_SET, intmask); - } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IE, intmask); - } else { - log_warn(&log, "Don't know how to enable interrupts.\n"); - } + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL, intmask); } static void -omap_i2c_bus_init(void) +rpi_i2c_bus_init(void) { /* Ensure i2c module is disabled before setting prescalar & bus speed */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL, 0); micro_delay(50000); - /* Disable autoidle */ - set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1<mapped_addr + omap_i2c_bus->regs->I2C_PSC, - ((omap_i2c_bus->functional_clock / omap_i2c_bus->module_clock) - - 1)); - - /* Set the bus speed */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SCLL, - ((omap_i2c_bus->module_clock / (2 * omap_i2c_bus->bus_speed)) - - 7)); - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SCLH, - ((omap_i2c_bus->module_clock / (2 * omap_i2c_bus->bus_speed)) - - 5)); - - /* Set own I2C address */ - if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_OA, I2C_OWN_ADDRESS); - } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_OA0, I2C_OWN_ADDRESS); - } else { - log_warn(&log, "Don't know how to set own address.\n"); + uint32_t divider = (rpi_i2c_bus->functional_clock / rpi_i2c_bus->module_clock) - 1; + if (divider > BCM283X_I2C_CDIV_MAX || + divider < BCM283X_I2C_CDIV_MIN) { + log_warn(&log, "Incorrect divider\n"); } - /* Set TX/RX Threshold to 1 and disable I2C DMA */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_BUF, 0x0000); + if (divider & 0x01) + divider++; + + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->DIV, divider); + + /* Set own I2C address */ + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->SL_ADDR, I2C_OWN_ADDRESS); /* Bring the i2c module out of reset */ - set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, (1<mapped_addr + rpi_i2c_bus->regs->CTRL, BCM283X_CTRL_I2C_EN, BCM283X_CTRL_I2C_EN); micro_delay(50000); /* * Enable interrupts */ - omap_i2c_intr_enable(); + rpi_i2c_intr_enable(); } -static uint16_t -omap_i2c_read_status(void) +static uint32_t +rpi_i2c_read_status(void) { - uint16_t status = 0x0000; - - if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - /* TRM says to use RAW for polling for events */ - status = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQSTATUS_RAW); - } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { - status = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_STAT); - } else { - log_warn(&log, "Don't know how to read i2c bus status.\n"); - } - + uint16_t status = read32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->ST); return status; } static void -omap_i2c_write_status(uint16_t mask) +rpi_i2c_write_status(uint32_t mask) { - if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - /* write 1's to IRQSTATUS (not RAW) to clear the bits */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQSTATUS, mask); - } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_STAT, mask); - } else { - log_warn(&log, "Don't know how to clear i2c bus status.\n"); - } + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->ST, mask); } static int -omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop) +rpi_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop) { int r, i; - uint16_t conopts; - uint16_t pollmask; - uint16_t errmask; + uint32_t ctrl; + uint32_t pollmask; + uint32_t errmask; /* Set address of slave device */ - conopts = 0; addr &= MAX_I2C_SA_MASK; /* sanitize address (10-bit max) */ - if (addr > 0x7f) { - /* 10-bit extended address in use, need to set XSA */ - conopts |= (1 << XSA); + + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->DLEN, 1); + + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->FIFO, addr & 0xff); + + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->SL_ADDR, (addr >> XSA) | SL_ADDR_MASK); + + ctrl = read32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL); + ctrl |= BCM283X_CTRL_ST; + ctrl &= (~BCM283X_CTRL_READ); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL, ctrl); + + pollmask |= BCM283X_STATUS_DONE; + errmask |= BCM283X_STATUS_CLKT; + errmask |= BCM283X_STATUS_ERR; + + r = rpi_i2c_poll(pollmask | errmask); + if ((r & errmask) != 0) { + /* only debug log level because i2cscan trigers this */ + log_debug(&log, "Read Error! Status=%x\n", r); + return EIO; + } else if ((r & pollmask) == 0) { + log_warn(&log, "No RRDY Interrupt. Status=%x\n", r); + log_warn(&log, + "Likely cause: bad pinmux or no devices on bus\n"); + return EBUSY; } + + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->DLEN, buflen); - errmask = 0; - errmask |= (1 << ROVR); - errmask |= (1 << AERR); - errmask |= (1 << NACK); - errmask |= (1 << AL); + ctrl = read32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL); + ctrl |= BCM283X_CTRL_ST; + ctrl |= BCM283X_CTRL_READ; + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL, ctrl); - pollmask = 0; - pollmask |= (1 << RRDY); - - /* Set bytes to read and slave address */ - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CNT, buflen); - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SA, addr); - - /* Set control register */ - conopts |= (1 << I2C_EN); /* enabled */ - conopts |= (1 << MST); /* master mode */ - conopts |= (1 << STT); /* start condition */ - - if (dostop != 0) { - conopts |= (1 << STP); /* stop condition */ - } - - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts); + pollmask |= BCM283X_STATUS_RXD; + pollmask |= BCM283X_STATUS_RXF; for (i = 0; i < buflen; i++) { /* Data to read? */ - r = omap_i2c_poll(pollmask | errmask); + r = rpi_i2c_poll(pollmask | errmask); if ((r & errmask) != 0) { /* only debug log level because i2cscan trigers this */ log_debug(&log, "Read Error! Status=%x\n", r); @@ -675,75 +488,47 @@ omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop) } /* read a byte */ - buf[i] = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA) & 0xff; + buf[i] = read32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->FIFO) & 0xff; /* clear the read ready flag */ - omap_i2c_write_status(pollmask); + rpi_i2c_write_status(BCM283X_STATUS_DONE | errmask); } - r = omap_i2c_read_status(); - if ((r & (1 << NACK)) != 0) { - log_warn(&log, "NACK\n"); - return EIO; - } - - /* Wait for operation to complete */ - pollmask = (1<mapped_addr + rpi_i2c_bus->regs->CTRL, BCM283X_CTRL_CFIFO, BCM283X_CTRL_CFIFO); return 0; } static int -omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, int dostop) +rpi_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, int dostop) { int r, i; - uint16_t conopts; - uint16_t pollmask; - uint16_t errmask; + uint32_t pollmask; + uint32_t errmask; + uint32_t ctrl; /* Set address of slave device */ - conopts = 0; addr &= MAX_I2C_SA_MASK; /* sanitize address (10-bit max) */ - if (addr > 0x7f) { - /* 10-bit extended address in use, need to set XSA */ - conopts |= (1 << XSA); - } - pollmask = 0; - pollmask |= (1 << XRDY); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->DLEN, buflen + 1); - errmask = 0; - errmask |= (1 << ROVR); - errmask |= (1 << AERR); - errmask |= (1 << NACK); - errmask |= (1 << AL); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->FIFO, addr & 0xff); - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CNT, buflen); - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SA, addr); + pollmask |= BCM283X_STATUS_DONE; + pollmask |= BCM283X_STATUS_TXE; + pollmask |= BCM283X_STATUS_TXD; + errmask |= BCM283X_STATUS_CLKT; + errmask |= BCM283X_STATUS_ERR; - /* Set control register */ - conopts |= (1 << I2C_EN); /* enabled */ - conopts |= (1 << MST); /* master mode */ - conopts |= (1 << TRX); /* TRX mode */ - conopts |= (1 << STT); /* start condition */ - - if (dostop != 0) { - conopts |= (1 << STP); /* stop condition */ - } - - omap_i2c_write_status(0x7fff); - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts); + ctrl = read32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL); + ctrl |= BCM283X_CTRL_ST; + ctrl &= (~BCM283X_CTRL_READ); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->CTRL, ctrl); for (i = 0; i < buflen; i++) { /* Ready to write? */ - r = omap_i2c_poll(pollmask | errmask); + r = rpi_i2c_poll(pollmask | errmask); if ((r & errmask) != 0) { log_warn(&log, "Write Error! Status=%x\n", r); return EIO; @@ -752,32 +537,19 @@ omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, int dostop) return EBUSY; } - write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA, buf[i]); + write32(rpi_i2c_bus->mapped_addr + rpi_i2c_bus->regs->FIFO, buf[i]); /* clear the write ready flag */ - omap_i2c_write_status(pollmask); + rpi_i2c_write_status(BCM283X_STATUS_DONE | errmask); } - r = omap_i2c_read_status(); - if ((r & (1 << NACK)) != 0) { - log_warn(&log, "NACK\n"); - return EIO; - } - - /* Wait for operation to complete */ - pollmask = (1<mapped_addr + rpi_i2c_bus->regs->CTRL, BCM283X_CTRL_CFIFO, BCM283X_CTRL_CFIFO); return 0; } int -omap_interface_setup(int (**process) (minix_i2c_ioctl_exec_t * ioctl_exec), +rpi_interface_setup(int (**process) (minix_i2c_ioctl_exec_t * ioctl_exec), int i2c_bus_id) { int r; @@ -788,37 +560,34 @@ omap_interface_setup(int (**process) (minix_i2c_ioctl_exec_t * ioctl_exec), /* Fill in the function pointer */ - *process = omap_i2c_process; + *process = rpi_i2c_process; /* Select the correct i2c definition for this SoC */ - if (BOARD_IS_BBXM(machine.board_id)){ - omap_i2c_buses = dm37xx_i2c_buses; - omap_i2c_nbuses = DM37XX_OMAP_NBUSES; - } else if (BOARD_IS_BB(machine.board_id)){ - omap_i2c_buses = am335x_i2c_buses; - omap_i2c_nbuses = AM335X_OMAP_NBUSES; + if (BOARD_IS_RPI_2_B(machine.board_id) || BOARD_IS_RPI_3_B(machine.board_id)){ + rpi_i2c_buses = bcm283x_i2c_buses; + rpi_i2c_nbuses = BCM283X_rpi_NBUSES; } else { return EINVAL; } - if (i2c_bus_id < 0 || i2c_bus_id >= omap_i2c_nbuses) { + if (i2c_bus_id < 0 || i2c_bus_id >= rpi_i2c_nbuses) { return EINVAL; } /* select the bus to operate on */ - omap_i2c_bus = &omap_i2c_buses[i2c_bus_id]; + rpi_i2c_bus = &rpi_i2c_buses[i2c_bus_id]; /* Configure Pins */ - omap_i2c_padconf(i2c_bus_id); + rpi_i2c_padconf(i2c_bus_id); /* * Map I2C Registers */ /* Configure memory access */ - mr.mr_base = omap_i2c_bus->mr_base; /* start addr */ - mr.mr_limit = mr.mr_base + omap_i2c_bus->mr_size; /* end addr */ + mr.mr_base = rpi_i2c_bus->mr_base; /* start addr */ + mr.mr_limit = mr.mr_base + rpi_i2c_bus->mr_size; /* end addr */ /* ask for privileges to access the I2C memory range */ if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { @@ -826,51 +595,25 @@ omap_interface_setup(int (**process) (minix_i2c_ioctl_exec_t * ioctl_exec), } /* map the memory into this process */ - omap_i2c_bus->mapped_addr = (vir_bytes) vm_map_phys(SELF, - (void *) omap_i2c_bus->mr_base, omap_i2c_bus->mr_size); + rpi_i2c_bus->mapped_addr = (vir_bytes) vm_map_phys(SELF, + (void *) rpi_i2c_bus->mr_base, rpi_i2c_bus->mr_size); - if (omap_i2c_bus->mapped_addr == (vir_bytes) MAP_FAILED) { + if (rpi_i2c_bus->mapped_addr == (vir_bytes) MAP_FAILED) { panic("Unable to map i2c registers"); } /* Enable Clocks */ - omap_i2c_clkconf(i2c_bus_id); + rpi_i2c_clkconf(i2c_bus_id); /* Perform a soft reset of the I2C module to ensure a fresh start */ - r = omap_i2c_soft_reset(); + r = rpi_i2c_soft_reset(); if (r != OK) { /* module didn't come back up :( */ return r; } /* Bring up I2C module */ - omap_i2c_bus_init(); - - /* Get I2C Revision */ - if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { - /* I2C_REVLO revision: major (bits 10-8), minor (bits 5-0) */ - i2c_rev = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_REVNB_LO); - major = (i2c_rev >> 8) & 0x07; - minor = i2c_rev & 0x3f; - - } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { - /* I2C_REV revision: major (bits 7-4), minor (bits 3-0) */ - i2c_rev = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_REV); - major = (i2c_rev >> 4) & 0x0f; - minor = i2c_rev & 0x0f; - } else { - panic("Don't know how to read i2c revision."); - } - - if (major != omap_i2c_bus->major || minor != omap_i2c_bus->minor) { - log_warn(&log, "Unrecognized value in I2C_REV register.\n"); - log_warn(&log, "Read: 0x%x.0x%x | Expected: 0x%x.0x%x\n", - major, minor, omap_i2c_bus->major, omap_i2c_bus->minor); - } - - /* display i2c revision information for debugging purposes */ - log_debug(&log, "i2c_%d: I2C rev 0x%x.0x%x\n", (i2c_bus_id + 1), - major, minor); + rpi_i2c_bus_init(); return OK; } diff --git a/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.h b/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.h index 70e56b432..7052e3935 100644 --- a/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.h +++ b/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c.h @@ -5,6 +5,6 @@ #include #include "rpi_i2c_registers.h" -int omap_interface_setup(int (**process)(minix_i2c_ioctl_exec_t *ioctl_exec), int i2c_bus_id); +int rpi_interface_setup(int (**process)(minix_i2c_ioctl_exec_t *ioctl_exec), int i2c_bus_id); #endif /* _RPI_I2C_H */ diff --git a/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c_registers.h b/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c_registers.h index fa4be6f16..4cea16bcc 100644 --- a/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c_registers.h +++ b/minix/drivers/bus/i2c/arch/earm/rpi/rpi_i2c_registers.h @@ -1,152 +1,84 @@ #ifndef _RPI_I2C_REGISTERS_H #define _RPI_I2C_REGISTERS_H -/* I2C Addresses for am335x (BeagleBone White / BeagleBone Black) */ +/* I2C Addresses for bcm2835 */ /* IRQ Numbers */ -#define AM335X_I2C0_IRQ 70 -#define AM335X_I2C1_IRQ 71 -#define AM335X_I2C2_IRQ 30 +#define BCM283X_I2C0_IRQ 47 /* Base Addresses */ -#define AM335X_I2C0_BASE 0x44e0b000 -#define AM335X_I2C1_BASE 0x4802a000 -#define AM335X_I2C2_BASE 0x4819c000 +#define BCM283X_I2C0_BASE 0x3f205000 +#define BCM283X_I2C1_BASE 0x3f804000 /* Size of I2C Register Address Range */ -#define AM335X_I2C0_SIZE 0x1000 -#define AM335X_I2C1_SIZE 0x1000 -#define AM335X_I2C2_SIZE 0x1000 +#define BCM283X_I2C0_SIZE 0x1000 +#define BCM283X_I2C1_SIZE 0x1000 /* Register Offsets */ -#define AM335X_I2C_REVNB_LO 0x00 -#define AM335X_I2C_REVNB_HI 0x04 -#define AM335X_I2C_SYSC 0x10 -#define AM335X_I2C_IRQSTATUS_RAW 0x24 -#define AM335X_I2C_IRQSTATUS 0x28 -#define AM335X_I2C_IRQENABLE_SET 0x2c -#define AM335X_I2C_IRQENABLE_CLR 0x30 -#define AM335X_I2C_WE 0x34 -#define AM335X_I2C_DMARXENABLE_SET 0x38 -#define AM335X_I2C_DMATXENABLE_SET 0x3c -#define AM335X_I2C_DMARXENABLE_CLR 0x40 -#define AM335X_I2C_DMATXENABLE_CLR 0x44 -#define AM335X_I2C_DMARXWAKE_EN 0x48 -#define AM335X_I2C_DMATXWAKE_EN 0x4c -#define AM335X_I2C_SYSS 0x90 -#define AM335X_I2C_BUF 0x94 -#define AM335X_I2C_CNT 0x98 -#define AM335X_I2C_DATA 0x9c -#define AM335X_I2C_CON 0xa4 -#define AM335X_I2C_OA 0xa8 -#define AM335X_I2C_SA 0xac -#define AM335X_I2C_PSC 0xb0 -#define AM335X_I2C_SCLL 0xb4 -#define AM335X_I2C_SCLH 0xb8 -#define AM335X_I2C_SYSTEST 0xbc -#define AM335X_I2C_BUFSTAT 0xc0 -#define AM335X_I2C_OA1 0xc4 -#define AM335X_I2C_OA2 0xc8 -#define AM335X_I2C_OA3 0xcc -#define AM335X_I2C_ACTOA 0xd0 -#define AM335X_I2C_SBLOCK 0xd4 +#define BCM283X_CTRL 0x00 +#define BCM283X_STATUS 0x04 +#define BCM283X_DLEN 0x08 +#define BCM283X_SL_ADDR 0x0C +#define BCM283X_FIFO 0x10 +#define BCM283X_DIV 0x14 +#define BCM283X_DEL 0x18 +#define BCM283X_CLKT 0x1c /* Constants */ -#define AM335X_FUNCTIONAL_CLOCK 96000000 /* 96 MHz */ -#define AM335X_MODULE_CLOCK 12000000 /* 12 MHz */ +#define BCM283X_FUNCTIONAL_CLOCK 96000000 /* 96 MHz */ +#define BCM283X_MODULE_CLOCK 12000000 /* 12 MHz */ -/* I2C_REV value found on the BeagleBone / BeagleBone Black */ -#define AM335X_REV_MAJOR 0x00 -#define AM335X_REV_MINOR 0x0b - -/* I2C Addresses for dm37xx (BeagleBoard-xM) */ - -/* IRQ Numbers */ -#define DM37XX_I2C0_IRQ 56 -#define DM37XX_I2C1_IRQ 57 -#define DM37XX_I2C2_IRQ 61 - -/* Base Addresses */ -#define DM37XX_I2C0_BASE 0x48070000 -#define DM37XX_I2C1_BASE 0x48072000 -#define DM37XX_I2C2_BASE 0x48060000 - -/* Size of I2C Register Address Range */ -#define DM37XX_I2C0_SIZE 0x1000 -#define DM37XX_I2C1_SIZE 0x1000 -#define DM37XX_I2C2_SIZE 0x1000 - -/* Register Offsets */ -#define DM37XX_I2C_REV 0x00 -#define DM37XX_I2C_IE 0x04 -#define DM37XX_I2C_STAT 0x08 -#define DM37XX_I2C_WE 0x0C -#define DM37XX_I2C_SYSS 0x10 -#define DM37XX_I2C_BUF 0x14 -#define DM37XX_I2C_CNT 0x18 -#define DM37XX_I2C_DATA 0x1c -#define DM37XX_I2C_SYSC 0x20 -#define DM37XX_I2C_CON 0x24 -#define DM37XX_I2C_OA0 0x28 -#define DM37XX_I2C_SA 0x2c -#define DM37XX_I2C_PSC 0x30 -#define DM37XX_I2C_SCLL 0x34 -#define DM37XX_I2C_SCLH 0x38 -#define DM37XX_I2C_SYSTEST 0x3c -#define DM37XX_I2C_BUFSTAT 0x40 -#define DM37XX_I2C_OA1 0x44 -#define DM37XX_I2C_OA2 0x48 -#define DM37XX_I2C_OA3 0x4c -#define DM37XX_I2C_ACTOA 0x50 -#define DM37XX_I2C_SBLOCK 0x54 - -/* Constants */ -#define DM37XX_FUNCTIONAL_CLOCK 96000000 /* 96 MHz */ -#define DM37XX_MODULE_CLOCK 19200000 /* 19.2 MHz */ - -#define DM37XX_REV_MAJOR 0x04 -#define DM37XX_REV_MINOR 0x00 +#define BCM283X_I2C_CDIV_MIN 0x0002 +#define BCM283X_I2C_CDIV_MAX 0xFFFE /* Shared Values */ -#define BUS_SPEED_100KHz 100000 /* 100 KHz */ -#define BUS_SPEED_400KHz 400000 /* 400 KHz */ -#define I2C_OWN_ADDRESS 0x01 +#define BUS_SPEED_100KHz 100000 /* 100 KHz */ +#define BUS_SPEED_400KHz 400000 /* 400 KHz */ +#define I2C_OWN_ADDRESS 0x01 /* Masks */ #define MAX_I2C_SA_MASK (0x3ff) /* Highest 10 bit address -- 9..0 */ +#define SL_ADDR_MASK (0x78) /* Mask for slave address (the last two bits + are the most significant of the addr)*/ /* Bit Offsets within Registers (only those used are listed) */ -/* Same offsets for both dm37xx and am335x */ +#define I2C_EN 15 +#define MST 10 +#define TRX 9 +#define XSA 8 +#define STP 1 +#define STT 0 -#define I2C_EN 15 /* I2C_CON */ -#define MST 10 /* I2C_CON */ -#define TRX 9 /* I2C_CON */ -#define XSA 8 /* I2C_CON */ -#define STP 1 /* I2C_CON */ -#define STT 0 /* I2C_CON */ +#define CLKACTIVITY_S 9 +#define CLKACTIVITY_I 8 +#define SMART_WAKE_UP 4 +#define NO_IDLE_MODE 3 +#define SRST 1 +#define AUTOIDLE 0 -#define CLKACTIVITY_S 9 /* I2C_SYSC */ -#define CLKACTIVITY_I 8 /* I2C_SYSC */ -#define SMART_WAKE_UP 4 /* I2C_SYSC */ -#define NO_IDLE_MODE 3 /* I2C_SYSC */ -#define SRST 1 /* I2C_SYSC */ -#define AUTOIDLE 0 /* I2C_SYSC */ +#define RDONE 0 -#define RDONE 0 /* I2C_SYSS */ +#define RXFIFO_CLR 14 +#define TXFIFO_CLR 6 -#define RXFIFO_CLR 14 /* I2C_BUF */ -#define TXFIFO_CLR 6 /* I2C_BUF */ +#define BCM283X_STATUS_TA 0x00 +#define BCM283X_STATUS_DONE 0x01 +#define BCM283X_STATUS_TXD 0x10 +#define BCM283X_STATUS_RXD 0x20 +#define BCM283X_STATUS_TXE 0x40 +#define BCM283X_STATUS_RXF 0x80 +#define BCM283X_STATUS_ERR 0x100 +#define BCM283X_STATUS_CLKT 0x200 -#define BB 12 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define ROVR 11 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define AERR 7 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define XRDY 4 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define RRDY 3 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define ARDY 2 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define NACK 1 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ -#define AL 0 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define BCM283X_CTRL_READ 0x00 +#define BCM283X_CTRL_ST 0x20 +#define BCM283X_CTRL_CFIFO 0x30 +#define BCM283X_CTRL_INTD 0x100 +#define BCM283X_CTRL_INTT 0x200 +#define BCM283X_CTRL_INTR 0x400 +#define BCM283X_CTRL_I2C_EN 0x8000 #endif /* _RPI_I2C_REGISTERS_H */ diff --git a/minix/drivers/bus/i2c/i2c.c b/minix/drivers/bus/i2c/i2c.c index 58371c7b1..d28c70d6c 100644 --- a/minix/drivers/bus/i2c/i2c.c +++ b/minix/drivers/bus/i2c/i2c.c @@ -438,6 +438,12 @@ sef_cb_init(int type, sef_init_info_t * UNUSED(info)) if (r != OK) { return r; } + } else if (BOARD_IS_RPI_2_B(machine.board_id) || BOARD_IS_RPI_3_B(machine.board_id)){ + /* Set callback and initialize the bus */ + r = rpi_interface_setup(&process, i2c_bus_id); + if (r != OK) { + return r; + } } else { return ENODEV; } diff --git a/minix/drivers/bus/i2c/i2c.conf b/minix/drivers/bus/i2c/i2c.conf new file mode 100644 index 000000000..99dc1f925 --- /dev/null +++ b/minix/drivers/bus/i2c/i2c.conf @@ -0,0 +1,21 @@ +service i2c +{ + system + PRIVCTL # 4 + IRQCTL # 19 + PADCONF # 57 + ; + irq + # DM37XX (BeagleBoard-xM) + 56 # I2C module 1 + 57 # I2C module 2 + 61 # I2C module 3 + # AM335X (BeagleBone) + 70 # I2C module 1 + 71 # I2C module 2 + 30 # I2C module 3 + # BCM283X (RaspberryPi 2,3) + 47 + ; + ipc SYSTEM RS DS; +}; diff --git a/releasetools/arm_sdimage_rpi.sh b/releasetools/arm_sdimage_rpi.sh index d05a2d580..93283f43e 100755 --- a/releasetools/arm_sdimage_rpi.sh +++ b/releasetools/arm_sdimage_rpi.sh @@ -121,6 +121,8 @@ device_tree=bcm2709-rpi-2-b.dtb [all] device_tree_address=0x100 kernel=minix_rpi.bin + +dtparam=i2c_arm=on EOF ${CROSS_TOOLS}/nbmakefs -t msdos -s $FAT_SIZE -O $FAT_START -o "F=32,c=1" ${IMG} ${ROOT_DIR} >/dev/null