[Soekris] 4801 GPIO

Steven Finnegan sjf at ctrlsft.com
Tue Mar 20 13:50:06 UTC 2007


On Mar 19, 2007, at 13:25 , Peter Wood wrote:

> Heya Steven,
>
> Sorry to contact you off list, but I'm trying to do similar things  
> to what you tried in January.
>
>> Is there something that needs to be done to program the GPIO pins  
>> as  outputs? Also, the "output bit numbers" (values put into  
>> "ledxb") are  not obvious. The 4801 manual shows the pc87366 pins  
>> mapped to GPIO  pins, with several apparent typos (GPIO24 and  
>> GPIO26 are listed  twice). I've tried both versions below, but  
>> neither seems to work.  Also, the error led is "20", which if the  
>> pc87366 bit numbers are  used would be GPIO 0 on pin #3. Although  
>> I can flash the error led,  NONE of the GPIO pins on JP5 are moving
>>
> Did anyone ever reply or did you manage to figure it out yourself?  
> If you got somewhere would you mind sharing the pins that you used?
>
> Cheers,
>
> Peter.
>


Peter
Well, I was successful, after much work, in using the GPIO outputs.  
It was NOT as simple as expanding on the error-led. The error-led  
uses the CPU's gpio line, whereas the "GPIO output pins" use the  
SuperIO chip's (PC87366) GPIO. So I had to figure out how to talk to  
that device.

I have attached a patch file that will modify the geode.c file to  
create gpio lines in the /dev/led directory.  Hope this helps

*** geode.c.orig        Wed Jan 31 15:24:28 2007
--- geode.c.new Thu Feb  1 13:19:20 2007
***************
*** 71,79 ****
--- 71,127 ----
   static unsigned       gpio;
   static unsigned       geode_counter;

+ /* begin sjf */
+ static unsigned sio_gpio;
+ static struct cdev* led[12];
+ static int ledb[12];
+ /* end sjf */
+
   static struct cdev *led1, *led2, *led3;
   static int    led1b, led2b, led3b;

+ /* begin sjf */
+ static void sio_led_func( void *ptr, int onoff)
+ {
+         unsigned int u;
+         int bit;
+       int port;
+
+         bit = *(int *)ptr;
+         if (bit < 0) {
+                 bit = -bit;
+                 onoff = !onoff;
+         }
+
+       switch( bit & 0x70)     // find proper port
+       {
+       default:
+               return;         // improper port number
+       case 0x00:
+               port = sio_gpio + 0;
+               break;
+       case 0x10:
+               port = sio_gpio + 4;
+               break;
+       case 0x20:
+               port = sio_gpio + 8;
+               break;
+       case 0x30:
+               port = sio_gpio + 10;
+               break;
+       }
+
+       bit = bit & 0x07;
+
+         u = inb(port);
+         if (onoff)
+                 u |= 1 << bit;
+         else
+                 u &= ~(1 << bit);
+         outb(port, u);
+ }
+ /* end sjf */
+
   static void
   led_func(void *ptr, int onoff)
   {
***************
*** 183,188 ****
--- 231,284 ----
                 printf("Geode GPIO@ = %x\n", gpio);
                 if ( bios_oem_strings(&bios_soekris,
                                         bios_oem, BIOS_OEM_MAXLEN) >  
0 ) {
+                       /* begin sjf (SIO -> SuperIO device, PC87366)*/
+ #define SIO_INDEX             0x2e
+ #define SIO_DATA              0x2f
+ #define SIO_ID_ADD            0x20
+ #define SIO_ACTIVATE  0x30
+ #define SIO_ID                0xe9
+ #define SIO_DEVICE_REG        0x07
+ #define SIO_GPIO_DEV          0x07
+ #define SIO_IOPORT0HI 0x60
+ #define SIO_IOPORT0LO 0x61
+ #define SIO_GPIOPINSEL        0xf0
+ #define SIO_GPIOPINCONF       0xf1
+                       int i;
+                       outb( SIO_INDEX, SIO_ID_ADD);
+                       i=inb(SIO_DATA);
+                       if( i != SIO_ID)
+                               printf( "SuperIO ID Failure 0x%x\n", i);
+                       else
+                       {
+                               int pins[]={0x20, 0x21, 0x22, 0x23,  
0x24, 0x25,
+                                       0x26, 0x27, 0x04, 0x05, 0x13,  
0x12};
+                               char* name[] =  
{"gpio00","gpio01","gpio02","gpio03","gpio04","gpio05",
+                                        
"gpio06","gpio07","gpio08","gpio09","gpio10","gpio11"};
+                               outb(SIO_INDEX, SIO_DEVICE_REG);
+                               outb(SIO_DATA, SIO_GPIO_DEV);   //  
point to gpio device
+                               // get GPIO address
+                               outb(SIO_INDEX, SIO_IOPORT0HI);
+                               sio_gpio = inb(SIO_DATA) << 8;
+                               outb(SIO_INDEX, SIO_IOPORT0LO);
+                               sio_gpio |= inb(SIO_DATA);
+                               printf("Geode SIO_GPIO@ = %x\n",  
sio_gpio);
+                               outb(SIO_INDEX, SIO_ACTIVATE);
+                               i=inb(SIO_DATA) & 0x01;
+                               if( !i )
+                                       printf("SIO_GPIO not enabled 
\n");
+                               else
+                                       for( i=0; i<12; i++)
+                                       { /* setup the pins */
+                                               outb(SIO_INDEX,  
SIO_GPIOPINSEL);
+                                               outb(SIO_DATA, pins 
[i]); // select the pin
+                                               outb(SIO_INDEX,  
SIO_GPIOPINCONF);
+                                               outb(SIO_DATA,  
0x01);   // Pullup off, Open drain, Out enab
+
+                                               ledb[i] = -pins[i];
+                                               led[i] = led_create 
(sio_led_func, &ledb[i], name[i]);
+                                       }
+                       }
+                       /* end sjf */
                         led1b = 20;
                         led1 = led_create(led_func, &led1b, "error");
                 } else if ( bios_oem_strings(&bios_pcengines,












****************************
Controlsoft L.P.
Steven Finnegan
Web: www.ctrlsft.com
Email: sjf at ctrlsft.com
Phone:   972-540-9935
****************************




More information about the Soekris-tech mailing list