I've been looking at the sopine compute module and clusterboard schematics, and it looks like there are no pullup resistors on the I2C bus at all (but I see mention that there is on the sopine baseboard, but a problem with VCC_CTP not being turned on??)
Since you have a working setup, it might be worth trying out the script mentioned here, to see if you can enable the internal pullups on the I2C pins... that might just do the trick, and remove the need for the 3v3 regulator just for pullups (as I2C does need the bus pulled up). I'm sure I've seen some mention of a way to enable pullups through sysfs, which would be easier, but I could be wrong there...
It is a bit annoying looking at the 20 pin header at last that pin17 wasn't brought out as a 3v3 pin... 5v is there on pin 1, so 17 would have been the perfect place to bring it out... as it may be needed to make proper use of the GPIO pins... unless you want to start using buffers or external voltage regulation. Edit: Just had an evil thought... if the GPIOs are 3v3 and you're not using the SPI bus... just use one of the GPIOs pulled high as the 3v3 supply... presuming there's enough drive current to do the necessary pullup... (which I can't see being problematic... but it would need verifying...)... :-D
Credit goes to khogh for putting this together for the pine64...
Since you have a working setup, it might be worth trying out the script mentioned here, to see if you can enable the internal pullups on the I2C pins... that might just do the trick, and remove the need for the 3v3 regulator just for pullups (as I2C does need the bus pulled up). I'm sure I've seen some mention of a way to enable pullups through sysfs, which would be easier, but I could be wrong there...
It is a bit annoying looking at the 20 pin header at last that pin17 wasn't brought out as a 3v3 pin... 5v is there on pin 1, so 17 would have been the perfect place to bring it out... as it may be needed to make proper use of the GPIO pins... unless you want to start using buffers or external voltage regulation. Edit: Just had an evil thought... if the GPIOs are 3v3 and you're not using the SPI bus... just use one of the GPIOs pulled high as the 3v3 supply... presuming there's enough drive current to do the necessary pullup... (which I can't see being problematic... but it would need verifying...)... :-D
Credit goes to khogh for putting this together for the pine64...
Code:
/*
* To compile the code
* gcc EnableI2cPullup.c -o EnableI2cPullup
*
* Make sure the program is run under root privilage
* sudo ./EnableI2cPullup
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
/*
* GPIO Base Address for Allwinner CPU
*/
#define SUNXI_GPIO_BASE0 (0x01C20800)
#define SUNXI_GPIO_BASE1 (0x01F02C00)
/*
* Offset address for PH wher I2c1 is located
* pull up/down value
* 0 = off
* 1 = Pull up
* 2 = Pull down
*/
#define PHPULL0 ((7*0x24)+0x1C)
#define PCPULL0 ((2*0x24)+0x1C)
#define PLPULL0 ((0*0x24)+0x1C)
#define PAGE_SIZE (4*1024)
volatile unsigned *gpio0;
volatile unsigned *gpio1;
// Setup the I/O memory map
void setup_io(int gpiono)
{
int mem_fd;
void *gpio_map;
unsigned int addr_start, addr_offset, PageSize, PageMask;
PageSize = PAGE_SIZE;
PageMask = (~(PageSize-1));
if (gpiono==0) {
addr_start = SUNXI_GPIO_BASE0 & PageMask;
addr_offset = SUNXI_GPIO_BASE0 & ~PageMask;
}
else {
addr_start = SUNXI_GPIO_BASE1 & PageMask;
addr_offset = SUNXI_GPIO_BASE1 & ~PageMask;
}
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
exit(-1);
}
/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
PageSize, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
addr_start //Offset to GPIO peripheral
);
close(mem_fd); //No need to keep mem_fd open after mmap
if (gpio_map == MAP_FAILED) {
printf("mmap error %d\n", errno);//Print errno
exit(-1);
}
// Always use volatile pointer!
if (gpiono==0) {
gpio0 = (volatile unsigned *)(gpio_map+addr_offset);
}
else {
gpio1 = (volatile unsigned *)(gpio_map+addr_offset);
}
}
// Read from the GPIO
uint32_t readgpio(int gpiono, uint32_t offset)
{
volatile uint32_t *addr;
if (gpiono==0) {
addr=(volatile uint32_t *)((uint64_t)gpio0+offset);
}
else {
addr=(volatile uint32_t *)((uint64_t)gpio1+offset);
}
//printf("Reading: gpiobase %08lx, offset %04x, final addr %08lx\r\n",(uint64_t)(gpio),offset,(uint64_t)(addr));
return(*(addr));
}
// Write into GPIO
void writegpio(int gpiono, uint32_t offset,uint32_t data)
{
volatile uint32_t *addr;
if (gpiono==0) {
addr=(volatile uint32_t *)((uint64_t)gpio0+offset);
}
else {
addr=(volatile uint32_t *)((uint64_t)gpio1+offset);
}
*addr=data;
//printf("Writing: gpiobase %08lx, offset %04x, final addr %08lx writedata %04x, rereaddata %04x\r\n",(uint64_t)(gpio),offset,(uint64_t)(addr),data,(*addr));
}
#define bitno(pin) ((pin)*2)
int main (int argc, char *argv []){
uint32_t tmp;
setup_io(0); //setup the io
setup_io(1); //setup the io
tmp=readgpio(0,PHPULL0); //read from the gpio register
tmp &= ~((3<<bitno(2))|(3<<bitno(3))|(3<<bitno(5))|(3<<bitno(6))); //mask off the bit 2 and 3
tmp |=((1<<bitno(2))|(1<<bitno(3))|(1<<bitno(5))|(1<<bitno(6))); //set bit 2 and 3 to enable pull up.
writegpio(0,PHPULL0,tmp); //write the setting into the gpio register
tmp=readgpio(0,PCPULL0);
tmp &= ~((3<<bitno(5))|(3<<bitno(9)));
tmp |=((1<<bitno(5))|(1<<bitno(9)));
writegpio(0,PCPULL0,tmp);
tmp=readgpio(1,PLPULL0);
tmp &= ~((3<<bitno(8))|(3<<bitno(9)));
tmp |=((1<<bitno(8))|(1<<bitno(9)));
writegpio(1,PLPULL0,tmp);
printf("I/O Port for Pine64 I2c POT pull up enabled.\n\r");
return(0);
}