Author: rminnich
Date: 2006-09-19 00:52:24 +0200 (Tue, 19 Sep 2006)
New Revision: 2421

Added:
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/Config.lb
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/chip.h
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.c
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.h
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_setup.c
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_smbus.c
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_ide.c
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus.h
   trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus2.h
Log:
add the _lx flavor of the 5536. This will later be merged into the 
cs5536, but I don't want to mess up the OLPC, and we really need the lx
support NOW.


Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/Config.lb
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/Config.lb                   
        (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/Config.lb   2006-09-18 
22:52:24 UTC (rev 2421)
@@ -0,0 +1,5 @@
+config chip.h
+driver cs5536.o
+driver cs5536_usb.o
+#driver cs5536_pci.o
+#driver cs5536_ide.o

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/chip.h
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/chip.h                      
        (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/chip.h      2006-09-18 
22:52:24 UTC (rev 2421)
@@ -0,0 +1,53 @@
+#ifndef _SOUTHBRIDGE_AMD_CS5536
+#define _SOUTHBRIDGE_AMD_CS5536
+
+#define MAX_UNWANTED_VPCI 10   /* increase if needed */
+
+extern struct chip_operations southbridge_amd_cs5536_ops;
+
+struct southbridge_amd_cs5536_config {
+       /* interrupt enable for LPC bus */
+       int lpc_serirq_enable;  /* how to enable, e.g. 0x80 */
+       int lpc_irq;            /* what to enable, e.g. 0x18 */
+       int enable_ide_nand_flash; /* if you are using nand flash instead of 
IDE drive */
+
+       /* following are IRQ numbers for various southbridge resources.
+        * these are configured and PCI headers are set */
+       
+       int isa_irq;            // f.0, 1022:2090
+       int flash_irq;          // f.1, 1022:2091
+
+       // ide irq is tied to IRQ14, this can only be enabled or disabled
+       int enable_ide_irq;             // f.2, 1022:2092
+
+       int audio_irq;          // f.3, 1022:2093
+       
+       int usb_irq;    // f.4,5,6,7, 1022:2094
+       // only one irq source for all usb devices
+
+       // internal UART IRQs
+       int uart0_irq;
+       int uart1_irq;
+
+       /* GPIO to IRQ mapping, intended to use for PCI IRQ's.
+        * This only does physical mapping, no PCI headers are configured
+        * PCI configuration is mainboard-specific and should be done in 
mainboard.c
+        */
+       // pci IRQs A-D. Set this to 0 to disable.
+       int pci_int[4];
+       // and their GPIO pins
+       int pci_int_pin[4];
+
+
+       // Enable KEL keyboard IRQ2
+       int enable_kel_keyb_irq;
+       // Enable KEL mouse IRQ12
+       int enable_kel_mouse_irq;
+       // Configure KEL Emulation IRQ (input Y13)
+       int kel_emul_irq;
+
+       /* the following allow you to disable unwanted virtualized PCI devices 
*/
+       unsigned long unwanted_vpci[MAX_UNWANTED_VPCI];
+};
+
+#endif /* _SOUTHBRIDGE_AMD_CS5536 */

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.c
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.c                    
        (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.c    2006-09-18 
22:52:24 UTC (rev 2421)
@@ -0,0 +1,331 @@
+
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <device/pci_ids.h>
+#include <console/console.h>
+#include <cpu/amd/lxdef.h>
+#include <cpu/x86/msr.h>
+#include "chip.h"
+
+// prototypes here, avoid warnings
+void setup_i8259(void);
+void pci_assign_irqs(unsigned bus, unsigned slot, const unsigned char 
pIntAtoD[4]);
+void print_conf(void);
+
+#define PIN_OPT_IDE            (1ULL<<0)       /* 0 for flash, 1 for IDE */
+
+/* Intended value for LBAR_FLSH0: 4KiB, enabled, MMIO, NAND, @0x20000000 */
+/* NOTE: no longer used, prune at some point */
+/* OOPS: steve's changes don't work, so we have to keep this */
+msr_t flsh1 = { .hi=0xFFFFF007, .lo=0x20000000};
+
+// ide is ENABLED by default (in early init), this disables it if neccesary
+// and enables flash
+static void enable_ide_nand_flash()
+{
+       msr_t msr;
+       printk_debug("cs5536: %s\n", __FUNCTION__);
+#if 1
+       printk_err("WARNING: using deprecated flash enable mechanism\n");
+       /* steve took this one out ... not sure if needed or not */
+       msr = rdmsr(MDD_LBAR_FLSH1);
+
+       if ( ((msr.hi) & 7) != 7) {
+               printk_debug("MDD_LBAR_FLSH1 was 0x%08x%08x\n", msr.hi,msr.lo);
+               wrmsr(MDD_LBAR_FLSH1, flsh1);
+       }
+       msr = rdmsr(MDD_LBAR_FLSH1);
+       printk_debug("MDD_LBAR_FLSH1 is 0x%08x%08x\n", msr.hi,msr.lo);
+#endif
+       msr = rdmsr(MDD_PIN_OPT);
+       if (msr.lo & PIN_OPT_IDE) {
+               printk_debug("MDD_PIN_OPT was 0x%08x%08x\n", msr.hi,msr.lo);
+               msr.lo &= ~PIN_OPT_IDE;
+               wrmsr(MDD_PIN_OPT, msr);
+       }
+       msr = rdmsr(MDD_PIN_OPT);
+       printk_debug("MDD_PIN_OPT is 0x%08x%08x\n", msr.hi,msr.lo);
+
+       msr = rdmsr(MDD_NANDF_DATA);
+       if (msr.lo != 0x00100010) {
+               printk_debug("MDD_NANDF_DATA was 0x%08x%08x\n", msr.hi,msr.lo);
+               msr.lo = 0x00100010;
+               wrmsr(MDD_NANDF_DATA, msr);
+       }
+       msr = rdmsr(MDD_NANDF_DATA);
+       printk_debug("MDD_NANDF_DATA is 0x%08x%08x\n", msr.hi,msr.lo);
+
+       msr = rdmsr(MDD_NADF_CNTL);
+       if (msr.lo != 0x0010) {
+               printk_debug("MDD_NADF_CNTL was 0x%08x%08x\n", msr.hi,msr.lo);
+               msr.lo = 0x0010;
+               wrmsr(MDD_NADF_CNTL, msr);
+       }
+       msr = rdmsr(MDD_NADF_CNTL);
+       printk_debug("MDD_NADF_CNTL is 0x%08x%08x\n", msr.hi,msr.lo);
+       printk_debug("cs5536: EXIT %s\n", __FUNCTION__);
+}
+
+/* note: this is a candidate for inclusion in src/devices/pci_device.c */
+// set pci headers to indicate correct IRQ number of the device
+void setup_irq(unsigned irq, unsigned level, unsigned bus, unsigned device, 
unsigned fn)
+{
+       if (irq)
+       {
+               unsigned devfn = PCI_DEVFN(device,fn);
+               device_t dev  = dev_find_slot(bus, devfn);
+               if (dev) 
+               {
+                       printk_debug("%s: assigning IRQ %d to %x.%x (0x%x)\n", 
+                               __FUNCTION__, irq, device, fn, devfn);
+
+                       pci_write_config8(dev, PCI_INTERRUPT_LINE, irq);
+                       if (level) pci_level_irq(irq);
+               }
+               else
+                       printk_err("%s: Can't find PCI device function 0x%x\n", 
__FUNCTION__, devfn);
+       }
+}
+
+// map an Y or Z irq source in programmable irq controller 
+// dev 0..15 Y, 16...31 Z
+void map_pic_irq(unsigned int dev, unsigned int irq){
+       msr_t msr;
+       unsigned long mask;
+       unsigned long val;
+       
+       
+       mask = ~(0xF<<((dev&7)<<2));
+       val = irq<<((dev&7)<<2);
+       
+       printk_debug("%s: mapping %d to src %d: mask %x val %x\n", 
+                               __FUNCTION__, irq, dev,mask,val);
+       
+       switch (dev & 0x18){
+               case 0:
+                       msr=rdmsr(MDD_IRQM_YLOW);
+                       msr.lo = (msr.lo & mask) | val;
+                       wrmsr(MDD_IRQM_YLOW,msr);
+                       break;
+               case 8:
+                       msr=rdmsr(MDD_IRQM_YHIGH);
+                       msr.lo = (msr.lo & mask) | val;
+                       wrmsr(MDD_IRQM_YHIGH,msr);
+                       break;
+               case 16:
+                       msr=rdmsr(MDD_IRQM_ZLOW);
+                       msr.lo = (msr.lo & mask) | val;
+                       wrmsr(MDD_IRQM_ZLOW,msr);
+                       break;
+               case 24:
+                       msr=rdmsr(MDD_IRQM_ZHIGH);
+                       msr.lo = (msr.lo & mask) | val;
+                       wrmsr(MDD_IRQM_ZHIGH,msr);
+       }
+}
+
+// map an GPIO pin to PIC Z source and that to an IRQ.
+void map_gpio_irq(unsigned int pin, unsigned int gpioirq, unsigned int irq, 
unsigned int invert){
+       
+       unsigned long temp;
+       unsigned long mask;
+       unsigned long val;
+
+       mask = ~(0xF<<((pin&7)<<2));
+       val = gpioirq<<((pin&7)<<2);
+       
+       // configure GPIO pin as INT source
+       outl(1<<(pin&0x0F), (pin<16)?GPIOL_INPUT_ENABLE:GPIOH_INPUT_ENABLE);
+       outl(1<<(pin&0x0F), (pin<16)?GPIOL_EVENTS_ENABLE:GPIOH_EVENTS_ENABLE);
+
+       if (invert) outl(1<<(pin&0x0F), 
(pin<16)?GPIOL_INPUT_INVERT_ENABLE:GPIOH_INPUT_INVERT_ENABLE);
+
+       // map current GPIO pin to PIC unrestricted Z GPIO irq source gpioirq
+       temp = inl((pin<16)?
+                       ((pin<8)?GPIO_MAPPER_X:GPIO_MAPPER_Y):
+                       ((pin<24)?GPIO_MAPPER_Z:GPIO_MAPPER_W));
+
+       outl((temp & mask)|val, 
+               (pin<16)?
+                       ((pin<8)?GPIO_MAPPER_X:GPIO_MAPPER_Y):
+                       ((pin<24)?GPIO_MAPPER_Z:GPIO_MAPPER_W));
+                       
+       // map PIC unrestricted Z GPIO source i to IRQ needed
+       map_pic_irq(gpioirq+24,irq);
+}
+
+static void southbridge_init(struct device *dev)
+{
+       struct southbridge_amd_cs5536_config  *sb = (struct 
southbridge_amd_cs5536_config *)dev->chip_info;
+       msr_t msr;
+       int i;
+
+       printk_spew(">> Entering cs5536.c: %s\n", __FUNCTION__);
+
+       /*
+        * struct device *gpiodev;
+        * unsigned short gpiobase = MDD_GPIO;
+        */
+
+       setup_i8259(); 
+
+       // at first, disable all primary IRQ inputs except timer, RTC and FPU
+       msr.lo=0x2101;
+       msr.hi=0;
+       wrmsr(MDD_IRQM_PRIM, msr);
+
+       // LPC bus IRQs are enabled here
+       if (sb->lpc_serirq_enable) {
+               msr.lo = sb->lpc_serirq_enable;
+               msr.hi  = 0;
+               wrmsr(MDD_LPC_SIRQ, msr);
+       }
+       if (sb->lpc_irq) {
+               msr.lo = sb->lpc_irq;
+               msr.hi = 0;
+               wrmsr(MDD_IRQM_LPC, msr);
+       }
+
+       // GPIO to IRQ mapping (meant for PCI IRQs)
+       //  here, only physical mapping is done. 
+       //  pci headers should be configured for all pci slots available in 
mainboard.c
+       //  so that operating system can read correct irq number from there
+       for (i=0; i<3; i++){
+               if (sb->pci_int[i]){
+                       printk_debug("cs5536: %s: Configuring PCI INT%c from 
GPIO %d to INT %d.\n",
+                                __FUNCTION__, 'A'+i, sb->pci_int_pin[i], 
sb->pci_int[i]);
+                       map_gpio_irq(sb->pci_int_pin[i], i, sb->pci_int[i], 1);
+               }
+       }
+/*     
+// PCI IRQ mapping should work like this through vsa, but it doesn't
+       outl(0xAC1C, 0xFC53); //magic word to enable hidden register
+       outl(0xAC1C, 0x0009); //command: PCI_INT_AB
+       outl(0xAC1E, 
+               (sb->pci_int[0]>0)?(sb->pci_int_pin[0]):0x21 |
+               (sb->pci_int[1]>0)?(sb->pci_int_pin[1]<<8):(0x21<<8)
+       );
+
+       outl(0x785C, sb->pci_int[0]|(sb->pci_int[1]<<8));
+*/
+
+       printk_debug("cs5536: %s: enable_ide_nand_flash is %d\n", __FUNCTION__, 
sb->enable_ide_nand_flash);
+       if (sb->enable_ide_nand_flash) {
+               enable_ide_nand_flash();
+       }
+
+       /* irq handling */
+       // setup_irq sets irq in pci headers only, no configuration is done.
+       // pci headers must be set, operating system reads IRQ numbers there.
+       // to disable, set IRQ=0
+       
+       if (sb->isa_irq){
+               setup_irq(sb->isa_irq, 1, 0, 0xf, 0);
+       }
+
+       if (sb->flash_irq){
+               setup_irq(sb->flash_irq, 1, 0, 0xf, 1);
+               map_pic_irq(6,sb->flash_irq);
+               map_pic_irq(7,sb->flash_irq);           
+       }
+
+       // IDE IRQ 14 (GPIO pin 2) can only be enabled or disabled
+       if (sb->enable_ide_irq){
+               setup_irq(14, 1, 0, 0xf, 2);
+
+               // set up IDE GPIO IRQ pin
+               outl(1<<2, GPIOL_INPUT_ENABLE);
+               outl(1<<2, GPIOL_IN_AUX1_SELECT);
+
+               // enable IDE IRQ in primary IRQ mask
+               msr=rdmsr(MDD_IRQM_PRIM);
+               msr.lo |= 0x4000;
+               wrmsr(MDD_IRQM_PRIM, msr);
+       }
+
+       if (sb->audio_irq){     
+               map_pic_irq(4,sb->audio_irq);
+               setup_irq(sb->audio_irq, 1, 0, 0xf, 3);
+       }
+
+       if (sb->uart0_irq){     
+               map_pic_irq(14,sb->uart0_irq);
+       }       
+       if (sb->uart1_irq){     
+               map_pic_irq(15,sb->uart1_irq);
+       }
+
+       if (sb->usb_irq){       
+               setup_irq(sb->usb_irq, 1, 0, 0xf, 4);
+               setup_irq(sb->usb_irq, 1, 0, 0xf, 5);
+               setup_irq(sb->usb_irq, 1, 0, 0xf, 6);
+               setup_irq(sb->usb_irq, 1, 0, 0xf, 7);
+               map_pic_irq(2,sb->usb_irq);
+       }
+
+       // KEL (Keyboard Emulation Logic) IRQs
+       if (sb->enable_kel_keyb_irq){
+               msr=rdmsr(MDD_IRQM_PRIM);
+               msr.lo |= 0x0002;
+               wrmsr(MDD_IRQM_PRIM, msr);
+       }
+
+       if (sb->enable_kel_mouse_irq){
+               msr=rdmsr(MDD_IRQM_PRIM);
+               msr.lo |= 0x1000;
+               wrmsr(MDD_IRQM_PRIM, msr);
+       }
+
+       if (sb->kel_emul_irq){
+               map_pic_irq(13,sb->kel_emul_irq);               
+       }
+
+
+
+
+       /* disable unwanted virtual PCI devices */
+       for (i = 0; (i < MAX_UNWANTED_VPCI) && (0 != sb->unwanted_vpci[i]); 
i++) {
+               printk_debug("Disabling VPCI device: 0x%08X\n", 
sb->unwanted_vpci[i]);
+               outl(sb->unwanted_vpci[i] + 0x7C, 0xCF8);
+               outl(0xDEADBEEF,                  0xCFC);
+       }
+
+       /* What do we have there? */
+       printk_debug("\nChipset config after southbridge_init():\n");
+       print_conf();
+}
+
+void southbridge_enable(struct device *dev)
+{
+}
+
+static void cs5536_pci_dev_enable_resources(device_t dev)
+{
+       printk_spew(">> Entering cs5536.c: %s\n", __FUNCTION__);
+       pci_dev_enable_resources(dev);
+       enable_childrens_resources(dev);
+}
+
+static struct device_operations southbridge_ops = {
+       .read_resources   = pci_dev_read_resources,
+       .set_resources    = pci_dev_set_resources,
+       .enable_resources = cs5536_pci_dev_enable_resources,
+       .init             = southbridge_init,
+       .scan_bus         = scan_static_bus,
+};
+
+static struct pci_driver cs5536_pci_driver __pci_driver = {
+       .ops    = &southbridge_ops,
+       .vendor = PCI_VENDOR_ID_AMD,
+       .device = PCI_DEVICE_ID_AMD_CS5536_ISA
+};
+
+struct chip_operations southbridge_amd_cs5536_ops = {
+       CHIP_NAME("AMD cs5536")
+       /* This only called when this device is listed in the 
+       * static device tree.
+       */
+       .enable_dev = southbridge_enable,
+};

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.h
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.h                    
        (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536.h    2006-09-18 
22:52:24 UTC (rev 2421)
@@ -0,0 +1,6 @@
+#ifndef _CS5536_H
+#define _CS5536_H
+
+extern void southbridge_enable(device_t dev);
+
+#endif

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_setup.c
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_setup.c        
                        (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_setup.c        
2006-09-18 22:52:24 UTC (rev 2421)
@@ -0,0 +1,336 @@
+
+/*
+ *
+ * cs5536_early_setup.c:       Early chipset initialization for CS5536 
companion device
+ *
+ *
+ * This file implements the initialization sequence documented in section 4.2 
of
+ * AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide.
+ *
+ */
+
+#define CS5536_GLINK_PORT_NUM  0x02    /* the geode link port number to the 
CS5536 */       
+#define CS5536_DEV_NUM                 0x0F    /* default PCI device number 
for CS5536 */
+
+
+/**
+ * By default, on cs5536 IDE is disabled and flash is enabled
+ * This function disables flash and enables IDE
+ */
+ 
+static void cs5536_enable_ide(void){
+       msr_t msr;
+       msr = __builtin_rdmsr(0x51400015);
+       msr.lo |= 0x00000001;
+       __builtin_wrmsr(0x51400015, msr.lo, msr.hi);
+}
+
+/**
+ * @brief Setup PCI IDSEL for CS5536
+ *
+ * 
+ */
+
+static void cs5536_setup_extmsr(void)
+{
+       msr_t msr;
+
+       /* forward MSR access to CS5536_GLINK_PORT_NUM to CS5536_DEV_NUM */
+       msr.hi = 0x00000000;
+       msr.lo = 0x00000000;
+       if (CS5536_GLINK_PORT_NUM <= 4) {
+               msr.lo = CS5536_DEV_NUM << ((CS5536_GLINK_PORT_NUM - 1) * 8);
+       } else {
+               msr.hi = CS5536_DEV_NUM << ((CS5536_GLINK_PORT_NUM - 5) * 8);
+       }
+       wrmsr(0x5000201e, msr);
+}
+
+static void cs5536_setup_idsel(void)
+{
+       /* write IDSEL to the write once register at address 0x0000 */
+       outl(0x1 << (CS5536_DEV_NUM + 10), 0);
+}
+
+static void cs5536_usb_swapsif(void)
+{
+       msr_t msr;
+
+       msr = rdmsr(0x51600005);
+       //USB Serial short detect bit.
+       if (msr.hi & 0x10) {
+               /* We need to preserve bits 32,33,35 and not clear any BIST 
error, but clear the
+                * SERSHRT error bit */
+               msr.hi &= 0xFFFFFFFB;
+               wrmsr(0x51600005, msr);
+       }
+}
+
+static int cs5536_setup_iobase(void)
+{
+       msr_t msr;
+
+       /* setup LBAR for SMBus controller */
+       __builtin_wrmsr(0x5140000b, 0x00006000, 0x0000f001);
+       /* setup LBAR for GPIO */
+       __builtin_wrmsr(0x5140000c, 0x00006100, 0x0000f001);
+       /* setup LBAR for MFGPT */
+       __builtin_wrmsr(0x5140000d, 0x00006200, 0x0000f001);
+       /* setup LBAR for ACPI */
+       __builtin_wrmsr(0x5140000e, 0x00009c00, 0x0000f001);
+       /* setup LBAR for PM Support */
+       __builtin_wrmsr(0x5140000f, 0x00009d00, 0x0000f001);
+}
+
+static void cs5536_setup_power_bottun(void)
+{
+       /* not implemented yet */
+#if 0
+       pwrBtn_setup:
+       ;
+       ;       Power Button Setup
+       ;
+       ;mov    eax, 0C0020000h                         ; 4 seconds + lock
+       mov     eax, 040020000h                         ; 4 seconds no lock
+       mov     dx, PMLogic_BASE + 40h
+       out     dx, eax
+
+       ; setup GPIO24, it is the external signal for 5536 vsb_work_aux
+       ; which controls all voltage rails except Vstandby & Vmem.
+       ; We need to enable, OUT_AUX1 and OUTPUT_ENABLE in this order.
+       ; If GPIO24 is not enabled then soft-off will not work.
+       mov     dx, GPIOH_OUT_AUX1_SELECT
+       mov     eax, GPIOH_24_SET
+       out     dx, eax
+       mov     dx, GPIOH_OUTPUT_ENABLE
+       out     dx, eax
+
+#endif
+}
+
+static void cs5536_setup_gpio(void)
+{
+       uint32_t val;
+
+       /* setup GPIO pins 14/15 for SDA/SCL */
+       val = (1<<14 | 1<<15);
+       /* Output Enable */
+       outl(0x3fffc000, 0x6100 + 0x04);
+       //outl(val, 0x6100 + 0x04);
+       /* Output AUX1 */
+       outl(0x3fffc000, 0x6100 + 0x10);
+       //outl(val, 0x6100 + 0x10);
+       /* Input Enable */
+       //outl(0x0f5af0a5, 0x6100 + 0x20);
+       outl(0x3fffc000, 0x6100 + 0x20);
+       //outl(val, 0x6100 + 0x20);
+       /* Input AUX1 */
+       //outl(0x3ffbc004, 0x6100 + 0x34);
+       outl(0x3fffc000, 0x6100 + 0x34);
+       //outl(val, 0x6100 + 0x34);
+
+       /*   GX3: Enable GPIO pins for UART2    */
+       outl(0x00000010, GPIOL_OUT_AUX1_SELECT);
+       outl(0x00000010, GPIOL_OUTPUT_ENABLE);
+       outl(0x00000008, GPIOL_IN_AUX1_SELECT);
+       outl(0x00000008, GPIOL_INPUT_ENABLE);
+
+#if 0
+       /* changes proposed by Ollie; we will test this later. */
+       /* setup GPIO pins 14/15 for SDA/SCL */
+       val = GPIOL_15_SET | GPIOL_14_SET;
+       /* Output Enable */
+       //outl(0x3fffc000, 0x6100 + 0x04);
+       outl(val, 0x6100 + 0x04);
+       /* Output AUX1 */
+       //outl(0x3fffc000, 0x6100 + 0x10);
+       outl(val, 0x6100 + 0x10);
+       /* Input Enable */
+       //outl(0x3fffc000, 0x6100 + 0x20);
+       outl(val, 0x6100 + 0x20);
+       /* Input AUX1 */
+       //outl(0x3fffc000, 0x6100 + 0x34);
+       outl(val, 0x6100 + 0x34);
+#endif
+}
+
+static void cs5536_disable_internal_uart(void)
+{
+       /* not implemented yet */
+#if 0
+       ; The UARTs default to enabled.
+       ; Disable and reset them and configure them later. (SIO init)
+       mov     ecx, MDD_UART1_CONF
+       RDMSR
+       mov     eax, 1h                                 ; reset
+       WRMSR
+       mov     eax, 0h                                 ; disabled
+       WRMSR
+
+       mov     ecx, MDD_UART2_CONF
+       RDMSR
+       mov     eax, 1h                                 ; reset
+       WRMSR
+       mov     eax, 0h                                 ; disabled
+       WRMSR
+
+#endif
+}
+
+static void cs5536_setup_cis_mode(void)
+{
+       msr_t msr;
+
+       /* setup CPU interface serial to mode C on both sides */
+       msr = __builtin_rdmsr(0x51000010);
+       msr.lo &= ~0x18;
+       msr.lo |= 0x10;
+       __builtin_wrmsr(0x51000010, msr.lo, msr.hi);
+       //Only do this if we are building for 5536
+       __builtin_wrmsr(0x54002010, 0x00000002, 0x00000000);
+}
+
+static void dummy(void)
+{
+}
+
+/* see page 412 of the cs5536 companion book */
+static int cs5536_setup_onchipuart(void)
+{
+       unsigned long m;
+       
+       unsigned char n;
+       
+       /* 
+        * 1. Eanble GPIO 8 to OUT_AUX1, 9 to IN_AUX1
+        *    GPIO LBAR + 0x04, LBAR + 0x10, LBAR + 0x20, LBAR + 34
+        * 2. Enable UART IO space in MDD
+        *    MSR 0x51400014 bit 18:16
+        * 3. Enable UART controller
+        *    MSR 0x5140003A bit 0, 1
+        * 4. IRQ routing on IRQ Mapper
+        *    MSR 0x51400021 bit [27:24]
+        */
+       msr_t msr;
+ 
+        /*  Bit 1 = DEVEN (device enable)
+         *  Bit 4 = EN_BANKS (allow access to the upper banks)
+         */
+ 
+        msr.lo = (1 << 4) | (1 << 1);
+       msr.hi = 0;
+       /* enable COM1 */
+       //wrmsr(0x5140003a, msr);
+       /* GPIO8 - UART1_TX */
+       /* Set: Output Enable  (0x4) */
+       m = inl(GPIOL_OUTPUT_ENABLE);
+       m |= GPIOL_8_SET;
+       m &= ~GPIOL_8_CLEAR;
+       //outl(m,GPIOL_OUTPUT_ENABLE);
+       /* Set: OUTAUX1 Select (0x10) */
+       m = inl(GPIOL_OUT_AUX1_SELECT);
+       m |= GPIOL_8_SET;
+       m &= ~GPIOL_8_CLEAR;
+       //outl(m,GPIOL_OUT_AUX1_SELECT);
+       /* Set: Pull Up        (0x18) */
+       m = inl(GPIOL_PULLUP_ENABLE);
+       m |= GPIOL_8_SET;
+       m &= ~GPIOL_8_CLEAR;
+       /* GPIO9 - UART1_RX */
+       /* Set: Pull Up        (0x18) */
+       m |= GPIOL_9_SET;
+       m &= ~GPIOL_9_CLEAR;
+       //outl(m,GPIOL_PULLUP_ENABLE);
+       /* Set: Input Enable   (0x20) */
+       m = inl(GPIOL_INPUT_ENABLE);
+       m |= GPIOL_9_SET;
+       m &= ~GPIOL_9_CLEAR;
+       //outl(m,GPIOL_INPUT_ENABLE);
+       /* Set: INAUX1 Select  (0x34) */
+       m = inl(GPIOL_IN_AUX1_SELECT);
+       m |= GPIOL_9_SET;
+       m &= ~GPIOL_9_CLEAR;
+       //outl(m,GPIOL_IN_AUX1_SELECT);
+
+       msr = rdmsr(MDD_LEG_IO);
+       msr.lo |= 0x7 << 16;
+       //wrmsr(MDD_LEG_IO,msr);
+       
+       // GX3: my board has UART2 wired up ;)
+
+
+       // enable UART2 as COM1
+       msr = rdmsr(MDD_LEG_IO);
+       msr.lo |= 0x700000;
+       wrmsr(MDD_LEG_IO, msr);
+
+       // reset UART2
+       msr = rdmsr(MDD_UART2_CONF);
+       msr.lo = 1;
+       wrmsr(MDD_UART2_CONF, msr);
+
+       // clear reset UART2
+       msr.lo = 0;
+       wrmsr(MDD_UART2_CONF, msr);
+
+       // enable UART2
+       msr.lo = 2;
+       wrmsr(MDD_UART2_CONF, msr);
+
+
+       // Set DLAB
+       n = 0x80;
+       outb(n, TTYS0_BASE + 3);
+ 
+       // Baud rate divisor
+       n = 0x01;
+       outb(n, TTYS0_BASE);
+
+       //  Line mode (8N1)
+       n = 0x03;
+       outb(n, TTYS0_BASE + 3);
+
+       //      Clear DTR & RTS
+       n = 0x00;
+       outb(n, TTYS0_BASE + 4);
+       
+}
+
+/* note: you can't do prints in here in most cases, 
+ * and we don't want to hang on serial, so they are 
+ * commented out 
+ */
+static int cs5536_early_setup(void)
+{
+       msr_t msr;
+
+       cs5536_setup_extmsr();
+
+/*     msr = rdmsr(GLCP_SYS_RSTPLL);
+       if (msr.lo & (0x3f << 26)) {
+               // PLL is already set and we are reboot from PLL reset
+               //print_debug("reboot from BIOS reset\n\r");
+               return;
+       }*/
+       
+       //print_debug("Setup idsel\r\n");
+       cs5536_setup_idsel();
+       //print_debug("Setup iobase\r\n");
+       cs5536_usb_swapsif();
+       cs5536_setup_iobase();
+       //print_debug("Setup gpio\r\n");
+       cs5536_setup_gpio();
+       //print_debug("Setup cis_mode\r\n");
+       cs5536_setup_cis_mode();
+       //print_debug("Setup smbus\r\n");
+       cs5536_enable_smbus();
+
+       // ide/flash bit goes to default on reset
+       // this value depends on boot straps
+       // lets set it to known enabled value
+       // later, cs5536_enable_ide_nand_flash changes it if needed.
+       //cs5536_enable_ide();
+
+
+       dummy();
+}

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_smbus.c
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_smbus.c        
                        (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_early_smbus.c        
2006-09-18 22:52:24 UTC (rev 2421)
@@ -0,0 +1,45 @@
+#include "cs5536_smbus.h"
+
+#define SMBUS_IO_BASE 0x6000
+
+/* initialization for SMBus Controller */
+static int cs5536_enable_smbus(void)
+{
+       unsigned char val;
+
+       /* reset SMBUS controller */
+       outb(0, SMBUS_IO_BASE + SMB_CTRL2);
+
+       /* Set SCL freq and enable SMB controller */
+       val = inb(SMBUS_IO_BASE + SMB_CTRL2);
+       val |= ((0x20 << 1) | SMB_CTRL2_ENABLE);
+       outb(val, SMBUS_IO_BASE + SMB_CTRL2);
+
+       /* Setup SMBus host controller address to 0xEF */
+       val = inb(SMBUS_IO_BASE + SMB_ADD);
+       val |= (0xEF | SMB_ADD_SAEN);
+       outb(val, SMBUS_IO_BASE + SMB_ADD); 
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+        return do_smbus_read_byte(SMBUS_IO_BASE, device, address-1);
+}
+
+#if 0
+static int smbus_recv_byte(unsigned device)
+{
+        return do_smbus_recv_byte(SMBUS_IO_BASE, device);
+}
+
+static int smbus_send_byte(unsigned device, unsigned char val)
+{
+        return do_smbus_send_byte(SMBUS_IO_BASE, device, val);
+}
+
+
+static int smbus_write_byte(unsigned device, unsigned address, unsigned char 
val)
+{
+        return do_smbus_write_byte(SMBUS_IO_BASE, device, address, val);
+}
+#endif

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_ide.c
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_ide.c                
                (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_ide.c        
2006-09-18 22:52:24 UTC (rev 2421)
@@ -0,0 +1,30 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "cs5536.h"
+
+static void ide_init(struct device *dev)
+{
+       printk_spew("cs5536_ide: %s\n", __FUNCTION__);
+}
+
+static void ide_enable(struct device *dev)
+{
+       printk_spew("cs5536_ide: %s\n", __FUNCTION__);
+}
+
+static struct device_operations ide_ops = {
+       .read_resources   = pci_dev_read_resources,
+       .set_resources    = pci_dev_set_resources,
+       .enable_resources = pci_dev_enable_resources,
+       .init             = ide_init,
+       .enable           = ide_enable,
+};
+
+static struct pci_driver ide_driver __pci_driver = {
+       .ops    = &ide_ops,
+       .vendor = PCI_VENDOR_ID_AMD,
+       .device = PCI_DEVICE_ID_AMD_CS5536_IDE,
+};

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus.h
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus.h              
                (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus.h      
2006-09-18 22:52:24 UTC (rev 2421)
@@ -0,0 +1,180 @@
+//#include <device/smbus_def.h>
+#define SMBUS_ERROR -1
+#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2
+#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT  -3
+
+#define        SMB_SDA         0x00
+#define SMB_STS                0x01
+#define SMB_CTRL_STS   0x02
+#define        SMB_CTRL1       0x03
+#define SMB_ADD                0x04
+#define SMB_CTRL2      0x05
+#define        SMB_CTRL3       0x06
+
+#define SMB_STS_SLVSTP (0x01 << 7)
+#define SMB_STS_SDAST  (0x01 << 6)
+#define        SMB_STS_BER     (0x01 << 5)
+#define SMB_STS_NEGACK (0x01 << 4)
+#define        SMB_STS_STASTR  (0x01 << 3)
+#define SMB_STS_NMATCH (0x01 << 2)
+#define        SMB_STS_MASTER  (0x01 << 1)
+#define SMB_STS_XMIT   (0x01 << 0)
+
+#define        SMB_CSTS_TGSCL  (0x01 << 5)
+#define SMB_CSTS_TSDA  (0x01 << 4)
+#define        SMB_CSTS_GCMTCH (0x01 << 3)
+#define SMB_CSTS_MATCH (0x01 << 2)
+#define        SMB_CSTS_BB     (0x01 << 1)
+#define SMB_CSTS_BUSY  (0x01 << 0)
+
+#define        SMB_CTRL1_STASTRE (0x01 << 7)
+#define SMB_CTRL1_NMINTE  (0x01 << 6)
+#define        SMB_CTRL1_GCMEN   (0x01 << 5)
+#define SMB_CTRL1_ACK     (0x01 << 4)
+#define        SMB_CTRL1_RSVD    (0x01 << 3)
+#define SMB_CTRL1_INTEN   (0x01 << 2)
+#define        SMB_CTRL1_STOP    (0x01 << 1)
+#define SMB_CTRL1_START   (0x01 << 0)
+
+#define        SMB_ADD_SAEN      (0x01 << 7)
+
+#define        SMB_CTRL2_ENABLE  0x01
+
+#define SMBUS_TIMEOUT (100*1000*10)
+#define SMBUS_STATUS_MASK 0xfbff
+
+#define SMBUS_IO_BASE 0x6000
+
+static void smbus_delay(void)
+{
+       outb(0x80, 0x80);
+}
+
+/* generate a smbus start condition */
+static int smbus_start_condition(unsigned smbus_io_base)
+{
+       unsigned char val;
+       unsigned long loops;
+       loops = SMBUS_TIMEOUT;
+
+       /* issue a START condition */
+       val = inb(smbus_io_base + SMB_CTRL1);
+       outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1);
+
+       /* check for bus conflict */
+       val = inb(smbus_io_base + SMB_STS);
+       if ((val & SMB_STS_BER) != 0)
+               return SMBUS_ERROR;
+
+       /* check for SDA status */
+       do {
+               smbus_delay();
+               val = inw(smbus_io_base + SMB_STS);
+               if ((val & SMB_STS_SDAST) != 0) {
+                       break;
+               }
+       } while(--loops);
+       return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+}
+
+static int smbus_check_stop_condition(unsigned smbus_io_base)
+{
+       unsigned char val;
+       unsigned long loops;
+       loops = SMBUS_TIMEOUT;
+       /* check for SDA status */
+       do {
+               smbus_delay();
+               val = inw(smbus_io_base + SMB_CTRL1);
+               if ((val & SMB_CTRL1_STOP) == 0) {
+                       break;
+               }
+       } while(--loops);
+       return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+}
+
+static int smbus_stop_condition(unsigned smbus_io_base)
+{
+       unsigned char val;
+       val = inb(smbus_io_base + SMB_CTRL1);
+       outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1);
+}
+
+static int smbus_send_slave_address(unsigned smbus_io_base, unsigned char 
device)
+{
+       unsigned char val;
+       unsigned long loops;
+       loops = SMBUS_TIMEOUT;
+                        
+       /* send the slave address */
+       outb(device, smbus_io_base + SMB_SDA);
+
+       /* check for bus conflict and NACK */
+       val = inb(smbus_io_base + SMB_STS);
+       if (((val & SMB_STS_BER)    != 0) ||
+           ((val & SMB_STS_NEGACK) != 0))
+               return SMBUS_ERROR;
+
+       /* check for SDA status */
+       do {
+               smbus_delay();
+               val = inw(smbus_io_base + SMB_STS);
+               if ((val & SMB_STS_SDAST) != 0) {
+                       break;
+               }
+       } while(--loops);
+       return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;  
+}
+
+static int smbus_send_command(unsigned smbus_io_base, unsigned char command)
+{
+        unsigned char val;
+       unsigned long loops;
+       loops = SMBUS_TIMEOUT;
+
+       /* send the command */
+       outb(command, smbus_io_base + SMB_SDA);
+
+       /* check for bus conflict and NACK */
+       val = inb(smbus_io_base + SMB_STS);
+       if (((val & SMB_STS_BER)    != 0) ||
+           ((val & SMB_STS_NEGACK) != 0))
+               return SMBUS_ERROR;
+
+       /* check for SDA status */
+       do {
+               smbus_delay();
+               val = inw(smbus_io_base + SMB_STS);
+               if ((val & SMB_STS_SDAST) != 0) {
+                       break;
+               }
+       } while(--loops);
+       return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;  
+}
+
+static unsigned char do_smbus_read_byte(unsigned smbus_io_base, unsigned char 
device, unsigned char address)
+{
+       unsigned char val, val1;
+
+       smbus_check_stop_condition(smbus_io_base);
+
+       smbus_start_condition(smbus_io_base);
+
+       smbus_send_slave_address(smbus_io_base, device);
+
+       smbus_send_command(smbus_io_base, address);
+
+       smbus_start_condition(smbus_io_base);
+
+       smbus_send_slave_address(smbus_io_base, device | 0x01);
+
+       /* send NACK to slave */
+       val = inb(smbus_io_base + SMB_CTRL1);
+       outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
+
+       val = inb(smbus_io_base + SMB_SDA);
+
+       //smbus_stop_condition(smbus_io_base);
+
+       return val;
+}

Added: trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus2.h
===================================================================
--- trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus2.h             
                (rev 0)
+++ trunk/LinuxBIOSv2/src/southbridge/amd/cs5536_lx/cs5536_smbus2.h     
2006-09-18 22:52:24 UTC (rev 2421)
@@ -0,0 +1,299 @@
+//#include <device/smbus_def.h>
+#define SMBUS_ERROR -1
+#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2
+#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT  -3
+
+#define        SMB_SDA         0x00
+#define SMB_STS                0x01
+#define SMB_CTRL_STS   0x02
+#define        SMB_CTRL1       0x03
+#define SMB_ADD                0x04
+#define SMB_CTRL2      0x05
+#define        SMB_CTRL3       0x06
+
+#define SMB_STS_SLVSTP (0x01 << 7)
+#define SMB_STS_SDAST  (0x01 << 6)
+#define        SMB_STS_BER     (0x01 << 5)
+#define SMB_STS_NEGACK (0x01 << 4)
+#define        SMB_STS_STASTR  (0x01 << 3)
+#define SMB_STS_NMATCH (0x01 << 2)
+#define        SMB_STS_MASTER  (0x01 << 1)
+#define SMB_STS_XMIT   (0x01 << 0)
+
+#define        SMB_CSTS_TGSCL  (0x01 << 5)
+#define SMB_CSTS_TSDA  (0x01 << 4)
+#define        SMB_CSTS_GCMTCH (0x01 << 3)
+#define SMB_CSTS_MATCH (0x01 << 2)
+#define        SMB_CSTS_BB     (0x01 << 1)
+#define SMB_CSTS_BUSY  (0x01 << 0)
+
+#define        SMB_CTRL1_STASTRE (0x01 << 7)
+#define SMB_CTRL1_NMINTE  (0x01 << 6)
+#define        SMB_CTRL1_GCMEN   (0x01 << 5)
+#define SMB_CTRL1_ACK     (0x01 << 4)
+#define        SMB_CTRL1_RSVD    (0x01 << 3)
+#define SMB_CTRL1_INTEN   (0x01 << 2)
+#define        SMB_CTRL1_STOP    (0x01 << 1)
+#define SMB_CTRL1_START   (0x01 << 0)
+
+#define        SMB_ADD_SAEN      (0x01 << 7)
+
+#define        SMB_CTRL2_ENABLE  0x01
+
+#define SMBUS_TIMEOUT (100*1000*10)
+#define SMBUS_STATUS_MASK 0xfbff
+
+#define SMBUS_IO_BASE 0x6000
+
+static void smbus_delay(void)
+{
+       outb(0x80, 0x80);
+}
+
+static int smbus_wait(unsigned smbus_io_base) {
+       unsigned long loops = SMBUS_TIMEOUT;
+       unsigned char val;
+
+       do {
+               smbus_delay();
+               val = inb(smbus_io_base + SMB_STS);
+               if ((val & SMB_STS_SDAST) != 0)
+                       break;
+               if (val & (SMB_STS_BER | SMB_STS_NEGACK)) {
+                       printk_debug("SMBUS WAIT ERROR %x\n", val);
+                       return SMBUS_ERROR;
+               }
+       } while(--loops);
+
+       outb(0, smbus_io_base + SMB_STS);
+       return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+}
+
+static int smbus_write(unsigned smbus_io_base, unsigned char byte) {
+
+       outb(byte, smbus_io_base + SMB_SDA);
+       return smbus_wait(smbus_io_base);
+}
+
+/* generate a smbus start condition */
+static int smbus_start_condition(unsigned smbus_io_base)
+{
+       unsigned char val;
+
+       /* issue a START condition */
+       val = inb(smbus_io_base + SMB_CTRL1);
+       outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1);
+
+       /* check for bus conflict */
+       val = inb(smbus_io_base + SMB_STS);
+       if ((val & SMB_STS_BER) != 0)
+               return SMBUS_ERROR;
+
+       return smbus_wait(smbus_io_base);
+}
+
+static int smbus_check_stop_condition(unsigned smbus_io_base)
+{
+       unsigned char val;
+       unsigned long loops;
+       loops = SMBUS_TIMEOUT;
+       /* check for SDA status */
+       do {
+               smbus_delay();
+               val = inb(smbus_io_base + SMB_CTRL1);
+               if ((val & SMB_CTRL1_STOP) == 0) {
+                       break;
+               }
+       } while(--loops);
+       return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+       /* Make sure everything is cleared and ready to go */
+
+       val = inb(smbus_io_base + SMB_CTRL1);
+       outb(val & ~(SMB_CTRL1_STASTRE | SMB_CTRL1_NMINTE),
+                       smbus_io_base + SMB_CTRL1);
+
+       outb(SMB_STS_BER | SMB_STS_NEGACK | SMB_STS_STASTR,
+                       smbus_io_base + SMB_STS);
+
+       val = inb(smbus_io_base + SMB_CTRL_STS);
+       outb(val | SMB_CSTS_BB, smbus_io_base + SMB_CTRL_STS);
+}
+
+static int smbus_stop_condition(unsigned smbus_io_base)
+{
+       unsigned char val;
+       val = inb(smbus_io_base + SMB_CTRL1);
+       outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1);
+
+       return 0;
+}
+
+static int smbus_ack(unsigned smbus_io_base, int state)
+{
+       unsigned char val = inb(smbus_io_base + SMB_CTRL1);
+
+       if (state)
+               outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
+       else
+               outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
+
+       return 0;
+}
+
+static int smbus_send_slave_address(unsigned smbus_io_base, unsigned char 
device)
+{
+       unsigned char val;
+
+       /* send the slave address */
+       outb(device, smbus_io_base + SMB_SDA);
+
+       /* check for bus conflict and NACK */
+       val = inb(smbus_io_base + SMB_STS);
+       if (((val & SMB_STS_BER)    != 0) ||
+           ((val & SMB_STS_NEGACK) != 0)) {
+               printk_debug("SEND SLAVE ERROR (%x)\n", val);
+               return SMBUS_ERROR;
+       }
+       return smbus_wait(smbus_io_base);
+}
+
+static int smbus_send_command(unsigned smbus_io_base, unsigned char command)
+{
+        unsigned char val;
+
+       /* send the command */
+       outb(command, smbus_io_base + SMB_SDA);
+
+       /* check for bus conflict and NACK */
+       val = inb(smbus_io_base + SMB_STS);
+       if (((val & SMB_STS_BER)    != 0) ||
+           ((val & SMB_STS_NEGACK) != 0))
+               return SMBUS_ERROR;
+
+       return smbus_wait(smbus_io_base);
+}
+
+static void _doread(unsigned smbus_io_base, unsigned char device,
+               unsigned char address, unsigned char *data, int count)
+{
+       int ret;
+       int index = 0;
+       unsigned char val;
+
+       if ((ret = smbus_check_stop_condition(smbus_io_base)))
+               goto err;
+
+       index++;
+
+       if ((ret = smbus_start_condition(smbus_io_base)))
+               goto err;
+
+       index++; /* 2 */
+       if ((ret = smbus_send_slave_address(smbus_io_base, device)))
+               goto err;
+
+       index++;
+       if ((ret = smbus_send_command(smbus_io_base, address)))
+               goto err;
+
+       index++;
+       if ((ret = smbus_start_condition(smbus_io_base)))
+               goto err;
+
+       /* Clear the ack for multiple byte reads */
+       smbus_ack(smbus_io_base, (count == 1) ? 1 : 0);
+
+       index++;
+       if ((ret = smbus_send_slave_address(smbus_io_base, device | 0x01)))
+               goto err;
+
+       while(count) {
+               /* Set the ACK if this is the next to last byte */
+               smbus_ack(smbus_io_base, (count == 2) ? 1 : 0);
+
+               /* Set the stop bit if this is the last byte to read */
+
+               if (count == 1)
+                       smbus_stop_condition(smbus_io_base);
+
+               val = inb(smbus_io_base + SMB_SDA);
+               *data++ = val;
+
+               if (count > 1) {
+                       int ret = smbus_wait(smbus_io_base);
+                       if (ret)
+                               return ret;
+               }
+
+               count--;
+       }
+
+       return;
+
+ err:
+       printk_debug("SMBUS READ ERROR (%d): %d\n", index, ret);
+}
+
+static unsigned char do_smbus_read_byte(unsigned smbus_io_base,
+               unsigned char device,
+                                       unsigned char address)
+{
+       unsigned char val = 0;
+       _doread(smbus_io_base, device, address, &val, sizeof(val));
+       return val;
+}
+
+static unsigned short do_smbus_read_word(unsigned smbus_io_base,
+               unsigned char device, unsigned char address)
+{
+       unsigned short val = 0;
+       _doread(smbus_io_base, device, address, (unsigned char *) &val,
+                       sizeof(val));
+       return val;
+}
+
+static int _dowrite(unsigned smbus_io_base, unsigned char device,
+               unsigned char address, unsigned char *data, int count) {
+
+       int ret;
+
+       if ((ret = smbus_check_stop_condition(smbus_io_base)))
+               goto err;
+
+       if ((ret = smbus_start_condition(smbus_io_base)))
+               goto err;
+
+       if ((ret = smbus_send_slave_address(smbus_io_base, device)))
+               goto err;
+
+       if ((ret = smbus_send_command(smbus_io_base, address)))
+               goto err;
+
+       while(count) {
+               if ((ret = smbus_write(smbus_io_base, *data++)))
+                       goto err;
+               count--;
+       }
+
+       smbus_stop_condition(smbus_io_base);
+       return 0;
+
+ err:
+       printk_debug("SMBUS WRITE ERROR: %d\n", ret);
+       return -1;
+}
+
+
+static int do_smbus_write_byte(unsigned smbus_io_base, unsigned char device,
+               unsigned char address, unsigned char data)
+{
+       return _dowrite(smbus_io_base, device, address,
+                       (unsigned char *) &data, 1);
+}
+
+static int do_smbus_write_word(unsigned smbus_io_base, unsigned char device, 
unsigned char address,
+                              unsigned short data)
+{
+       return _dowrite(smbus_io_base, device ,address, (unsigned char *) 
&data, 2);
+}


-- 
linuxbios mailing list
[email protected]
http://www.openbios.org/mailman/listinfo/linuxbios

Reply via email to