Add comments, correct warnings, add a note by Marc Jones,

and change a name per Marc Jone's suggestion.
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Peter Stuge <peter@stuge.se>




git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@346 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Ronald G. Minnich 2007-06-05 21:01:05 +00:00
commit faf5bc5f1b
2 changed files with 85 additions and 56 deletions

View file

@ -16,47 +16,59 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <console.h>
#include <io.h>
#include <msr.h>
#include <amd_geodelx.h>
#include "cs5536.h"
/*
* cs5536_early_setup.c:Early chipset initialization for CS5536 companion device
* This code is needed for setting up ram, since we need SMBUS working as
* well as serial port.
* This code is needed for setting up ram, since we need SMBUS working as
* well as serial port.
* This file implements the initialization sequence documented in section 4.2 of
* AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide.
*/
/**
* @brief Set up GLINK routing for this part. The routing is controlled by an MSR.
* @brief Set up GLINK routing for this part. The routing is controlled by an MSR.
* This appears to be the
* same on all boards.
* If you don't know what GLINK routing is, there is no way to explain it here.
*/
static void cs5536_setup_extmsr(void)
void cs5536_setup_extmsr(void)
{
msr_t msr;
/* forward MSR access to CS5536_GLINK_PORT_NUM to CS5536_DEV_NUM */
msr.hi = msr.lo = 0x00000000;
if (CS5536_GLINK_PORT_NUM <= 4) {
msr.lo = CS5536_DEV_NUM <<
(unsigned char)((CS5536_GLINK_PORT_NUM - 1) * 8);
} else {
msr.hi = CS5536_DEV_NUM <<
(unsigned char)((CS5536_GLINK_PORT_NUM - 5) * 8);
}
#if CS5536_GLINK_PORT_NUM <= 4
msr.lo = CS5536_DEV_NUM <<
(unsigned char)((CS5536_GLINK_PORT_NUM - 1) * 8);
#else
msr.hi = CS5536_DEV_NUM <<
(unsigned char)((CS5536_GLINK_PORT_NUM - 5) * 8);
#endif
wrmsr(GLPCI_ExtMSR, msr);
}
/**
* @brief Setup PCI IDSEL for CS5536
* @brief Setup PCI IDSEL for CS5536. There is a Magic Register that must be
* written so that the chip appears at the expected place in the PCI tree.
*/
static void cs5536_setup_idsel(void)
void cs5536_setup_idsel(void)
{
/* write IDSEL to the write once register at address 0x0000 */
outl(0x1 << (CS5536_DEV_NUM + 10), 0);
}
/**
* @brief Need to get a good explanation of what this is.
* @brief Magic Bits for undocumented register.
* You don' t need to see those papers.
* These are not the bits you're looking for.
* You can go about your business.
* Move along, move along.
*/
static void cs5536_usb_swapsif(void)
void cs5536_usb_swapsif(void)
{
msr_t msr;
@ -72,13 +84,13 @@ static void cs5536_usb_swapsif(void)
}
/**
* @brief Set up IO bases for SMBUS, GPIO, MFGPT, ACPI, and PM.
* These can be changed by Linux later. We set some initial value so
* that the resources are there as needed.
* @brief Set up IO bases for SMBUS, GPIO, MFGPT, ACPI, and PM.
* These can be changed by Linux later. We set some initial value so
* that the resources are there as needed.
* The values are hardcoded because, this early in the process, fancy
* allocation can do more harm than good.
* allocation can do more harm than good.
*/
static void cs5536_setup_iobase(void)
void cs5536_setup_iobase(void)
{
msr_t msr;
/* setup LBAR for SMBus controller */
@ -108,30 +120,28 @@ static void cs5536_setup_iobase(void)
}
/**
* @brief Set up the power button for operation.
* @brief Power Button Setup
* 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.
*/
static void cs5536_setup_power_button(void)
void cs5536_setup_power_button(void)
{
/* Power Button Setup */
outl(0x40020000, PMS_IO_BASE + 0x40);
/* 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.
*/
outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUT_AUX1_SELECT);
outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUTPUT_ENABLE);
}
/**
* @brief Set the various GPIOs. An unknown question at this point is
* how general this is to all mainboards.
* @brief Set the various GPIOs. An unknown question at this point is
* how general this is to all mainboards. At the same time, many
* boards seem to follow this particular reference spec.
*/
static void cs5536_setup_gpio(void)
void cs5536_setup_smbus_gpio(void)
{
uint32_t val;
u32 val;
/* setup GPIO pins 14/15 for SDA/SCL */
val = GPIOL_15_SET | GPIOL_14_SET;
@ -146,14 +156,14 @@ static void cs5536_setup_gpio(void)
}
/**
* @brief Disable the internal UART.
* Different boards have different UARTs for COM1.
* @brief Disable the internal UART.
* Different boards have different UARTs for COM1.
*/
static void cs5536_disable_internal_uart(void)
void cs5536_disable_internal_uart(void)
{
msr_t msr;
/* The UARTs default to enabled.
* Disable and reset them and configure them later. (SIO init)
* Disable and reset them and configure them later. (SIO init)
*/
msr = rdmsr(MDD_UART1_CONF);
msr.lo = 1; // reset
@ -169,9 +179,11 @@ static void cs5536_disable_internal_uart(void)
}
/**
* @brief Set up the cs5536 CIS interface to CPU interface to match modes.
* @brief Set up the cs5536 CIS interface to CPU interface to match modes.
* The CIS is related to the interrupt system. It is important to match the
* south and the cpu chips. At the same time, they always seem to use mode B.
*/
static void cs5536_setup_cis_mode(void)
void cs5536_setup_cis_mode(void)
{
msr_t msr;
@ -183,10 +195,9 @@ static void cs5536_setup_cis_mode(void)
}
/**
* @brief Enable the on chip UART.
* @brief Enable the on chip UART.see page 412 of the cs5536 companion book
*/
/* see page 412 of the cs5536 companion book */
static void cs5536_setup_onchipuart(void)
void cs5536_setup_onchipuart(void)
{
msr_t msr;
@ -227,12 +238,30 @@ static void cs5536_setup_onchipuart(void)
/**
* @brief Board setup. Known to work on norwich and digitial logic boards.
* @brief Board setup. Known to work on norwich and digitial logic boards.
* The extmsr and cis_mode are common for sure.
* The RSTPLL check is mandatory.
* IDSEl of course is required, so the chip appears in PCI config space,
* and the swapsif covers a necessary chip fix.
* Finally, the iobase is needed for DRAM, the GPIOs
* are likely common to all boards, and the power button
* seems to be the same on all. At the same time,
* we may need to move gpio and power button
* out as developments demand.
* Note we do NOT do any UART
* setup here -- this is done later by the mainboard setup,
* since UART usage is not universal.
* setup here -- this is done later by the mainboard setup,
* since UART usage is not universal.
* A comment from Marc Jones:
"It
would be difficult to move this to early mainboard (car_auto) because
the IObase needs to be setup first and then SMBus setup would be
optional etc. I think that any platform that uses the SMBus GPIOs for
something other than SMBus will need a lot of customization anyway and
they would have to override the generic file. I understand the desire to
make everything generic but that really over complicates 99% of the
designs."
*/
static void cs5536_early_setup(void)
void cs5536_early_setup(void)
{
msr_t msr;
@ -251,7 +280,7 @@ static void cs5536_early_setup(void)
cs5536_setup_idsel();
cs5536_usb_swapsif();
cs5536_setup_iobase();
cs5536_setup_gpio();
cs5536_enable_smbus();
cs5536_setup_smbus_gpio();
/* cs5536_enable_smbus(); -- leave this out for now */
cs5536_setup_power_button();
}

View file

@ -259,37 +259,37 @@ static u8 do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address)
if (smbus_check_stop_condition(smbus_io_base)) {
error = "smbus_check_stop_condition timed out";
goto err
goto err;
}
if (errno = smbus_start_condition(smbus_io_base)) {
if ((errno = smbus_start_condition(smbus_io_base))) {
error = "smbus_start_condition";
goto err;
}
if (errno = smbus_send_slave_address(smbus_io_base, device)) {
if ((errno = smbus_send_slave_address(smbus_io_base, device))) {
error = "smbus_send_slave_address";
goto err;
}
smbus_ack(smbus_io_base);
if (errno = smbus_send_command(smbus_io_base, address)) {
if ((errno = smbus_send_command(smbus_io_base, address))) {
error = "smbus_send_command";
goto err;
}
if (errno = smbus_start_condition(smbus_io_base)) {
if ((errno = smbus_start_condition(smbus_io_base))) {
error = "smbus_start_condition";
goto err;
}
if (errno = smbus_send_slave_address(smbus_io_base, device | 0x01)) {
if ((errno = smbus_send_slave_address(smbus_io_base, device | 0x01))) {
error = "smbus_send_slave_address";
goto err;
}
if (errno = smbus_stop_condition(smbus_io_base)) {
if ((errno = smbus_stop_condition(smbus_io_base))) {
error = "second smbus_stop_condition";
goto err;
}