Drop the src/southbridge/amd/cs5536_lx directory and its contents, as
the new src/southbridge/amd/cs5536 code completely replaces it. The Artecgroup dbe61 board currently uses it, but that is broken anyway at the moment. A fix to use the new CS5536 code for it is being worked on. Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2697 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
da0eec07fb
commit
63b087a8ab
|
@ -1,5 +0,0 @@
|
||||||
config chip.h
|
|
||||||
driver cs5536.o
|
|
||||||
driver cs5536_usb.o
|
|
||||||
#driver cs5536_pci.o
|
|
||||||
#driver cs5536_ide.o
|
|
|
@ -1,53 +0,0 @@
|
||||||
#ifndef _SOUTHBRIDGE_AMD_CS5536_LX
|
|
||||||
#define _SOUTHBRIDGE_AMD_CS5536_LX
|
|
||||||
|
|
||||||
#define MAX_UNWANTED_VPCI 10 /* increase if needed */
|
|
||||||
|
|
||||||
extern struct chip_operations southbridge_amd_cs5536_lx_ops;
|
|
||||||
|
|
||||||
struct southbridge_amd_cs5536_lx_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_LX */
|
|
|
@ -1,331 +0,0 @@
|
||||||
|
|
||||||
#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_lx_config *sb = (struct southbridge_amd_cs5536_lx_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_lx_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_lx_ops = {
|
|
||||||
CHIP_NAME("AMD Geode CS5536 (LX) Southbridge")
|
|
||||||
/* This only called when this device is listed in the
|
|
||||||
* static device tree.
|
|
||||||
*/
|
|
||||||
.enable_dev = southbridge_enable,
|
|
||||||
};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef _CS5536_H
|
|
||||||
#define _CS5536_H
|
|
||||||
|
|
||||||
extern void southbridge_enable(device_t dev);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,336 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* 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();
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
#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
|
|
|
@ -1,30 +0,0 @@
|
||||||
#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,
|
|
||||||
};
|
|
|
@ -1,180 +0,0 @@
|
||||||
//#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;
|
|
||||||
}
|
|
|
@ -1,299 +0,0 @@
|
||||||
//#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);
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
#include <console/console.h>
|
|
||||||
#include <device/device.h>
|
|
||||||
#include <device/pci.h>
|
|
||||||
#include <device/pci_ids.h>
|
|
||||||
#include <device/pci_ops.h>
|
|
||||||
|
|
||||||
#include <cpu/amd/lxdef.h>
|
|
||||||
#include <cpu/x86/msr.h>
|
|
||||||
|
|
||||||
#include "cs5536.h"
|
|
||||||
|
|
||||||
#define GLIU2_P2D_BM_1 0x51010021 // southbridge GLIU P2D base mask descriptor
|
|
||||||
#define USBMSRUOCB 0x5120000b // USB option controller base address register
|
|
||||||
#define UOCMUX (USBOC_BASE_ADDRESS + 4) // option controller native multiplex register
|
|
||||||
|
|
||||||
#define USBOC_BASE_ADDRESS 0xe1017000 // USB option contoller base address, used only here
|
|
||||||
#define USBOC_PORT4_FUNCTION 2 // USB port 4 desired function (0 = disabled, 2 = host, 3 = device)
|
|
||||||
|
|
||||||
static void ohci_init(struct device *dev)
|
|
||||||
{
|
|
||||||
uint32_t n;
|
|
||||||
msr_t msr;
|
|
||||||
|
|
||||||
printk_debug("USB: Setting up OHCI controller... ");
|
|
||||||
|
|
||||||
// enable controller bus mastering
|
|
||||||
n = pci_read_config32(dev, PCI_COMMAND);
|
|
||||||
pci_write_config32(dev, PCI_COMMAND,
|
|
||||||
n | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
|
|
||||||
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
|
|
||||||
|
|
||||||
// set the USB option controller base address
|
|
||||||
msr.hi = 0x0000000a;
|
|
||||||
msr.lo = USBOC_BASE_ADDRESS;
|
|
||||||
wrmsr(USBMSRUOCB, msr);
|
|
||||||
|
|
||||||
// create the GLIU memory mapping
|
|
||||||
msr.hi = 0x40000000 | ((USBOC_BASE_ADDRESS >> 24) & 0x000000ff);
|
|
||||||
msr.lo = ((USBOC_BASE_ADDRESS << 8) & 0xfff00000) | 0x000fffff;
|
|
||||||
wrmsr(GLIU2_P2D_BM_1, msr);
|
|
||||||
|
|
||||||
// set the multiplex register with port 4 function
|
|
||||||
*((uint32_t*)UOCMUX) = USBOC_PORT4_FUNCTION;
|
|
||||||
|
|
||||||
// finally, disable the USB option controller memory mapping
|
|
||||||
msr.hi = 0x000000ff;
|
|
||||||
msr.lo = 0xfff00000;
|
|
||||||
wrmsr(GLIU2_P2D_BM_1, msr);
|
|
||||||
|
|
||||||
printk_debug("done.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ehci_init(struct device *dev)
|
|
||||||
{
|
|
||||||
uint32_t cmd;
|
|
||||||
printk_debug("USB: Setting up EHCI controller... ");
|
|
||||||
|
|
||||||
// enable controller bus mastering
|
|
||||||
cmd = pci_read_config32(dev, PCI_COMMAND);
|
|
||||||
pci_write_config32(dev, PCI_COMMAND,
|
|
||||||
cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
|
|
||||||
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
|
|
||||||
|
|
||||||
printk_debug("done.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct device_operations ohci_ops = {
|
|
||||||
.read_resources = pci_dev_read_resources,
|
|
||||||
.set_resources = pci_dev_set_resources,
|
|
||||||
.enable_resources = pci_dev_enable_resources,
|
|
||||||
.init = ohci_init,
|
|
||||||
.scan_bus = 0,
|
|
||||||
.enable = southbridge_enable,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct device_operations ehci_ops = {
|
|
||||||
.read_resources = pci_dev_read_resources,
|
|
||||||
.set_resources = pci_dev_set_resources,
|
|
||||||
.enable_resources = pci_dev_enable_resources,
|
|
||||||
.init = ehci_init,
|
|
||||||
.scan_bus = 0,
|
|
||||||
.enable = southbridge_enable,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pci_driver cs5536_usb1_driver __pci_driver = {
|
|
||||||
.ops = &ohci_ops,
|
|
||||||
.vendor = PCI_VENDOR_ID_AMD,
|
|
||||||
.device = PCI_DEVICE_ID_AMD_CS5536_OHCI
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pci_driver cs5536_usb2_driver __pci_driver = {
|
|
||||||
.ops = &ehci_ops,
|
|
||||||
.vendor = PCI_VENDOR_ID_AMD,
|
|
||||||
.device = PCI_DEVICE_ID_AMD_CS5536_EHCI
|
|
||||||
};
|
|
Loading…
Reference in New Issue