diff options
-rw-r--r-- | src/soc/amd/common/block/alink/Kconfig | 5 | ||||
-rw-r--r-- | src/soc/amd/common/block/alink/Makefile.inc | 6 | ||||
-rw-r--r-- | src/soc/amd/common/block/alink/alink.c | 95 | ||||
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/alink.h | 48 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/include/soc/smbus.h | 23 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/smbus.c | 76 |
6 files changed, 154 insertions, 99 deletions
diff --git a/src/soc/amd/common/block/alink/Kconfig b/src/soc/amd/common/block/alink/Kconfig new file mode 100644 index 0000000000..75cf66f194 --- /dev/null +++ b/src/soc/amd/common/block/alink/Kconfig @@ -0,0 +1,5 @@ +config SOC_AMD_COMMON_BLOCK_ALINK + bool + default n + help + Select this option to access the FCH A-link configuration registers. diff --git a/src/soc/amd/common/block/alink/Makefile.inc b/src/soc/amd/common/block/alink/Makefile.inc new file mode 100644 index 0000000000..720a7cbd82 --- /dev/null +++ b/src/soc/amd/common/block/alink/Makefile.inc @@ -0,0 +1,6 @@ +bootblock-$(CONFIG_SOC_AMD_COMMON_BLOCK_ALINK) += alink.c +verstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_ALINK) += alink.c +romstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_ALINK) += alink.c +postcar-$(CONFIG_SOC_AMD_COMMON_BLOCK_ALINK) += alink.c +ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_ALINK) += alink.c +smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_ALINK) += alink.c diff --git a/src/soc/amd/common/block/alink/alink.c b/src/soc/amd/common/block/alink/alink.c new file mode 100644 index 0000000000..f481f6b340 --- /dev/null +++ b/src/soc/amd/common/block/alink/alink.c @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <stdint.h> +#include <console/console.h> +#include <amdblocks/alink.h> + +void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val) +{ + u32 tmp; + + outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); + tmp = inl(AB_DATA); + /* rpr 4.2 + * For certain revisions of the chip, the ABCFG registers, + * with an address of 0x100NN (where 'N' is any hexadecimal + * number), require an extra programming step.*/ + outl(0, AB_INDX); + + tmp &= ~mask; + tmp |= val; + + // printk(BIOS_DEBUG, "about write %x, index=%x", tmp, + // (reg_space&0x3)<<29 | reg_addr); + + /* probably we dont have to do it again. */ + outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); + outl(tmp, AB_DATA); + outl(0, AB_INDX); +} + +void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val) +{ + u32 tmp; + + outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); + tmp = inl(AB_DATA); + /* rpr 4.2 + * For certain revisions of the chip, the ABCFG registers, + * with an address of 0x100NN (where 'N' is any hexadecimal + * number), require an extra programming step.*/ + outl(0, AB_INDX); + + tmp &= ~mask; + tmp |= val; + + //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, + // (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr); + + /* probably we dont have to do it again. */ + outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); + outl(tmp, AB_DATA); + outl(0, AB_INDX); +} + +/* + * space = 0: AX_INDXC, AX_DATAC + * space = 1: AX_INDXP, AX_DATAP + */ +void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val) +{ + u32 tmp; + + /* read axindc to tmp */ + outl(space << 29 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(0, AB_INDX); + outl(space << 29 | space << 3 | 0x34, AB_INDX); + tmp = inl(AB_DATA); + outl(0, AB_INDX); + + tmp &= ~mask; + tmp |= val; + + /* write tmp */ + outl(space << 29 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(0, AB_INDX); + outl(space << 29 | space << 3 | 0x34, AB_INDX); + outl(tmp, AB_DATA); + outl(0, AB_INDX); +} diff --git a/src/soc/amd/common/block/include/amdblocks/alink.h b/src/soc/amd/common/block/include/amdblocks/alink.h new file mode 100644 index 0000000000..a6f748b809 --- /dev/null +++ b/src/soc/amd/common/block/include/amdblocks/alink.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __AMDBLOCKS_ALINK_H__ +#define __AMDBLOCKS_ALINK_H__ + +#include <stdint.h> + +#define AB_INDX 0xcd8 +#define AB_DATA (AB_INDX + 4) + +#define AX_INDXC 0 +#define AX_INDXP 2 +#define AXCFG 4 +#define ABCFG 6 +#define RC_INDXC 1 +#define RC_INDXP 3 + +#define abcfg_reg(reg, mask, val) \ + alink_ab_indx((ABCFG), (reg), (mask), (val)) +#define axcfg_reg(reg, mask, val) \ + alink_ab_indx((AXCFG), (reg), (mask), (val)) +#define axindxc_reg(reg, mask, val) \ + alink_ax_indx((AX_INDXC), (reg), (mask), (val)) +#define axindxp_reg(reg, mask, val) \ + alink_ax_indx((AX_INDXP), (reg), (mask), (val)) +#define rcindxc_reg(reg, port, mask, val) \ + alink_rc_indx((RC_INDXC), (reg), (port), (mask), (val)) +#define rcindxp_reg(reg, port, mask, val) \ + alink_rc_indx((RC_INDXP), (reg), (port), (mask), (val)) + +void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val); +void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val); +void alink_ax_indx(u32 space /* c or p? */, u32 axindc, u32 mask, u32 val); + +#endif /* __AMDBLOCKS_ALINK_H__ */ diff --git a/src/soc/amd/stoneyridge/include/soc/smbus.h b/src/soc/amd/stoneyridge/include/soc/smbus.h index 71f7fafa5e..391084d807 100644 --- a/src/soc/amd/stoneyridge/include/soc/smbus.h +++ b/src/soc/amd/stoneyridge/include/soc/smbus.h @@ -21,38 +21,15 @@ #define SMB_SPEED_400KHZ (66000000 / (400000 * 4)) -#define AX_INDXC 0 -#define AX_INDXP 2 -#define AXCFG 4 -#define ABCFG 6 -#define RC_INDXC 1 -#define RC_INDXP 3 - /* * Between 1-10 seconds, We should never timeout normally * Longer than this is just painful when a timeout condition occurs. */ #define SMBUS_TIMEOUT (100 * 1000 * 10) -#define abcfg_reg(reg, mask, val) \ - alink_ab_indx((ABCFG), (reg), (mask), (val)) -#define axcfg_reg(reg, mask, val) \ - alink_ab_indx((AXCFG), (reg), (mask), (val)) -#define axindxc_reg(reg, mask, val) \ - alink_ax_indx((AX_INDXC), (reg), (mask), (val)) -#define axindxp_reg(reg, mask, val) \ - alink_ax_indx((AX_INDXP), (reg), (mask), (val)) -#define rcindxc_reg(reg, port, mask, val) \ - alink_rc_indx((RC_INDXC), (reg), (port), (mask), (val)) -#define rcindxp_reg(reg, port, mask, val) \ - alink_rc_indx((RC_INDXP), (reg), (port), (mask), (val)) - int do_smbus_read_byte(u32 mmio, u8 device, u8 address); int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val); int do_smbus_recv_byte(u32 mmio, u8 device); int do_smbus_send_byte(u32 mmio, u8 device, u8 val); -void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val); -void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val); -void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val); #endif /* __STONEYRIDGE_SMBUS_H__ */ diff --git a/src/soc/amd/stoneyridge/smbus.c b/src/soc/amd/stoneyridge/smbus.c index df7a86edc7..31457f98b8 100644 --- a/src/soc/amd/stoneyridge/smbus.c +++ b/src/soc/amd/stoneyridge/smbus.c @@ -189,79 +189,3 @@ int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val) return 0; } - -void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val) -{ - u32 tmp; - - outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); - tmp = inl(AB_DATA); - /* rpr 4.2 - * For certain revisions of the chip, the ABCFG registers, - * with an address of 0x100NN (where 'N' is any hexadecimal - * number), require an extra programming step.*/ - outl(0, AB_INDX); - - tmp &= ~mask; - tmp |= val; - - // printk(BIOS_DEBUG, "about write %x, index=%x", tmp, - // (reg_space&0x3)<<29 | reg_addr); - - /* probably we dont have to do it again. */ - outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); - outl(tmp, AB_DATA); - outl(0, AB_INDX); -} - -void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val) -{ - u32 tmp; - - outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); - tmp = inl(AB_DATA); - /* rpr 4.2 - * For certain revisions of the chip, the ABCFG registers, - * with an address of 0x100NN (where 'N' is any hexadecimal - * number), require an extra programming step.*/ - outl(0, AB_INDX); - - tmp &= ~mask; - tmp |= val; - - //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, - // (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr); - - /* probably we dont have to do it again. */ - outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); - outl(tmp, AB_DATA); - outl(0, AB_INDX); -} - -/* - * space = 0: AX_INDXC, AX_DATAC - * space = 1: AX_INDXP, AX_DATAP - */ -void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val) -{ - u32 tmp; - - /* read axindc to tmp */ - outl(space << 29 | space << 3 | 0x30, AB_INDX); - outl(axindc, AB_DATA); - outl(0, AB_INDX); - outl(space << 29 | space << 3 | 0x34, AB_INDX); - tmp = inl(AB_DATA); - outl(0, AB_INDX); - - tmp &= ~mask; - tmp |= val; - - /* write tmp */ - outl(space << 29 | space << 3 | 0x30, AB_INDX); - outl(axindc, AB_DATA); - outl(0, AB_INDX); - outl(space << 29 | space << 3 | 0x34, AB_INDX); - outl(tmp, AB_DATA); - outl(0, AB_INDX); -} |