linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
@ 2006-05-17 10:14 Zang Roy-r61911
  2006-05-17 13:47 ` Kumar Gala
  2006-05-18  0:49 ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 5+ messages in thread
From: Zang Roy-r61911 @ 2006-05-17 10:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Alexandre.Bounine, Yang Xin-Xin-r48390

Add Tundra Semiconductor tsi108 host bridge common function support.

Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
Signed-off-by: Roy Zang	<tie-fei.zang@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@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 */
+};
+
+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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
  2006-05-17 10:14 [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function Zang Roy-r61911
@ 2006-05-17 13:47 ` Kumar Gala
  2006-05-18  0:49 ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 5+ messages in thread
From: Kumar Gala @ 2006-05-17 13:47 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine


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@tundra.com>
> Signed-off-by: Roy Zang	<tie-fei.zang@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@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@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
  2006-05-17 10:14 [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function Zang Roy-r61911
  2006-05-17 13:47 ` Kumar Gala
@ 2006-05-18  0:49 ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 5+ messages in thread
From: Benjamin Herrenschmidt @ 2006-05-18  0:49 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine

On Wed, 2006-05-17 at 18:14 +0800, Zang Roy-r61911 wrote:
> Add Tundra Semiconductor tsi108 host bridge common function support.

As I explained in the first patch, the PCI functions for the tsi108
should be kept together with the pci_ops structure. If you have a few
other functions unrelated to PCI, it's ok to keep them all in the same
file, but you start adding more, you should also think about splitting
tsi108_pci.c from tsi108_whateverelse.c :)

Ben.

> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang	<tie-fei.zang@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@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 */
> +};
> +
> +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);
> +}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
@ 2006-05-18  6:49 Zang Roy-r61911
  0 siblings, 0 replies; 5+ messages in thread
From: Zang Roy-r61911 @ 2006-05-18  6:49 UTC (permalink / raw)
  To: Kumar Gala
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]

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

I am not sure. I will have a try!

> 
> > +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;
> > +	}
> > +
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
@ 2006-05-25  4:20 Zang Roy-r61911
  0 siblings, 0 replies; 5+ messages in thread
From: Zang Roy-r61911 @ 2006-05-25  4:20 UTC (permalink / raw)
  To: Kumar Gala, Benjamin Herrenschmidt
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine


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

Now , I was confirmed that we cannot switch to it.
Reason for that is our need for the machine check exception handling for PCI Config reads.
Tsi108/109 does not have HW mechanism to ignore Master Abort during Config read and return all ones. 
We have to provide our routine with .fixup section to be able process failed PCI Config reads (Master Abort on PCI).
The indirect method relies on the HW mechanism. 

Another question that appeared around machine check handling was calling of tsi108_clear_pci_cfg_error() function.
We have it to clean errors reported during PCI bus probe. We may skip it (and PCI block still be operational) but
 this will block error reporting mechanism because the PCI block only records the first detected error. 
So we decided it may be better to keep error reporting active by cleaning errors that we expect during PCI enumeration.
 I do not see any harm here because I will  provide our own machine check handler in my board support file according to 
Ben's suggestion.

Roy 


> 
> > +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;
> > +}
> > +

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-05-25  4:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-17 10:14 [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function Zang Roy-r61911
2006-05-17 13:47 ` Kumar Gala
2006-05-18  0:49 ` Benjamin Herrenschmidt
  -- strict thread matches above, loose matches on Subject: below --
2006-05-18  6:49 Zang Roy-r61911
2006-05-25  4:20 Zang Roy-r61911

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).