[PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function

Kumar Gala galak at kernel.crashing.org
Wed May 17 23:47:43 EST 2006


On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:

> Add Tundra Semiconductor tsi108 host bridge common function support.
>
> Signed-off-by: Alexandre Bounine <alexandreb at tundra.com>
> Signed-off-by: Roy Zang	<tie-fei.zang at freescale.com>
>
> ---
>
>  arch/powerpc/sysdev/Makefile        |    1
>  arch/powerpc/sysdev/tsi108_common.c |  224 ++++++++++++++++++++++++ 
> +++++++++++
>  2 files changed, 225 insertions(+), 0 deletions(-)
>  create mode 100644 arch/powerpc/sysdev/tsi108_common.c
>
> ab3b477b5924d2c9cbf6ba3ae4d95fe333c9bad9
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/ 
> Makefile
> index 4c2b356..8c0afb7 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_U3_DART)		+= dart_iommu.o
>  obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
>  obj-$(CONFIG_PPC_83xx)		+= ipic.o
>  obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
> +obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_common.o tsi108_pic.o
> diff --git a/arch/powerpc/sysdev/tsi108_common.c b/arch/powerpc/ 
> sysdev/tsi108_common.c
> new file mode 100644
> index 0000000..3c55f99
> --- /dev/null
> +++ b/arch/powerpc/sysdev/tsi108_common.c
> @@ -0,0 +1,224 @@
> +/*
> + * arch/ppc/syslib/tsi108_common.c
> + *
> + * Common routines for Tundra Semiconductor TSI108 host bridge.
> + *
> + * 2004-2005 (c) Tundra Semiconductor Corp.
> + * Author: Alex Bounine (alexandreb at tundra.com)
> + *
> + * 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; either version 2 of the License, or (at  
> your option)
> + * any later version.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public  
> License along with
> + * this program; if not, write to the Free Software Foundation,  
> Inc., 59
> + * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/slab.h>
> +
> +#include <asm/byteorder.h>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/uaccess.h>
> +#include <asm/machdep.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/tsi108.h>
> +#include <asm/prom.h>
> +
> +u32 tsi108_pci_cfg_base;
> +
> +#undef TSI108_PCI_DEBUG
> +
> +#define tsi_mk_config_addr(bus, devfunc, offset) \
> +	(((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)|  
> tsi108_pci_cfg_base)
> +
> +static phys_addr_t tsi108_csr_base = -1;
> +
> +phys_addr_t get_csrbase(void)
> +{
> +	struct device_node *tsi;
> +
> +	if (tsi108_csr_base != -1)
> +		return tsi108_csr_base;
> +
> +	tsi = of_find_node_by_type(NULL, "tsi-bridge");
> +	if (tsi) {
> +		unsigned int size;
> +		void *prop = get_property(tsi, "reg", &size);
> +		tsi108_csr_base = of_translate_address(tsi, prop);
> +		of_node_put(tsi);
> +	};
> +	return tsi108_csr_base;
> +}
> +
> +u32 get_vir_csrbase(void)
> +{
> +	return (u32) (ioremap(get_csrbase(), 0x10000));
> +}
> +
> +EXPORT_SYMBOL(get_csrbase);
> +EXPORT_SYMBOL(get_vir_csrbase);
> +
> +/*
> + * Prosessor Bus Clock (in MHz) defined by CG_PB_SELECT
> + * (based on recommended Tsi108 reference clock 33MHz)
> + */
> +static int pb_clk_sel[8] = { 0, 0, 183, 100, 133, 167, 200, 233 };
> +
> +/*
> + * SDRAM Clock (in MHz) defined by CG_SD_SELECT
> + * (based on recommended Tsi108 reference clock 33MHz)
> + */
> +static int sd_clk_sel[2][8] = {
> +	{0, 0, 183, 100, 133, 167, 200, 233},	/* SYNC */
> +	{0, 0, 0, 0, 133, 160, 200, 0}	/* ASYNC */
> +};
> +

Can the PCI use indirect like used on most other PPC platforms.

> +int
> +tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
> +			   int offset, int len, u32 val)
> +{
> +	volatile unsigned char *cfg_addr;
> +
> +	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
> +							devfunc, offset) |
> +				     (offset & 0x03));
> +
> +#ifdef TSI108_PCI_DEBUG
> +	printk("PCI CFG write : ");
> +	printk("%d:0x%x:0x%x ", bus->number, devfunc, offset);
> +	printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
> +	printk("data = 0x%08x\n", val);
> +#endif
> +
> +	switch (len) {
> +	case 1:
> +		out_8((u8 *) cfg_addr, val);
> +		break;
> +	case 2:
> +		out_le16((u16 *) cfg_addr, val);
> +		break;
> +	default:
> +		out_le32((u32 *) cfg_addr, val);
> +		break;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +void tsi108_clear_pci_error(u32 pci_cfg_base)
> +{
> +	u32 err_stat, err_addr, pci_stat;
> +
> +	/*
> +	 * Quietly clear PB and PCI error flags set as result
> +	 * of PCI/X configuration read requests.
> +	 */
> +
> +	/* Read PB Error Log Registers */
> +
> +	err_stat = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS);
> +	err_addr = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_AERR);
> +
> +	if (err_stat & TSI108_PB_ERRCS_ES) {
> +		/* Clear error flag */
> +		tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS,
> +				 TSI108_PB_ERRCS_ES);
> +
> +		/* Clear read error reported in PB_ISR */
> +		tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ISR,
> +				 TSI108_PB_ISR_PBS_RD_ERR);
> +
> +		/* Clear PCI/X bus cfg errors if applicable */
> +		if ((err_addr & 0xFF000000) == pci_cfg_base) {
> +			pci_stat =
> +			    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR);
> +			tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR,
> +					 pci_stat);
> +		}
> +	}
> +
> +	return;
> +}
> +
> +#define __tsi108_read_pci_config(x, addr, op)		\
> +	__asm__ __volatile__(				\
> +		"	"op" %0,0,%1\n"		\
> +		"1:	eieio\n"			\
> +		"2:\n"					\
> +		".section .fixup,\"ax\"\n"		\
> +		"3:	li %0,-1\n"			\
> +		"	b 2b\n"				\
> +		".section __ex_table,\"a\"\n"		\
> +		"	.align 2\n"			\
> +		"	.long 1b,3b\n"			\
> +		".text"					\
> +		: "=r"(x) : "r"(addr))
> +
> +int
> +tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn,  
> int offset,
> +			  int len, u32 * val)
> +{
> +	volatile unsigned char *cfg_addr;
> +	u32 temp;
> +
> +	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
> +							devfn,
> +							offset) | (offset &
> +								   0x03));
> +
> +	switch (len) {
> +	case 1:
> +		__tsi108_read_pci_config(temp, cfg_addr, "lbzx");
> +		break;
> +	case 2:
> +		__tsi108_read_pci_config(temp, cfg_addr, "lhbrx");
> +		break;
> +	default:
> +		__tsi108_read_pci_config(temp, cfg_addr, "lwbrx");
> +		break;
> +	}
> +
> +	*val = temp;
> +
> +#ifdef TSI108_PCI_DEBUG
> +	if ((0xFFFFFFFF != temp) && (0xFFFF != temp) && (0xFF != temp)) {
> +		printk("PCI CFG read : ");
> +		printk("%d:0x%x:0x%x ", bus->number, devfn, offset);
> +		printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
> +		printk("data = 0x%x\n", *val);
> +	}
> +#endif
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +unsigned long tsi108_get_cpu_clk(void)
> +{
> +	/* Detect PB clock freq. */
> +	u32 i = tsi108_read_reg(TSI108_CLK_OFFSET + TSI108_CG_PWRUP_STATUS);
> +
> +	i = (i >> 16) & 0x07;	/* Get PB PLL multiplier */
> +	return (pb_clk_sel[i] * 1000000);
> +}
> +
> +unsigned long tsi108_get_sdc_clk(void)
> +{
> +	u32 i, k;
> +
> +	/* Get SDC/PB clock freq. from CG settings */
> +	i = tsi108_read_reg(TSI108_CLK_OFFSET + TSI108_CG_PWRUP_STATUS);
> +	k = (i >> 16) & 0x07;	/* Get PB PLL multiplier */
> +	i = (i >> 20) & 0x07;	/* Get SDC PLL multiplier */
> +	k = (k == i) ? 0 : 1;	/* sync/async configuration */
> +	return (sd_clk_sel[k][i] * 1000000);
> +}
> -- 
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev




More information about the Linuxppc-dev mailing list