LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [patch 1/6] pasemi_mac: Move RX/TX section enablement to dma_lib
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, pasemi-linux, linuxppc-dev
In-Reply-To: <20080221025753.903665000@lixom.net>

Also stop both rx and tx sections before changing the configuration of
the dma device during init.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/dma_lib.c
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -478,6 +478,30 @@ int pasemi_dma_init(void)
 	for (i = 0; i < MAX_RXCH; i++)
 		__set_bit(i, rxch_free);
 
+	i = 1000;
+	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
+	while ((i > 0) && (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1))
+		i--;
+	if (i < 0)
+		printk(KERN_INFO "Warning: Could not disable RX section\n");
+
+	i = 1000;
+	pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
+	while ((i > 0) && (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1))
+		i--;
+	if (i < 0)
+		printk(KERN_INFO "Warning: Could not disable TX section\n");
+
+	/* setup resource allocations for the different DMA sections */
+	tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
+	pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
+
+	/* enable tx section */
+	pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
+
+	/* enable rx section */
+	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
+
 	printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
 		"(%d tx, %d rx channels)\n", num_txch, num_rxch);
 
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1043,12 +1043,6 @@ static int pasemi_mac_open(struct net_de
 	unsigned int flags;
 	int ret;
 
-	/* enable rx section */
-	write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
-
-	/* enable tx section */
-	write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
-
 	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
 		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
 		PAS_MAC_CFG_TXP_TIFT(8) | PAS_MAC_CFG_TXP_TIFG(12);
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 PA Semi, Inc
+ * Copyright (C) 2006-2008 PA Semi, Inc
  *
  * Hardware register layout and descriptor formats for the on-board
  * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
@@ -40,6 +40,11 @@ enum {
 	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
 	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
 	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
+	PAS_DMA_COM_CFG   = 0x114,	/* Common config reg	      */
+	PAS_DMA_TXF_SFLG0 = 0x140,	/* Set flags                  */
+	PAS_DMA_TXF_SFLG1 = 0x144,	/* Set flags                  */
+	PAS_DMA_TXF_CFLG0 = 0x148,	/* Set flags                  */
+	PAS_DMA_TXF_CFLG1 = 0x14c,	/* Set flags                  */
 };
 
 

-- 

^ permalink raw reply

* [patch 2/6] [POWERPC] pasemi: Add flag management functions to dma_lib
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, pasemi-linux, linuxppc-dev
In-Reply-To: <20080221025753.903665000@lixom.net>

Add functions to manage the channel syncronization flags to dma_lib
    
Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/dma_lib.c
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -26,6 +26,7 @@
 
 #define MAX_TXCH 64
 #define MAX_RXCH 64
+#define MAX_FLAGS 64
 
 static struct pasdma_status *dma_status;
 
@@ -43,6 +44,7 @@ static struct pci_dev *dma_pdev;
 
 static DECLARE_BITMAP(txch_free, MAX_TXCH);
 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
+static DECLARE_BITMAP(flags_free, MAX_FLAGS);
 
 /* pasemi_read_iob_reg - read IOB register
  * @reg: Register to read (offset into PCI CFG space)
@@ -373,6 +375,71 @@ void pasemi_dma_free_buf(struct pasemi_d
 }
 EXPORT_SYMBOL(pasemi_dma_free_buf);
 
+/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
+ *
+ * Allocates a flag for use with channel syncronization (event descriptors).
+ * Returns allocated flag (0-63), < 0 on error.
+ */
+int pasemi_dma_alloc_flag(void)
+{
+	int bit;
+
+retry:
+	bit = find_next_bit(flags_free, MAX_FLAGS, 0);
+	if (bit >= MAX_FLAGS)
+		return -ENOSPC;
+	if (!test_and_clear_bit(bit, flags_free))
+		goto retry;
+
+	return bit;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_flag);
+
+
+/* pasemi_dma_free_flag - Deallocates a flag (event)
+ * @flag: Flag number to deallocate
+ *
+ * Frees up a flag so it can be reused for other purposes.
+ */
+void pasemi_dma_free_flag(int flag)
+{
+	BUG_ON(test_bit(flag, flags_free));
+	BUG_ON(flag >= MAX_FLAGS);
+	set_bit(flag, flags_free);
+}
+EXPORT_SYMBOL(pasemi_dma_free_flag);
+
+
+/* pasemi_dma_set_flag - Sets a flag (event) to 1
+ * @flag: Flag number to set active
+ *
+ * Sets the flag provided to 1.
+ */
+void pasemi_dma_set_flag(int flag)
+{
+	BUG_ON(flag >= MAX_FLAGS);
+	if (flag < 32)
+		pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
+	else
+		pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
+}
+EXPORT_SYMBOL(pasemi_dma_set_flag);
+
+/* pasemi_dma_clear_flag - Sets a flag (event) to 0
+ * @flag: Flag number to set inactive
+ *
+ * Sets the flag provided to 0.
+ */
+void pasemi_dma_clear_flag(int flag)
+{
+	BUG_ON(flag >= MAX_FLAGS);
+	if (flag < 32)
+		pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
+	else
+		pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
+}
+EXPORT_SYMBOL(pasemi_dma_clear_flag);
+
 static void *map_onedev(struct pci_dev *p, int index)
 {
 	struct device_node *dn;
@@ -502,6 +569,13 @@ int pasemi_dma_init(void)
 	/* enable rx section */
 	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
 
+	for (i = 0; i < MAX_FLAGS; i++)
+		__set_bit(i, flags_free);
+
+	/* clear all status flags */
+	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
+	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
+
 	printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
 		"(%d tx, %d rx channels)\n", num_txch, num_rxch);
 
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -466,6 +466,12 @@ extern void *pasemi_dma_alloc_buf(struct
 extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
 				dma_addr_t *handle);
 
+/* Routines to allocate flags (events) for channel syncronization */
+extern int  pasemi_dma_alloc_flag(void);
+extern void pasemi_dma_free_flag(int flag);
+extern void pasemi_dma_set_flag(int flag);
+extern void pasemi_dma_clear_flag(int flag);
+
 /* Initialize the library, must be called before any other functions */
 extern int pasemi_dma_init(void);
 

-- 

^ permalink raw reply

* [patch 3/6] [POWERPC] pasemi: Add function engine management functions to dma_lib
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, pasemi-linux, linuxppc-dev
In-Reply-To: <20080221025753.903665000@lixom.net>

Used to allocate functions for crypto/checksum offload.
    
Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/dma_lib.c
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -27,6 +27,7 @@
 #define MAX_TXCH 64
 #define MAX_RXCH 64
 #define MAX_FLAGS 64
+#define MAX_FUN 8
 
 static struct pasdma_status *dma_status;
 
@@ -45,6 +46,7 @@ static struct pci_dev *dma_pdev;
 static DECLARE_BITMAP(txch_free, MAX_TXCH);
 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
 static DECLARE_BITMAP(flags_free, MAX_FLAGS);
+static DECLARE_BITMAP(fun_free, MAX_FUN);
 
 /* pasemi_read_iob_reg - read IOB register
  * @reg: Register to read (offset into PCI CFG space)
@@ -440,6 +442,41 @@ void pasemi_dma_clear_flag(int flag)
 }
 EXPORT_SYMBOL(pasemi_dma_clear_flag);
 
+/* pasemi_dma_alloc_fun - Allocate a function engine
+ *
+ * Allocates a function engine to use for crypto/checksum offload
+ * Returns allocated engine (0-8), < 0 on error.
+ */
+int pasemi_dma_alloc_fun(void)
+{
+	int bit;
+
+retry:
+	bit = find_next_bit(fun_free, MAX_FLAGS, 0);
+	if (bit >= MAX_FLAGS)
+		return -ENOSPC;
+	if (!test_and_clear_bit(bit, fun_free))
+		goto retry;
+
+	return bit;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_fun);
+
+
+/* pasemi_dma_free_fun - Deallocates a function engine
+ * @flag: Engine number to deallocate
+ *
+ * Frees up a function engine so it can be used for other purposes.
+ */
+void pasemi_dma_free_fun(int fun)
+{
+	BUG_ON(test_bit(fun, fun_free));
+	BUG_ON(fun >= MAX_FLAGS);
+	set_bit(fun, fun_free);
+}
+EXPORT_SYMBOL(pasemi_dma_free_fun);
+
+
 static void *map_onedev(struct pci_dev *p, int index)
 {
 	struct device_node *dn;
@@ -572,6 +609,9 @@ int pasemi_dma_init(void)
 	for (i = 0; i < MAX_FLAGS; i++)
 		__set_bit(i, flags_free);
 
+	for (i = 0; i < MAX_FUN; i++)
+		__set_bit(i, fun_free);
+
 	/* clear all status flags */
 	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
 	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -472,6 +472,10 @@ extern void pasemi_dma_free_flag(int fla
 extern void pasemi_dma_set_flag(int flag);
 extern void pasemi_dma_clear_flag(int flag);
 
+/* Routines to allocate function engines */
+extern int  pasemi_dma_alloc_fun(void);
+extern void pasemi_dma_free_fun(int fun);
+
 /* Initialize the library, must be called before any other functions */
 extern int pasemi_dma_init(void);
 

-- 

^ permalink raw reply

* [patch 4/6] pasemi_mac: jumbo frame support
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, pasemi-linux, linuxppc-dev
In-Reply-To: <20080221025753.903665000@lixom.net>

First cut at jumbo frame support. To support large MTU, one or several
separate channels must be allocated to calculate the TCP/UDP checksum
separately, since the mac lacks enough buffers to hold a whole packet
while it's being calculated.

Furthermore, it seems that a single function channel is not quite
enough to feed one of the 10Gig links, so allocate two channels for
XAUI interfaces.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: 2.6.25/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.c
+++ 2.6.25/drivers/net/pasemi_mac.c
@@ -59,11 +59,12 @@
 /* Must be a power of two */
 #define RX_RING_SIZE 2048
 #define TX_RING_SIZE 4096
+#define CS_RING_SIZE (TX_RING_SIZE*2)
 
 #define LRO_MAX_AGGR 64
 
 #define PE_MIN_MTU	64
-#define PE_MAX_MTU	1500
+#define PE_MAX_MTU	9000
 #define PE_DEF_MTU	ETH_DATA_LEN
 
 #define DEFAULT_MSG_ENABLE	  \
@@ -81,6 +82,7 @@
 #define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
 #define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
 #define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
 
 #define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
 				 & ((ring)->size - 1))
@@ -322,6 +324,103 @@ static int pasemi_mac_unmap_tx_skb(struc
 	return (nfrags + 3) & ~1;
 }
 
+static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac)
+{
+	struct pasemi_mac_csring *ring;
+	u32 val;
+	unsigned int cfg;
+	int chno;
+
+	ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
+				       offsetof(struct pasemi_mac_csring, chan));
+
+	if (!ring) {
+		dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
+		goto out_chan;
+	}
+
+	chno = ring->chan.chno;
+
+	ring->size = CS_RING_SIZE;
+	ring->next_to_fill = 0;
+
+	/* Allocate descriptors */
+	if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
+		goto out_ring_desc;
+
+	write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
+		      PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
+	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
+	val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3);
+
+	write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
+
+	ring->events[0] = pasemi_dma_alloc_flag();
+	ring->events[1] = pasemi_dma_alloc_flag();
+	if (ring->events[0] < 0 || ring->events[1] < 0)
+		goto out_flags;
+
+	pasemi_dma_clear_flag(ring->events[0]);
+	pasemi_dma_clear_flag(ring->events[1]);
+
+	ring->fun = pasemi_dma_alloc_fun();
+	if (ring->fun < 0)
+		goto out_fun;
+
+	cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP |
+	      PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) |
+	      PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ;
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+	write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
+
+	/* enable channel */
+	pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ |
+					   PAS_DMA_TXCHAN_TCMDSTA_DB |
+					   PAS_DMA_TXCHAN_TCMDSTA_DE |
+					   PAS_DMA_TXCHAN_TCMDSTA_DA);
+
+	return ring;
+
+out_fun:
+out_flags:
+	if (ring->events[0] >= 0)
+		pasemi_dma_free_flag(ring->events[0]);
+	if (ring->events[1] >= 0)
+		pasemi_dma_free_flag(ring->events[1]);
+	pasemi_dma_free_ring(&ring->chan);
+out_ring_desc:
+	pasemi_dma_free_chan(&ring->chan);
+out_chan:
+
+	return NULL;
+}
+
+static void pasemi_mac_setup_csrings(struct pasemi_mac *mac)
+{
+	int i;
+	mac->cs[0] = pasemi_mac_setup_csring(mac);
+	if (mac->type == MAC_TYPE_XAUI)
+		mac->cs[1] = pasemi_mac_setup_csring(mac);
+	else
+		mac->cs[1] = 0;
+
+	for (i = 0; i < MAX_CS; i++)
+		if (mac->cs[i])
+			mac->num_cs++;
+}
+
+static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
+{
+	pasemi_dma_stop_chan(&csring->chan);
+	pasemi_dma_free_flag(csring->events[0]);
+	pasemi_dma_free_flag(csring->events[1]);
+	pasemi_dma_free_ring(&csring->chan);
+	pasemi_dma_free_chan(&csring->chan);
+}
+
 static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
 {
 	struct pasemi_mac_rxring *ring;
@@ -445,7 +544,7 @@ pasemi_mac_setup_tx_resources(const stru
 	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
 	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
 	      PAS_DMA_TXCHAN_CFG_UP |
-	      PAS_DMA_TXCHAN_CFG_WT(2);
+	      PAS_DMA_TXCHAN_CFG_WT(4);
 
 	if (translation_enabled())
 		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
@@ -810,13 +909,21 @@ restart:
 		u64 mactx = TX_DESC(txring, i);
 		struct sk_buff *skb;
 
-		skb = TX_DESC_INFO(txring, i+1).skb;
-		nr_frags = TX_DESC_INFO(txring, i).dma;
-
 		if ((mactx  & XCT_MACTX_E) ||
 		    (*chan->status & PAS_STATUS_ERROR))
 			pasemi_mac_tx_error(mac, mactx);
 
+		/* Skip over control descriptors */
+		if (!(mactx & XCT_MACTX_LLEN_M)) {
+			TX_DESC(txring, i) = 0;
+			TX_DESC(txring, i+1) = 0;
+			buf_count = 2;
+			continue;
+		}
+
+		skb = TX_DESC_INFO(txring, i+1).skb;
+		nr_frags = TX_DESC_INFO(txring, i).dma;
+
 		if (unlikely(mactx & XCT_MACTX_O))
 			/* Not yet transmitted */
 			break;
@@ -1058,6 +1165,12 @@ static int pasemi_mac_open(struct net_de
 	if (!mac->tx)
 		goto out_tx_ring;
 
+	if (dev->mtu > 1500) {
+		pasemi_mac_setup_csrings(mac);
+		if (!mac->num_cs)
+			goto out_tx_ring;
+	}
+
 	/* 0x3ff with 33MHz clock is about 31us */
 	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
 		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
@@ -1241,7 +1354,7 @@ static int pasemi_mac_close(struct net_d
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int sta;
-	int rxch, txch;
+	int rxch, txch, i;
 
 	rxch = rx_ring(mac)->chan.chno;
 	txch = tx_ring(mac)->chan.chno;
@@ -1286,6 +1399,9 @@ static int pasemi_mac_close(struct net_d
 	free_irq(mac->tx->chan.irq, mac->tx);
 	free_irq(mac->rx->chan.irq, mac->rx);
 
+	for (i = 0; i < mac->num_cs; i++)
+		pasemi_mac_free_csring(mac->cs[i]);
+
 	/* Free resources */
 	pasemi_mac_free_rx_resources(mac);
 	pasemi_mac_free_tx_resources(mac);
@@ -1293,35 +1409,113 @@ static int pasemi_mac_close(struct net_d
 	return 0;
 }
 
+static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
+				    const dma_addr_t *map,
+				    const unsigned int *map_size,
+				    struct pasemi_mac_txring *txring,
+				    struct pasemi_mac_csring *csring)
+{
+	u64 fund;
+	dma_addr_t cs_dest;
+	const int nh_off = skb_network_offset(skb);
+	const int nh_len = skb_network_header_len(skb);
+	const int nfrags = skb_shinfo(skb)->nr_frags;
+	int cs_size, i, fill, hdr, cpyhdr, evt;
+	dma_addr_t csdma;
+
+	fund = XCT_FUN_ST | XCT_FUN_RR_8BRES |
+	       XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
+	       XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) |
+	       XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE;
+
+	switch (ip_hdr(skb)->protocol) {
+	case IPPROTO_TCP:
+		fund |= XCT_FUN_SIG_TCP4;
+		/* TCP checksum is 16 bytes into the header */
+		cs_dest = map[0] + skb_transport_offset(skb) + 16;
+		break;
+	case IPPROTO_UDP:
+		fund |= XCT_FUN_SIG_UDP4;
+		/* UDP checksum is 6 bytes into the header */
+		cs_dest = map[0] + skb_transport_offset(skb) + 6;
+		break;
+	default:
+		WARN_ON(1);
+	}
+
+	/* Do the checksum offloaded */
+	fill = csring->next_to_fill;
+	hdr = fill;
+
+	CS_DESC(csring, fill++) = fund;
+	/* Room for 8BRES. Checksum result is really 2 bytes into it */
+	csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2;
+	CS_DESC(csring, fill++) = 0;
+
+	CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off);
+	for (i = 1; i <= nfrags; i++)
+		CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
+
+	fill += i;
+	if (fill & 1)
+		fill++;
+
+	/* Copy the result into the TCP packet */
+	cpyhdr = fill;
+	CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
+				  XCT_FUN_LLEN(2) | XCT_FUN_SE;
+	CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T;
+	CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma);
+	fill++;
+
+	evt = !csring->last_event;
+	csring->last_event = evt;
+
+	/* Event handshaking with MAC TX */
+	CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]);
+	CS_DESC(csring, fill++) = 0;
+	CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]);
+	CS_DESC(csring, fill++) = 0;
+	csring->next_to_fill = fill & (CS_RING_SIZE-1);
+
+	cs_size = fill - hdr;
+	write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
+
+	/* TX-side event handshaking */
+	fill = txring->next_to_fill;
+	TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]);
+	TX_DESC(txring, fill++) = 0;
+	TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+				  CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]);
+	TX_DESC(txring, fill++) = 0;
+	txring->next_to_fill = fill;
+
+	write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
+
+	return;
+}
+
 static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct pasemi_mac *mac = netdev_priv(dev);
-	struct pasemi_mac_txring *txring;
-	u64 dflags, mactx;
+	struct pasemi_mac * const mac = netdev_priv(dev);
+	struct pasemi_mac_txring * const txring = tx_ring(mac);
+	struct pasemi_mac_csring *csring;
+	u64 dflags = 0;
+	u64 mactx;
 	dma_addr_t map[MAX_SKB_FRAGS+1];
 	unsigned int map_size[MAX_SKB_FRAGS+1];
 	unsigned long flags;
 	int i, nfrags;
 	int fill;
+	const int nh_off = skb_network_offset(skb);
+	const int nh_len = skb_network_header_len(skb);
 
-	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
-
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const unsigned char *nh = skb_network_header(skb);
+	prefetch(&txring->ring_info);
 
-		switch (ip_hdr(skb)->protocol) {
-		case IPPROTO_TCP:
-			dflags |= XCT_MACTX_CSUM_TCP;
-			dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
-			dflags |= XCT_MACTX_IPO(nh - skb->data);
-			break;
-		case IPPROTO_UDP:
-			dflags |= XCT_MACTX_CSUM_UDP;
-			dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
-			dflags |= XCT_MACTX_IPO(nh - skb->data);
-			break;
-		}
-	}
+	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
 
 	nfrags = skb_shinfo(skb)->nr_frags;
 
@@ -1344,24 +1538,46 @@ static int pasemi_mac_start_tx(struct sk
 		}
 	}
 
-	mactx = dflags | XCT_MACTX_LLEN(skb->len);
+	if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) {
+		switch (ip_hdr(skb)->protocol) {
+		case IPPROTO_TCP:
+			dflags |= XCT_MACTX_CSUM_TCP;
+			dflags |= XCT_MACTX_IPH(nh_len >> 2);
+			dflags |= XCT_MACTX_IPO(nh_off);
+			break;
+		case IPPROTO_UDP:
+			dflags |= XCT_MACTX_CSUM_UDP;
+			dflags |= XCT_MACTX_IPH(nh_len >> 2);
+			dflags |= XCT_MACTX_IPO(nh_off);
+			break;
+		default:
+			WARN_ON(1);
+		}
+	}
 
-	txring = tx_ring(mac);
+	mactx = dflags | XCT_MACTX_LLEN(skb->len);
 
 	spin_lock_irqsave(&txring->lock, flags);
 
-	fill = txring->next_to_fill;
-
 	/* Avoid stepping on the same cache line that the DMA controller
 	 * is currently about to send, so leave at least 8 words available.
 	 * Total free space needed is mactx + fragments + 8
 	 */
-	if (RING_AVAIL(txring) < nfrags + 10) {
+	if (RING_AVAIL(txring) < nfrags + 14) {
 		/* no room -- stop the queue and wait for tx intr */
 		netif_stop_queue(dev);
 		goto out_err;
 	}
 
+	if (mac->num_cs && skb->len > 1540) {
+		csring = mac->cs[mac->last_cs];
+		mac->last_cs = (mac->last_cs+1) % mac->num_cs;
+
+		/* Queue up checksum + event descriptors, if needed */
+		pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring);
+	}
+
+	fill = txring->next_to_fill;
 	TX_DESC(txring, fill) = mactx;
 	TX_DESC_INFO(txring, fill).dma = nfrags;
 	fill++;
@@ -1441,6 +1657,7 @@ static int pasemi_mac_change_mtu(struct 
 	unsigned int reg;
 	unsigned int rcmdsta;
 	int running;
+	int ret = 0;
 
 	if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
 		return -EINVAL;
@@ -1462,6 +1679,16 @@ static int pasemi_mac_change_mtu(struct 
 		pasemi_mac_pause_rxint(mac);
 		pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
 		pasemi_mac_free_rx_buffers(mac);
+
+	}
+
+	/* Setup checksum channels if large MTU and none already allocated */
+	if (new_mtu > 1500 && !mac->num_cs) {
+		pasemi_mac_setup_csrings(mac);
+		if (!mac->num_cs) {
+			ret = -ENOMEM;
+			goto out;
+		}
 	}
 
 	/* Change maxf, i.e. what size frames are accepted.
@@ -1476,6 +1703,7 @@ static int pasemi_mac_change_mtu(struct 
 	/* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
 	mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
+out:
 	if (running) {
 		write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
 			      rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
@@ -1488,7 +1716,7 @@ static int pasemi_mac_change_mtu(struct 
 		pasemi_mac_intf_enable(mac);
 	}
 
-	return 0;
+	return ret;
 }
 
 static int __devinit
Index: 2.6.25/drivers/net/pasemi_mac.h
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.h
+++ 2.6.25/drivers/net/pasemi_mac.h
@@ -27,6 +27,7 @@
 #include <linux/phy.h>
 
 #define MAX_LRO_DESCRIPTORS 8
+#define MAX_CS	2
 
 struct pasemi_mac_txring {
 	struct pasemi_dmachan chan; /* Must be first */
@@ -51,6 +52,15 @@ struct pasemi_mac_rxring {
 	struct pasemi_mac *mac;	/* Needed in intr handler */
 };
 
+struct pasemi_mac_csring {
+	struct pasemi_dmachan chan;
+	unsigned int	size;
+	unsigned int	next_to_fill;
+	int		events[2];
+	int		last_event;
+	int		fun;
+};
+
 struct pasemi_mac {
 	struct net_device *netdev;
 	struct pci_dev *pdev;
@@ -60,10 +70,12 @@ struct pasemi_mac {
 	struct napi_struct napi;
 
 	int		bufsz; /* RX ring buffer size */
+	int		last_cs;
+	int		num_cs;
+	u32		dma_if;
 	u8		type;
 #define MAC_TYPE_GMAC	1
 #define MAC_TYPE_XAUI	2
-	u32	dma_if;
 
 	u8		mac_addr[6];
 
@@ -74,6 +86,7 @@ struct pasemi_mac {
 
 	struct pasemi_mac_txring *tx;
 	struct pasemi_mac_rxring *rx;
+	struct pasemi_mac_csring *cs[MAX_CS];
 	char		tx_irq_name[10];		/* "eth%d tx" */
 	char		rx_irq_name[10];		/* "eth%d rx" */
 	int	link;
Index: 2.6.25/include/asm-powerpc/pasemi_dma.h
===================================================================
--- 2.6.25.orig/include/asm-powerpc/pasemi_dma.h
+++ 2.6.25/include/asm-powerpc/pasemi_dma.h
@@ -128,11 +128,16 @@ enum {
 #define    PAS_DMA_TXCHAN_TCMDSTA_DA	0x00000100
 #define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
+#define    PAS_DMA_TXCHAN_CFG_TY_COPY	0x00000001	/* Type = copy only */
+#define    PAS_DMA_TXCHAN_CFG_TY_FUNC	0x00000002	/* Type = function */
+#define    PAS_DMA_TXCHAN_CFG_TY_XOR	0x00000003	/* Type = xor only */
 #define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
 #define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
 #define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
 					 PAS_DMA_TXCHAN_CFG_TATTR_M)
-#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
+#define    PAS_DMA_TXCHAN_CFG_LPDQ	0x00000800
+#define    PAS_DMA_TXCHAN_CFG_LPSQ	0x00000400
+#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000003c0
 #define    PAS_DMA_TXCHAN_CFG_WT_S	6
 #define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
 					 PAS_DMA_TXCHAN_CFG_WT_M)
@@ -399,11 +404,62 @@ enum {
 				 XCT_COPY_LLEN_M)
 #define XCT_COPY_SE		0x0000000000000001ull
 
+/* Function descriptor fields */
+#define XCT_FUN_T		0x8000000000000000ull
+#define XCT_FUN_ST		0x4000000000000000ull
+#define XCT_FUN_RR_M		0x3000000000000000ull
+#define XCT_FUN_RR_NORES	0x0000000000000000ull
+#define XCT_FUN_RR_8BRES	0x1000000000000000ull
+#define XCT_FUN_RR_24BRES	0x2000000000000000ull
+#define XCT_FUN_RR_40BRES	0x3000000000000000ull
+#define XCT_FUN_I		0x0800000000000000ull
+#define XCT_FUN_O		0x0400000000000000ull
+#define XCT_FUN_E		0x0200000000000000ull
+#define XCT_FUN_FUN_M		0x01c0000000000000ull
+#define XCT_FUN_FUN_S		54
+#define XCT_FUN_FUN(x)		((((long)(x)) << XCT_FUN_FUN_S) & XCT_FUN_FUN_M)
+#define XCT_FUN_CRM_M		0x0038000000000000ull
+#define XCT_FUN_CRM_NOP		0x0000000000000000ull
+#define XCT_FUN_CRM_SIG		0x0008000000000000ull
+#define XCT_FUN_LLEN_M		0x0007ffff00000000ull
+#define XCT_FUN_LLEN_S		32
+#define XCT_FUN_LLEN(x)		((((long)(x)) << XCT_FUN_LLEN_S) & XCT_FUN_LLEN_M)
+#define XCT_FUN_SHL_M		0x00000000f8000000ull
+#define XCT_FUN_SHL_S		27
+#define XCT_FUN_SHL(x)		((((long)(x)) << XCT_FUN_SHL_S) & XCT_FUN_SHL_M)
+#define XCT_FUN_CHL_M		0x0000000007c00000ull
+#define XCT_FUN_HSZ_M		0x00000000003c0000ull
+#define XCT_FUN_ALG_M		0x0000000000038000ull
+#define XCT_FUN_HP		0x0000000000004000ull
+#define XCT_FUN_BCM_M		0x0000000000003800ull
+#define XCT_FUN_BCP_M		0x0000000000000600ull
+#define XCT_FUN_SIG_M		0x00000000000001f0ull
+#define XCT_FUN_SIG_TCP4	0x0000000000000140ull
+#define XCT_FUN_SIG_TCP6	0x0000000000000150ull
+#define XCT_FUN_SIG_UDP4	0x0000000000000160ull
+#define XCT_FUN_SIG_UDP6	0x0000000000000170ull
+#define XCT_FUN_A		0x0000000000000008ull
+#define XCT_FUN_C		0x0000000000000004ull
+#define XCT_FUN_AL2		0x0000000000000002ull
+#define XCT_FUN_SE		0x0000000000000001ull
+
+/* Function descriptor 8byte result fields */
+#define XCT_FUNRES_8B_CS_M	0x0000ffff00000000ull
+#define XCT_FUNRES_8B_CS_S	32
+#define XCT_FUNRES_8B_CRC_M	0x00000000ffffffffull
+#define XCT_FUNRES_8B_CRC_S	0
+
 /* Control descriptor fields */
 #define CTRL_CMD_T		0x8000000000000000ull
 #define CTRL_CMD_META_EVT	0x2000000000000000ull
 #define CTRL_CMD_O		0x0400000000000000ull
-#define CTRL_CMD_REG_M		0x000000000000000full
+#define CTRL_CMD_ETYPE_M	0x0038000000000000ull
+#define CTRL_CMD_ETYPE_EXT	0x0000000000000000ull
+#define CTRL_CMD_ETYPE_WSET	0x0020000000000000ull
+#define CTRL_CMD_ETYPE_WCLR	0x0028000000000000ull
+#define CTRL_CMD_ETYPE_SET	0x0030000000000000ull
+#define CTRL_CMD_ETYPE_CLR	0x0038000000000000ull
+#define CTRL_CMD_REG_M		0x000000000000007full
 #define CTRL_CMD_REG_S		0
 #define CTRL_CMD_REG(x)		((((long)(x)) << CTRL_CMD_REG_S) & \
 				 CTRL_CMD_REG_M)

-- 

^ permalink raw reply

* [patch 5/6] pasemi_mac: Enable GSO by default
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, pasemi-linux, linuxppc-dev
In-Reply-To: <20080221025753.903665000@lixom.net>

Ethtool support will handle the runtime toggling, but we do quite a bit
better with it on by default so just leave it on for now.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1750,7 +1750,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
 
 	dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
-			NETIF_F_HIGHDMA;
+			NETIF_F_HIGHDMA | NETIF_F_GSO;
 
 	mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
 	mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;

-- 

^ permalink raw reply

* [patch 6/6] pasemi_mac: basic ethtool support
From: Olof Johansson @ 2008-02-21  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, pasemi-linux, linuxppc-dev
In-Reply-To: <20080221025753.903665000@lixom.net>

First cut at ethtool support, to be completed over time.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: 2.6.25/drivers/net/Makefile
===================================================================
--- 2.6.25.orig/drivers/net/Makefile
+++ 2.6.25/drivers/net/Makefile
@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
+obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
+pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
 obj-$(CONFIG_MLX4_CORE) += mlx4/
 obj-$(CONFIG_ENC28J60) += enc28j60.o
 
Index: 2.6.25/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.c
+++ 2.6.25/drivers/net/pasemi_mac.c
@@ -55,12 +55,6 @@
  * - Multiqueue RX/TX
  */
 
-
-/* Must be a power of two */
-#define RX_RING_SIZE 2048
-#define TX_RING_SIZE 4096
-#define CS_RING_SIZE (TX_RING_SIZE*2)
-
 #define LRO_MAX_AGGR 64
 
 #define PE_MIN_MTU	64
@@ -77,17 +71,6 @@
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
-#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
-#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
-#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
-#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
-#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
-
-#define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
-				 & ((ring)->size - 1))
-#define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
 MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
@@ -96,6 +79,8 @@ static int debug = -1;	/* -1 == use DEFA
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
 
+extern const struct ethtool_ops pasemi_mac_ethtool_ops;
+
 static int translation_enabled(void)
 {
 #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
@@ -1148,7 +1133,7 @@ static int pasemi_mac_open(struct net_de
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int flags;
-	int ret;
+	int i, ret;
 
 	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
 		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
@@ -1171,6 +1156,10 @@ static int pasemi_mac_open(struct net_de
 			goto out_tx_ring;
 	}
 
+	/* Zero out rmon counters */
+	for (i = 0; i < 32; i++)
+		write_mac_reg(mac, PAS_MAC_RMON(i), 0);
+
 	/* 0x3ff with 33MHz clock is about 31us */
 	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
 		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
@@ -1812,6 +1801,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
 	dev->change_mtu = pasemi_mac_change_mtu;
+	dev->ethtool_ops = &pasemi_mac_ethtool_ops;
 
 	if (err)
 		goto out;
Index: 2.6.25/drivers/net/pasemi_mac.h
===================================================================
--- 2.6.25.orig/drivers/net/pasemi_mac.h
+++ 2.6.25/drivers/net/pasemi_mac.h
@@ -26,6 +26,12 @@
 #include <linux/spinlock.h>
 #include <linux/phy.h>
 
+/* Must be a power of two */
+#define RX_RING_SIZE 2048
+#define TX_RING_SIZE 4096
+#define CS_RING_SIZE (TX_RING_SIZE*2)
+
+
 #define MAX_LRO_DESCRIPTORS 8
 #define MAX_CS	2
 
@@ -103,6 +109,16 @@ struct pasemi_mac_buffer {
 	dma_addr_t	dma;
 };
 
+#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
+#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
+#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
+
+#define RING_USED(ring)	(((ring)->next_to_fill - (ring)->next_to_clean) \
+				& ((ring)->size - 1))
+#define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
 
 /* PCI register offsets and formats */
 
@@ -114,6 +130,7 @@ enum {
 	PAS_MAC_CFG_ADR0 = 0x8c,
 	PAS_MAC_CFG_ADR1 = 0x90,
 	PAS_MAC_CFG_TXP = 0x98,
+	PAS_MAC_CFG_RMON = 0x100,
 	PAS_MAC_IPC_CHNL = 0x208,
 };
 
@@ -185,6 +202,8 @@ enum {
 #define PAS_MAC_CFG_TXP_TIFG(x)		(((x) << PAS_MAC_CFG_TXP_TIFG_S) & \
 					 PAS_MAC_CFG_TXP_TIFG_M)
 
+#define PAS_MAC_RMON(r)			(0x100+(r)*4)
+
 #define PAS_MAC_IPC_CHNL_DCHNO_M	0x003f0000
 #define PAS_MAC_IPC_CHNL_DCHNO_S	16
 #define PAS_MAC_IPC_CHNL_DCHNO(x)	(((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \
@@ -194,4 +213,5 @@ enum {
 #define PAS_MAC_IPC_CHNL_BCH(x)		(((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
 					 PAS_MAC_IPC_CHNL_BCH_M)
 
+
 #endif /* PASEMI_MAC_H */
Index: 2.6.25/drivers/net/pasemi_mac_ethtool.c
===================================================================
--- /dev/null
+++ 2.6.25/drivers/net/pasemi_mac_ethtool.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2006-2008 PA Semi, Inc
+ *
+ * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/inet_lro.h>
+
+#include <asm/pasemi_dma.h>
+#include "pasemi_mac.h"
+
+static struct {
+	const char str[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+	{ "rx-drops" },
+	{ "rx-bytes" },
+	{ "rx-packets" },
+	{ "rx-broadcast-packets" },
+	{ "rx-multicast-packets" },
+	{ "rx-crc-errors" },
+	{ "rx-undersize-errors" },
+	{ "rx-oversize-errors" },
+	{ "rx-short-fragment-errors" },
+	{ "rx-jabber-errors" },
+	{ "rx-64-byte-packets" },
+	{ "rx-65-127-byte-packets" },
+	{ "rx-128-255-byte-packets" },
+	{ "rx-256-511-byte-packets" },
+	{ "rx-512-1023-byte-packets" },
+	{ "rx-1024-1518-byte-packets" },
+	{ "rx-pause-frames" },
+	{ "tx-bytes" },
+	{ "tx-packets" },
+	{ "tx-broadcast-packets" },
+	{ "tx-multicast-packets" },
+	{ "tx-collisions" },
+	{ "tx-late-collisions" },
+	{ "tx-excessive-collisions" },
+	{ "tx-crc-errors" },
+	{ "tx-undersize-errors" },
+	{ "tx-oversize-errors" },
+	{ "tx-64-byte-packets" },
+	{ "tx-65-127-byte-packets" },
+	{ "tx-128-255-byte-packets" },
+	{ "tx-256-511-byte-packets" },
+	{ "tx-512-1023-byte-packets" },
+	{ "tx-1024-1518-byte-packets" },
+};
+
+static int
+pasemi_mac_ethtool_get_settings(struct net_device *netdev,
+			       struct ethtool_cmd *cmd)
+{
+	struct pasemi_mac *mac = netdev_priv(netdev);
+	struct phy_device *phydev = mac->phydev;
+
+	return phy_ethtool_gset(phydev, cmd);
+}
+
+static void
+pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
+			       struct ethtool_drvinfo *drvinfo)
+{
+	struct pasemi_mac *mac;
+	mac = netdev_priv(netdev);
+
+	/* clear and fill out info */
+	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+	strncpy(drvinfo->driver, "pasemi_mac", 12);
+	strcpy(drvinfo->version, "N/A");
+	strcpy(drvinfo->fw_version, "N/A");
+	strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
+}
+
+static u32
+pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
+{
+	struct pasemi_mac *mac = netdev_priv(netdev);
+	return mac->msg_enable;
+}
+
+static void
+pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
+				u32 level)
+{
+	struct pasemi_mac *mac = netdev_priv(netdev);
+	mac->msg_enable = level;
+}
+
+
+static void
+pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
+				 struct ethtool_ringparam *ering)
+{
+	struct pasemi_mac *mac = netdev->priv;
+
+	ering->tx_max_pending = TX_RING_SIZE/2;
+	ering->tx_pending = RING_USED(mac->tx)/2;
+	ering->rx_max_pending = RX_RING_SIZE/4;
+	ering->rx_pending = RING_USED(mac->rx)/4;
+}
+
+static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(ethtool_stats_keys);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
+		struct ethtool_stats *stats, u64 *data)
+{
+	struct pasemi_mac *mac = netdev->priv;
+	int i;
+
+	data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
+			>> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
+	for (i = 0; i < 32; i++)
+		data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
+}
+
+static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
+				   u8 *data)
+{
+	memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
+}
+
+const struct ethtool_ops pasemi_mac_ethtool_ops = {
+	.get_settings		= pasemi_mac_ethtool_get_settings,
+	.get_drvinfo		= pasemi_mac_ethtool_get_drvinfo,
+	.get_msglevel		= pasemi_mac_ethtool_get_msglevel,
+	.set_msglevel		= pasemi_mac_ethtool_set_msglevel,
+	.get_link		= ethtool_op_get_link,
+	.get_ringparam          = pasemi_mac_ethtool_get_ringparam,
+	.get_strings		= pasemi_mac_get_strings,
+	.get_sset_count		= pasemi_mac_get_sset_count,
+	.get_ethtool_stats	= pasemi_mac_get_ethtool_stats,
+};
+

-- 

^ permalink raw reply

* Re: [patch v8 3/4] USB: add Cypress c67x00 OTG controller HCD driver
From: David Brownell @ 2008-02-21  3:06 UTC (permalink / raw)
  To: Peter Korsgaard; +Cc: dbrownell, greg, linux-usb, linuxppc-dev, stern
In-Reply-To: <20080220091401.612406000@sunsite.dk>

On Wednesday 20 February 2008, Peter Korsgaard wrote:
> +ifeq ($(CONFIG_USB_DEBUG),y)
> +       EXTRA_CFLAGS            += -DDEBUG
> +endif

The canonical Sam Ravnborg comment is to replace that with:

  +ccflags-$(CONFIG_USB_DEBUG)    += -DDEBUG

It's a newish idiom, most easily applied to new code before
it merges ...  :)


> +++ linux-2.6/drivers/usb/host/Kconfig
> @@ -261,3 +261,15 @@
>           To compile this driver as a module, choose M here: the
>           module will be called r8a66597-hcd.
>  
> +config USB_C67X00_HCD
> +       tristate "Cypress C67x00 HCD support"
> +       depends on USB

And I realize that some of the drivers there have violated the
normal "alphabetical order" convention, so maybe one big
cleanup patch would be in order ... but still, I'd rather see
such new options added in the right place, rather than need
to see them fixed up later.

- Dave

^ permalink raw reply

* Re: [PATCH v2][POWERPC] Fix initial lmb add region with a non-zero base
From: Josh Boyer @ 2008-02-21  4:01 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: sparclinux, linuxppc-dev, linux-kernel, David Miller
In-Reply-To: <18364.57054.427433.405627@cargo.ozlabs.ibm.com>

On Thu, 21 Feb 2008 13:15:58 +1100
Paul Mackerras <paulus@samba.org> wrote:

> Kumar Gala writes:
> 
> > np.  Are we trying to get this into 2.6.25 or .26?
> 
> I was going to put it into my powerpc-next branch and put it in
> 2.6.26.  I don't see any need for it to go in 2.6.25.

Is that a new branch you're going to create, or the normal "for-2.6.xx"?

josh

^ permalink raw reply

* Re: Question about PPC_NATIVE/hash_native_64.c
From: Paul Mackerras @ 2008-02-21  4:47 UTC (permalink / raw)
  To: Gerhard Pircher; +Cc: linuxppc-dev
In-Reply-To: <20080220115713.193460@gmx.net>

Gerhard Pircher writes:

> I'm a little bit confused about the hash_native_64.c file, which is compiled
> in the kernel, if PPC_NATIVE is defined. PPC_NATIVE seems to be defined also
> for 32bit platforms (CHRP, PREP, etc.), but the name of the hash_native_64.c
> file and the Makefile suggest that it is for 64bit platforms only.
> What is hash_native_64.c actually good for on 32bit platforms and which cpus
> can make use of it?

It's not included on 32-bit platforms.  Here are the relevant lines
from arch/powerpc/mm/Makefile:

hash-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
obj-$(CONFIG_PPC64)		+= hash_utils_64.o \
				   slb_low.o slb.o stab.o mmap.o $(hash-y)

Note that the first line sets hash-y not obj-y, and $(hash-y) is only
used on 64-bit machines.

Paul.

^ permalink raw reply

* Re: [Linux-fbdev-devel] [PATCH 1/2] fb: add support for foreign endianness
From: Paul Mackerras @ 2008-02-21  4:59 UTC (permalink / raw)
  To: avorontsov
  Cc: linux-fbdev-devel, adaplas, Krzysztof Helt, linux-kernel,
	linuxppc-dev, Geert Uytterhoeven, Andrew Morton
In-Reply-To: <20080220121818.GA20836@localhost.localdomain>

Anton Vorontsov writes:

> > I was wondering if it would be sufficient to provide alternative
> > versions of fb_readl, fb_writel etc. that do byte-swapping.
> 
> This is of course viable alternative. And I was considering this, but
> later I abandoned the idea: that way we'll end up doing math in the
> native endianness and then converting it to the foreign. This feels
> ugly in contrast when we can do the right math in the first place, per
> framebuffer.

OK.  I guess I'm convinced then.  However, your patch description
needs to be a lot better.  It should describe things like why you
want to make the change and why the change you are proposing is a good
idea and is better than other alternatives.  If you'd done that
originally we might not have needed to have all this discussion. :)

Paul.

^ permalink raw reply

* EBC access
From: Silwer star @ 2008-02-21  5:48 UTC (permalink / raw)
  To: linuxppc-embedded


Hi,

I am working on the PPC 405EX processor with a peripheral attached to the
EBC. I've requested for I/O memory & mapped it using ioremap. The following
are my doubts:

1) How do I ensure that the memory range that I requested is non-cacheable.
I've to work with non-cacheable memory.  I've requested for memory using
request_mem_region( ). 
2) Between any consecutive writes or any consecutive reads, if I introduce a
delay of 500msec, the read/write is completing.  Does this have to do
anything with caching? What could be the  reason for this?

Any help will be appreciated.

Regards,
Silwer Star
-- 
View this message in context: http://www.nabble.com/EBC-access-tp15605219p15605219.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH] mpic: make sparse happy
From: Milton Miller @ 2008-02-21  5:50 UTC (permalink / raw)
  To: Johannes Berg; +Cc: ppcdev
In-Reply-To: <1203507104.17534.32.camel@johannes.berg>

At Wed Feb 20 22:31:44 EST 2008, Johannes Berg wrote:
> I was running sparse on something else and noticed sparse warnings
> and especially the bogus code that is fixed by the first hunk of
> this patch, so I fixed them all while at it.

But your change is not equivalent!

> --- everything.orig/arch/powerpc/sysdev/mpic.c  2008-02-20 
> 12:25:41.000000000 +0100
> +++ everything/arch/powerpc/sysdev/mpic.c       2008-02-20 
> 12:28:37.000000000 +0100
> @@ -175,13 +175,13 @@ static inline void _mpic_write(enum mpic
>         switch(type) {
>  #ifdef CONFIG_PPC_DCR
>         case mpic_access_dcr:
> -               return dcr_write(rb->dhost, reg, value);
> +               dcr_write(rb->dhost, reg, value);
>  #endif
>         case mpic_access_mmio_be:
> -               return out_be32(rb->base + (reg >> 2), value);
> +               out_be32(rb->base + (reg >> 2), value);
>         case mpic_access_mmio_le:
>         default:
> -               return out_le32(rb->base + (reg >> 2), value);
> +               out_le32(rb->base + (reg >> 2), value);
>         }
>  }

You now write to the register with dcr, big, and little endian variants!

Either put a return or break after the calls to the void functions so 
you don't fall through.

...

> @@ -1107,10 +1108,10 @@ struct mpic * __init mpic_alloc(struct d
>          * in, try to obtain one
>          */
>         if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
> -               const u32 *reg;
> -               reg = of_get_property(node, "reg", NULL);
> -               BUG_ON(reg == NULL);
> -               paddr = of_translate_address(node, reg);
> +               const u32 *regprop;
> +               regprop = of_get_property(node, "reg", NULL);
> +               BUG_ON(regprop == NULL);
> +               paddr = of_translate_address(node, regprop);
>                 BUG_ON(paddr == OF_BAD_ADDR);
>         }

This is reg variable is shadowed ... ok, although i might have renamed 
the outer one features or greg_feature.  For that matter, I would have 
initialized this reg/regprop on definition.

^ permalink raw reply

* Re: [PATCH] powerpc: don't create two devices for each cpm_uart device tree node
From: Nikita V. Youshchenko @ 2008-02-21  6:13 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20080220164052.GB32165@ld0162-tx32.am.freescale.net>

> On Wed, Feb 20, 2008 at 02:32:33AM +0300, Nikita V. Youshchenko wrote:
> >     powerpc: don't create two devices for each cpm_uart device tree
> > node
> >
> >     Code in arch/powerpc/sysdev/fsl_soc.c used to create two 'struct
> > device' objects for each cpm_uart device tree node - one
> > "fsl-cpm-scc:uart" in cpm_uart_of_init() and one "fsl-cpm-smc:uart" in
> > cpm_smc_uart_of_init().
>
> This is old code that only exists for non-CONFIG_PPC_CPM_NEW_BINDING
> boards.  As there are none of these remaining in-tree, this code should
> go away soon.

Thank you for information.

I am working with vendor kernel, based on 2.6.18, and that does not have 
CONFIG_PPC_CPM_NEW_BINDING. I thought that fix I made for that kernel 
could be usable for mainline, but if not - nevermind.

^ permalink raw reply

* Re: Sample driver
From: Jeff Mock @ 2008-02-21  6:54 UTC (permalink / raw)
  To: fariyaf; +Cc: linuxppc-embedded
In-Reply-To: <8024567.229231203576334424.JavaMail.nabble@isper.nabble.com>



fariyaf@gmail.com wrote:
> Hi,
> 
> Thanks so much for the driver. I have a few doubts.. .may be u cud
> help me out with it.... Basically, I am working on the PPC 405EX
> processor with a peripheral attached to the EBC. I've requested for
> I/O memory & mapped it using ioremap. The following are my doubts:
> 
> 1) How do I ensure that the memory range that I requested is
> non-cacheable. I've to work with non-cacheable memory.  I've
> requested for memory using request_mem_region( ).

In my example the memory range is set to non-cacheable, this needs to be 
done if you are talking to real hardware registers:

   "vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);"

static int
pdev_mmap(struct file *file, struct vm_area_struct *vma)
{
     int fpga_num = iminor(file->f_dentry->d_inode) - PDEV_SPCTL;
     phys_addr_t     paddr;

     paddr = fpga_num ? PDEV_SP1_REG : PDEV_SP0_REG;
#ifdef PDEV_DEBUG
     printk("pdev-gxctl: fpga %d reg mmap() at %016llx\n", fpga_num, paddr);
#endif
     vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
     if (remap_pfn_range(vma,
             vma->vm_start,
             paddr >> PAGE_SHIFT,
             vma->vm_end-vma->vm_start,
             vma->vm_page_prot))
         return -EAGAIN;
     return 0;
}

> 2) Between any consecutive writes or any consecutive reads to the EBC
> peripheral, if I introduce a delay of 500msec, the read/write is
> completing.  Does this have to do anything with caching? What could
> be the  reason for this?


I have no idea where the 500ms delay comes from, this is quite a long 
delay.  Maybe there is some problem with the EBC programming for your 
example.  The EBC is quite flexible and can be programmed in any number 
of insane ways that might cause trouble.

jeff

^ permalink raw reply

* Xilinx  PowerPC
From: David H. Lynch Jr. @ 2008-02-21  6:58 UTC (permalink / raw)
  To: Grant Likely, linuxppc-embedded

    So when you have Xilinx under powerpc working, do we pull it from your
    git tree or the xilinx one ?

    Will there be an announcement ?

    How about a one paragraph getting started guide to moving a xilinx
ppc bsp to
    xilinx powerpc.

    Like  ?

    step 1).
             Generate a dts - gen-mhs-devicetree ?
             And pass it to through your boot loader to Linux ?
   
    Step 2).
             the code in arch/powerpc/???? is the devicetree equvalent to
             arch/ppc/platforms/4xx/xilinx_ml410.c

    Step 3).
             device drivers need to change initialization/setup from
             ???? to ???
      
    Just something to give those of us with no clue, a small one to start.

     Thanks.

^ permalink raw reply

* Block devices
From: David H. Lynch Jr. @ 2008-02-21  7:05 UTC (permalink / raw)
  To: linuxppc-embedded, linux-fsdevel, linux-mtd

    Sometime recently it seems to have become possible to disable the
whole block device subsystem.
    Though in my tests I can't quit build with it disabled.

     Anyway, for an embedded device this might be appealing.
    how does this interact with initramfs and flash ?
   
    Can I boot an initramfs kernel without a block device ?
    Can I write a filesystem driver for a flash device that does not
require a block device ?
    Are their any examples of something even close ?

   

      







-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.627.3770 	       dhlii@dlasys.net 	  http://www.dlasys.net
fax: 1.253.369.9244 			           Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein

^ permalink raw reply

* Re: [patch v8 3/4] USB: add Cypress c67x00 OTG controller HCD driver
From: Peter Korsgaard @ 2008-02-21  7:53 UTC (permalink / raw)
  To: David Brownell; +Cc: dbrownell, greg, linux-usb, linuxppc-dev, stern
In-Reply-To: <200802201906.35830.david-b@pacbell.net>

>>>>> "David" == David Brownell <david-b@pacbell.net> writes:

Hi,

 David>   +ccflags-$(CONFIG_USB_DEBUG)    += -DDEBUG

 David> It's a newish idiom, most easily applied to new code before
 David> it merges ...  :)

Ok. I'll fix that.

 David> And I realize that some of the drivers there have violated the
 David> normal "alphabetical order" convention, so maybe one big
 David> cleanup patch would be in order ... but still, I'd rather see
 David> such new options added in the right place, rather than need
 David> to see them fixed up later.

And this as well.

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* Re: MPC8641D PCI-Express error
From: Marco Stornelli @ 2008-02-21  8:02 UTC (permalink / raw)
  To: Kumar Gala; +Cc: LinuxPPC-Embedded
In-Reply-To: <BA5ADBDE-BDE5-4126-B012-DA6C5A8F8EF3@kernel.crashing.org>

Kumar Gala ha scritto:
> 
> On Feb 20, 2008, at 10:13 AM, Marco Stornelli wrote:
> 
>> Kumar Gala wrote:
>>>> Marco Stornelli wrote:
>>>>
>>>>> No, but I can try to backport the PCI-E code from 2.6.24 to 2.6.18
>>>>> if it could help. What do you think about it? Do you think this
>>>>> problem could be not present in 2.6.24?
>>>>> I have no idea there, honestly.  Sorry.
>>
>>> As Jon said, try 2.6.24 and see if it has an issue, if so we can look
>>> at helping.  if not, you know you need to back port the fixes.
>>
>>> - k
>>
>> I've "backported" the PCI-Express code from 2.6.24 to 2.6.18, but it
>> still doesn't work, I have the same problem (sigh), could you give me
>> any suggestions?
> 
> did 2.6.24 work for you or not?
> 
> - k
> 
No, it didn't. I have the same problem even with the 2.6.18 plus the
2.6.24 PCI-Express code. I performed this action because I can't change
kernel version but I can modify it.

Marco

^ permalink raw reply

* Re: [PATCH] mpic: make sparse happy
From: Johannes Berg @ 2008-02-21  9:23 UTC (permalink / raw)
  To: Milton Miller; +Cc: ppcdev
In-Reply-To: <91eb052edd9d5c608658fcdcfdc7589c@bga.com>

[-- Attachment #1: Type: text/plain, Size: 468 bytes --]


On Wed, 2008-02-20 at 23:50 -0600, Milton Miller wrote:
> At Wed Feb 20 22:31:44 EST 2008, Johannes Berg wrote:
> > I was running sparse on something else and noticed sparse warnings
> > and especially the bogus code that is fixed by the first hunk of
> > this patch, so I fixed them all while at it.
> 
> But your change is not equivalent!

> You now write to the register with dcr, big, and little endian variants!

Ouch, you're right, doh.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* [PATCH v2] mpic: make sparse happy
From: Johannes Berg @ 2008-02-21  9:39 UTC (permalink / raw)
  To: Milton Miller; +Cc: ppcdev
In-Reply-To: <91eb052edd9d5c608658fcdcfdc7589c@bga.com>

I was running sparse on something else and noticed sparse warnings
and especially the bogus code that is fixed by the first hunk of
this patch, so I fixed them all while at it.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Milton Miller <miltonm@bga.com>
---
 arch/powerpc/sysdev/mpic.c |   32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

--- everything.orig/arch/powerpc/sysdev/mpic.c	2008-02-20 23:22:52.000000000 +0100
+++ everything/arch/powerpc/sysdev/mpic.c	2008-02-21 10:25:53.000000000 +0100
@@ -175,13 +175,16 @@ static inline void _mpic_write(enum mpic
 	switch(type) {
 #ifdef CONFIG_PPC_DCR
 	case mpic_access_dcr:
-		return dcr_write(rb->dhost, reg, value);
+		dcr_write(rb->dhost, reg, value);
+		break;
 #endif
 	case mpic_access_mmio_be:
-		return out_be32(rb->base + (reg >> 2), value);
+		out_be32(rb->base + (reg >> 2), value);
+		break;
 	case mpic_access_mmio_le:
 	default:
-		return out_le32(rb->base + (reg >> 2), value);
+		out_le32(rb->base + (reg >> 2), value);
+		break;
 	}
 }
 
@@ -1000,7 +1003,7 @@ struct mpic * __init mpic_alloc(struct d
 				const char *name)
 {
 	struct mpic	*mpic;
-	u32		reg;
+	u32		greg_feature;
 	const char	*vers;
 	int		i;
 	int		intvec_top;
@@ -1064,7 +1067,8 @@ struct mpic * __init mpic_alloc(struct d
 
 	/* Look for protected sources */
 	if (node) {
-		unsigned int psize, bits, mapsize;
+		int psize;
+		unsigned int bits, mapsize;
 		const u32 *psrc =
 			of_get_property(node, "protected-sources", &psize);
 		if (psrc) {
@@ -1107,8 +1111,7 @@ struct mpic * __init mpic_alloc(struct d
 	 * in, try to obtain one
 	 */
 	if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
-		const u32 *reg;
-		reg = of_get_property(node, "reg", NULL);
+		const u32 *reg = of_get_property(node, "reg", NULL);
 		BUG_ON(reg == NULL);
 		paddr = of_translate_address(node, reg);
 		BUG_ON(paddr == OF_BAD_ADDR);
@@ -1137,12 +1140,13 @@ struct mpic * __init mpic_alloc(struct d
 	 * MPICs, num sources as well. On ISU MPICs, sources are counted
 	 * as ISUs are added
 	 */
-	reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+	greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
+	mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
 			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
 	if (isu_size == 0)
-		mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
-				     >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+		mpic->num_sources =
+			((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+			 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
 
 	/* Map the per-CPU registers */
 	for (i = 0; i < mpic->num_cpus; i++) {
@@ -1161,7 +1165,7 @@ struct mpic * __init mpic_alloc(struct d
 	mpic->isu_mask = (1 << mpic->isu_shift) - 1;
 
 	/* Display version */
-	switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+	switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
 	case 1:
 		vers = "1.0";
 		break;
@@ -1321,7 +1325,7 @@ void __init mpic_set_serial_int(struct m
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 {
-	int is_ipi;
+	unsigned int is_ipi;
 	struct mpic *mpic = mpic_find(irq, &is_ipi);
 	unsigned int src = mpic_irq_to_hw(irq);
 	unsigned long flags;
@@ -1344,7 +1348,7 @@ void mpic_irq_set_priority(unsigned int 
 
 unsigned int mpic_irq_get_priority(unsigned int irq)
 {
-	int is_ipi;
+	unsigned int is_ipi;
 	struct mpic *mpic = mpic_find(irq, &is_ipi);
 	unsigned int src = mpic_irq_to_hw(irq);
 	unsigned long flags;

^ permalink raw reply

* Re: initramfs problem - /init file
From: raul.moreno @ 2008-02-21 10:38 UTC (permalink / raw)
  To: dhlii; +Cc: linuxppc-embedded
In-Reply-To: <47BD1CFB.103@dlasys.lcl>







raul.moreno@telvent.abengoa.com wrote:
>> Hello everybody,
>>
>> I created a tiny root filesystem, just with Busybox, that I want to =
use
as
>> rootfs through initramfs (and keep it as the final root filesystem).=

>>
>>  Then I created an init file which is a link to
>> /sbin/init and I inserted the created cpio file with this filesystem=
 in
>> CONFIG_INITRAMFS_SOURCE.
>    The simplest way to get initramfs working is to stuff your
>root filesystem tree in a directory, and point
>    CONFIG_INITRAMFS_SOURCE at it.
>    The kernel build process will take care of all the cpio stuff
>for you.
>   Personally I think it is the easiest to maintain.


Hello Dave,

thanks for your answer. I agree with you, the easy way is to assign the=

rootfs directory. I gave the filesystem as a cpio file because it is th=
e
same (the kernel takes the rootfs and converts it to a cpio format), bu=
t
the compilation is faster. Anyway, although now I do as you said, I sti=
ll
get the error:
"Failed to execute /init
Kernel panic - not syncing: No init found.  Try passing init=3D option =
to
kernel."
I can't understand why it happens. I check the permission of /init and
/sbin/init and everything seems to me OK.

Any idea?

Ra=FAl Moreno

=

^ permalink raw reply

* Re: [PATCHv4 2.6.25] i2c: adds support for i2c bus on Freescale CPM1/CPM2 controllers
From: Jean Delvare @ 2008-02-21 12:05 UTC (permalink / raw)
  To: Jochen Friedrich; +Cc: linux-kernel, linuxppc-dev list, i2c, Scott Wood
In-Reply-To: <47A1C4E9.4000003@scram.de>

Hallo Jochen,

On Thu, 31 Jan 2008 13:54:01 +0100, Jochen Friedrich wrote:
> Using the port of 2.4 code from Vitaly Bordug <vitb@kernel.crashing.org>
> and the actual algorithm used by the i2c driver of the DBox code on
> cvs.tuxboc.org from Tmbinc, Gillem (htoa@gmx.net). Renamed i2c-rpx.c and
> i2c-algo-8xx.c to i2c-cpm.c and converted the driver to an
> of_platform_driver.
> 
> Signed-off-by: Jochen Friedrich <jochen@scram.de>
> ---
>  drivers/i2c/busses/Kconfig   |   10 +
>  drivers/i2c/busses/Makefile  |    1 +
>  drivers/i2c/busses/i2c-cpm.c |  759 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 770 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-cpm.c
> 
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index b61f56b..1d18db7 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -114,6 +114,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
>  	help
>  	  The unit of the TWI clock is kHz.
>  
> +config I2C_CPM
> +	tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
> +	depends on (CPM1 || CPM2) && I2C && PPC_OF

The dependency on I2C is now handled at menu level, you no longer need
to mention it here.

> +	help
> +	  This supports the use of the I2C interface on Freescale
> +	  processors with CPM1 or CPM2.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-cpm.
> +
>  config I2C_DAVINCI
>  	tristate "DaVinci I2C driver"
>  	depends on ARCH_DAVINCI
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index ea7068f..1291e2b 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
>  obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
>  obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
>  obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
> +obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
>  obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
>  obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
>  obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
> diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
> new file mode 100644
> index 0000000..7191427
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-cpm.c
> @@ -0,0 +1,759 @@
> +/*
> + * Freescale CPM1/CPM2 I2C interface.
> + * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
> + *
> + * moved into proper i2c interface;
> + * Brad Parker (brad@heeltoe.com)
> + *
> + * (C) 2007 Montavista Software, Inc.
> + * Vitaly Bordug <vitb@kernel.crashing.org>
> + *
> + * RPX lite specific parts of the i2c interface
> + * Update:  There actually isn't anything RPXLite-specific about this module.
> + * This should work for most any CPM board.  The console messages have been
> + * changed to eliminate RPXLite references.

Maybe this block comment can be removed entirely? It adds more
confusion than value IMHO.

> + *
> +    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., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * moved into proper i2c interface; separated out platform specific
> + * parts into i2c-8xx.c
> + * Brad Parker (brad@heeltoe.com)

Redundant with one of the block comments above.

> + *
> + * Parts from dbox2_i2c.c (cvs.tuxbox.org)
> + * (C) 2000-2001 Tmbinc, Gillem (htoa@gmx.net)
> + *
> + * (C) 2007 Montavista Software, Inc.
> + * Vitaly Bordug <vitb@kernel.crashing.org>

Redundant as well.

> + *
> + * Converted to of_platform_device. Renamed to i2c-cpm.c.
> + * (C) 2007 Jochen Friedrich <jochen@scram.de>
> + */

Please group all the copyright statements together, having some before
the GPL boilerplate and some after is rather confusing.

> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/errno.h>
> +#include <linux/sched.h>

It's not obvious to me why you need to include <linux/sched.h>, please
clarify.

> +#include <linux/stddef.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/time.h>

I don't think that you need <linux/time.h> either?

> +#include <linux/dma-mapping.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <sysdev/fsl_soc.h>
> +#include <asm/cpm.h>
> +
> +/*
> + * Wait for patch from Jon Smirl
> + * #include "powerpc-common.h"
> + */

It doesn't make sense to merge this comment upstream.

> +
> +/* Try to define this if you have an older CPU (earlier than rev D4) */
> +/* However, better use a GPIO based bitbang driver in this case :/   */
> +#undef	I2C_CHIP_ERRATA
> +
> +#define CPM_MAX_READ    513
> +#define CPM_MAXBD       4
> +
> +#define CPM_CR_INIT_TRX		(0x00)
> +#define CPM_CR_CLOSE_RXBD	(0x07)
> +
> +#define I2C_EB			(0x10) /* Big endian mode */
> +
> +/* I2C parameter RAM. */
> +struct i2c_ram {
> +	ushort  rbase;		/* Rx Buffer descriptor base address */
> +	ushort  tbase;		/* Tx Buffer descriptor base address */
> +	u_char  rfcr;		/* Rx function code */
> +	u_char  tfcr;		/* Tx function code */
> +	ushort  mrblr;		/* Max receive buffer length */
> +	uint    rstate;		/* Internal */
> +	uint    rdp;		/* Internal */
> +	ushort  rbptr;		/* Rx Buffer descriptor pointer */
> +	ushort  rbc;		/* Internal */
> +	uint    rxtmp;		/* Internal */
> +	uint    tstate;		/* Internal */
> +	uint    tdp;		/* Internal */
> +	ushort  tbptr;		/* Tx Buffer descriptor pointer */
> +	ushort  tbc;		/* Internal */
> +	uint    txtmp;		/* Internal */
> +	char    res1[4];	/* Reserved */
> +	ushort  rpbase;		/* Relocation pointer */
> +	char    res2[2];	/* Reserved */
> +};
> +
> +/* I2C Registers */
> +struct i2c_reg {
> +	u8	i2mod;
> +	u8	res1[3];
> +	u8	i2add;
> +	u8	res2[3];
> +	u8	i2brg;
> +	u8	res3[3];
> +	u8	i2com;
> +	u8	res4[3];
> +	u8	i2cer;
> +	u8	res5[3];
> +	u8	i2cmr;
> +};
> +
> +struct cpm_i2c {
> +	char *base;
> +	struct of_device *ofdev;
> +	struct i2c_adapter adap;
> +	uint dp_addr;
> +	int version; /* CPM1=1, CPM2=2 */
> +	int irq;
> +	int cp_command;
> +	struct i2c_reg __iomem *i2c_reg;
> +	struct i2c_ram __iomem *i2c_ram;
> +	u16 i2c_addr;
> +	wait_queue_head_t i2c_wait;
> +	struct mutex i2c_mutex; /* Protects I2C CPM */

"I2C CPM" isn't very descriptive. Best would be to list the structure
fields which are protected.

> +	u_char *txbuf[CPM_MAXBD];
> +	u_char *rxbuf[CPM_MAXBD];
> +	u32 txdma[CPM_MAXBD];
> +	u32 rxdma[CPM_MAXBD];
> +};
> +
> +static irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id)
> +{
> +	struct cpm_i2c *cpm;
> +	struct i2c_reg __iomem *i2c_reg;
> +	struct i2c_adapter *adap = dev_id;
> +	int i;
> +
> +	cpm = i2c_get_adapdata(dev_id);
> +	i2c_reg = cpm->i2c_reg;
> +
> +	/* Clear interrupt. */
> +	i = in_8(&i2c_reg->i2cer);
> +	out_8(&i2c_reg->i2cer, i);
> +
> +	dev_dbg(&adap->dev, "Interrupt: %x\n", i);
> +
> +	/* Get 'me going again. */

Extra '.

> +	wake_up_interruptible(&cpm->i2c_wait);
> +
> +	return i ? IRQ_HANDLED : IRQ_NONE;
> +}
> +
> +static void cpm_reset_i2c_params(struct cpm_i2c *cpm)
> +{
> +	struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
> +
> +	/* Set up the IIC parameters in the parameter ram. */
> +	out_be16(&i2c_ram->tbase, cpm->dp_addr);
> +	out_be16(&i2c_ram->rbase, cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD);
> +
> +	out_8(&i2c_ram->tfcr, I2C_EB);
> +	out_8(&i2c_ram->rfcr, I2C_EB);
> +
> +	out_be16(&i2c_ram->mrblr, CPM_MAX_READ);
> +
> +	out_be32(&i2c_ram->rstate, 0);
> +	out_be32(&i2c_ram->rdp, 0);
> +	out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
> +	out_be16(&i2c_ram->rbc, 0);
> +	out_be32(&i2c_ram->rxtmp, 0);
> +	out_be32(&i2c_ram->tstate, 0);
> +	out_be32(&i2c_ram->tdp, 0);
> +	out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
> +	out_be16(&i2c_ram->tbc, 0);
> +	out_be32(&i2c_ram->txtmp, 0);
> +}
> +
> +static void cpm_i2c_force_close(struct i2c_adapter *adap)
> +{
> +	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
> +	struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
> +
> +	dev_dbg(&adap->dev, "cpm_i2c_force_close()\n");
> +
> +	cpm_command(cpm->cp_command, CPM_CR_CLOSE_RXBD);
> +
> +	out_8(&i2c_reg->i2cmr, 0x00);	/* Disable all interrupts */
> +	out_8(&i2c_reg->i2cer, 0xff);
> +}
> +
> +static void cpm_i2c_parse_message(struct i2c_adapter *adap,
> +	struct i2c_msg *pmsg, int num, int tx, int rx)
> +{
> +	cbd_t *tbdf, *rbdf;
> +	u_char addr;
> +	u_char *tb;
> +	u_char *rb;
> +	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
> +	struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
> +	int i, dscan;
> +
> +	tbdf = (cbd_t *) cpm_muram_addr(in_be16(&i2c_ram->tbase));
> +	rbdf = (cbd_t *) cpm_muram_addr(in_be16(&i2c_ram->rbase));
> +
> +	/*
> +	 * This chip can't do zero length writes. However, the i2c core uses
> +	 * them to scan for devices. The best we can do is to convert them
> +	 * into 1 byte reads
> +	 */

Nack. New-style i2c drivers don't require this probing mechanism,
that's what you want to use if your I2C master doesn't support
zero-byte messages. Well, that's most probably what you want to use on
embedded platforms anyway.

So, please no hack for zero-byte messages. If they aren't supported by
the hardware, they aren't supported by the driver either.

> +
> +	dscan = ((pmsg->len == 0) && (num == 1));
> +
> +	addr = pmsg->addr << 1;
> +	if ((pmsg->flags & I2C_M_RD) || dscan)
> +		addr |= 1;
> +
> +	tb = cpm->txbuf[tx];
> +	rb = cpm->rxbuf[rx];
> +
> +	/* Align read buffer */
> +	rb = (u_char *) (((ulong) rb + 1) & ~1);
> +
> +	if ((pmsg->flags & I2C_M_RD) || dscan) {
> +		/*
> +		 * To read, we need an empty buffer of the proper length.
> +		 * All that is used is the first byte for address, the remainder
> +		 * is just used for timing (and doesn't really have to exist).
> +		 */
> +		tb[0] = addr;		/* Device address byte w/rw flag */
> +
> +		dev_dbg(&adap->dev, "cpm_i2c_read(abyte=0x%x)\n", addr);
> +
> +		if (dscan)
> +			tbdf[tx].cbd_datlen = 2;
> +		else
> +			tbdf[tx].cbd_datlen = pmsg->len + 1;
> +
> +		tbdf[tx].cbd_sc = 0;
> +
> +		if (!(pmsg->flags & I2C_M_NOSTART))
> +			tbdf[tx].cbd_sc |= BD_I2C_START;
> +		if (tx + 1 == num)
> +			tbdf[tx].cbd_sc |= BD_SC_LAST | BD_SC_WRAP;
> +
> +		rbdf[rx].cbd_datlen = 0;
> +		rbdf[rx].cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
> +
> +		if (rx + 1 == CPM_MAXBD)
> +			tbdf[rx].cbd_sc |= BD_SC_WRAP;
> +
> +		eieio();
> +		tbdf[tx].cbd_sc |= BD_SC_READY;
> +	} else {
> +		tb[0] = addr;		/* Device address byte w/rw flag */
> +		for (i = 0; i < pmsg->len; i++)
> +			tb[i+1] = pmsg->buf[i];
> +
> +		dev_dbg(&adap->dev, "cpm_iic_write(abyte=0x%x)\n", addr);
> +
> +		tbdf[tx].cbd_datlen = pmsg->len + 1;
> +		tbdf[tx].cbd_sc = 0;
> +
> +		if (!(pmsg->flags & I2C_M_NOSTART))
> +			tbdf[tx].cbd_sc |= BD_I2C_START;
> +
> +		if (tx + 1 == num)
> +			tbdf[tx].cbd_sc |= BD_SC_LAST | BD_SC_WRAP;
> +
> +		eieio();
> +		tbdf[tx].cbd_sc |= BD_SC_READY | BD_SC_INTRPT;
> +
> +		dev_dbg(&adap->dev, "tx sc %d %04x\n",
> +			tx, tbdf[tx].cbd_sc);
> +	}
> +}
> +
> +static int cpm_i2c_check_message(struct i2c_adapter *adap,
> +	struct i2c_msg *pmsg, int tx, int rx)
> +{
> +	cbd_t *tbdf, *rbdf;
> +	u_char *tb;
> +	u_char *rb;
> +	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
> +	struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
> +	int i;
> +
> +	tbdf = (cbd_t *) cpm_muram_addr(in_be16(&i2c_ram->tbase));
> +	rbdf = (cbd_t *) cpm_muram_addr(in_be16(&i2c_ram->rbase));
> +
> +	tb = cpm->txbuf[tx];
> +	rb = cpm->rxbuf[rx];
> +
> +	/* Align read buffer */
> +	rb = (u_char *) (((uint) rb + 1) & ~1);
> +
> +	if (pmsg->flags & I2C_M_RD) {
> +		dev_dbg(&adap->dev, "rx sc %04x, rx sc %04x\n",
> +			tbdf[tx].cbd_sc, rbdf[rx].cbd_sc);
> +
> +		if (tbdf[tx].cbd_sc & BD_SC_NAK) {
> +			dev_dbg(&adap->dev, "IIC read; No ack\n");
> +
> +			if (pmsg->flags & I2C_M_IGNORE_NAK)
> +				return 0;

Are there known I2C chips on this platform which need this flag? Its
implementation is purely optional, only a few broken I2C chips need it,
so it should really only be implemented when strictly needed.

> +			else
> +				return -EIO;
> +		}
> +		if (rbdf[rx].cbd_sc & BD_SC_EMPTY) {
> +			dev_dbg(&adap->dev,
> +				"IIC read; complete but rbuf empty\n");
> +			return -EREMOTEIO;
> +		}
> +		if (rbdf[rx].cbd_sc & BD_SC_OV) {
> +			dev_dbg(&adap->dev, "IIC read; Overrun\n");
> +			return -EREMOTEIO;
> +		}
> +		for (i = 0; i < pmsg->len; i++)
> +			pmsg->buf[i] = rb[i];
> +	} else {
> +		dev_dbg(&adap->dev, "tx sc %d %04x\n", tx, tbdf[tx].cbd_sc);
> +
> +		if (tbdf[tx].cbd_sc & BD_SC_NAK) {
> +			dev_dbg(&adap->dev, "IIC write; No ack\n");
> +
> +			if (pmsg->flags & I2C_M_IGNORE_NAK)
> +				return 0;
> +			else
> +				return -EIO;
> +		}
> +		if (tbdf[tx].cbd_sc & BD_SC_UN) {
> +			dev_dbg(&adap->dev, "IIC write; Underrun\n");
> +			return -EIO;
> +		}
> +		if (tbdf[tx].cbd_sc & BD_SC_CL) {
> +			dev_dbg(&adap->dev, "IIC write; Collision\n");
> +			return -EIO;
> +		}
> +	}
> +	return 0;
> +}

Many of the dev_dbg() calls in the function above could be replaced
with dev_err(), methinks.

> +
> +static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
> +{
> +	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
> +	struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
> +	struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
> +	struct i2c_msg *pmsg, *rmsg;
> +	int ret, i;
> +	int tptr;
> +	int rptr;
> +	cbd_t *tbdf, *rbdf;
> +
> +	if (num > CPM_MAXBD)
> +		return -EINVAL;
> +
> +	/* Check if we have any oversized READ requests */
> +	for (i = 0; i < num; i++) {
> +		pmsg = &msgs[i];
> +		if (pmsg->len >= CPM_MAX_READ)
> +			return -EINVAL;
> +	}
> +
> +	mutex_lock(&cpm->i2c_mutex);
> +
> +	/* Reset to use first buffer */
> +	out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
> +	out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
> +
> +	tbdf = (cbd_t *) cpm_muram_addr(in_be16(&i2c_ram->tbase));
> +	rbdf = (cbd_t *) cpm_muram_addr(in_be16(&i2c_ram->rbase));
> +
> +	tptr = 0;
> +	rptr = 0;
> +
> +	while (tptr < num) {
> +		pmsg = &msgs[tptr];
> +		dev_dbg(&adap->dev, "i2c-algo-cpm.o: " "R: %d T: %d\n",

Incorrect (and unneeded) file name reference.

> +			rptr, tptr);
> +
> +		cpm_i2c_parse_message(adap, pmsg, num, tptr, rptr);
> +		if (pmsg->flags & I2C_M_RD)
> +			rptr++;
> +		tptr++;
> +	}
> +	/* Start transfer now */
> +	/* Chip bug, set enable here */
> +	out_8(&i2c_reg->i2cmr, 0x13);	/* Enable RX/TX/Error interupts */
> +	out_8(&i2c_reg->i2cer, 0xff);	/* Clear interrupt status */
> +	out_8(&i2c_reg->i2mod, in_8(&i2c_reg->i2mod) | 1);	/* Enable */
> +	/* Begin transmission */
> +	out_8(&i2c_reg->i2com, in_8(&i2c_reg->i2com) | 0x80);
> +
> +	tptr = 0;
> +	rptr = 0;
> +
> +	while (tptr < num) {
> +		/* Check for outstanding messages */
> +		dev_dbg(&adap->dev, "test ready.\n");
> +		if (!(tbdf[tptr].cbd_sc & BD_SC_READY)) {
> +			dev_dbg(&adap->dev, "ready.\n");
> +			rmsg = &msgs[tptr];
> +			ret = cpm_i2c_check_message(adap, rmsg, tptr, rptr);
> +			tptr++;
> +			if (rmsg->flags & I2C_M_RD)
> +				rptr++;
> +			if (ret)
> +				goto out_err;
> +		} else {
> +			dev_dbg(&adap->dev, "not ready.\n");
> +			ret = wait_event_interruptible_timeout(cpm->i2c_wait,
> +				!(tbdf[tptr].cbd_sc & BD_SC_READY), 1 * HZ);
> +			if (ret == 0) {
> +				ret = -EREMOTEIO;
> +				dev_dbg(&adap->dev, "I2C read: timeout!\n");
> +				goto out_err;
> +			}
> +		}
> +	}
> +#ifdef I2C_CHIP_ERRATA
> +	/*
> +	 * Chip errata, clear enable. This is not needed on rev D4 CPUs.
> +	 * Disabling I2C too early may cause too short stop condition
> +	 */
> +	udelay(4);
> +	out_8(&i2c_reg->i2mod, in_8(&i2c_reg->i2mod) | ~1);
> +#endif
> +	mutex_unlock(&cpm->i2c_mutex);
> +	return (num);
> +
> +out_err:
> +	cpm_i2c_force_close(adap);
> +#ifdef I2C_CHIP_ERRATA
> +	/*
> +	 * Chip errata, clear enable. This is not needed on rev D4 CPUs.
> +	 */
> +	out_8(&i2c_reg->i2mod, in_8(&i2c_reg->i2mod) | ~1);
> +#endif
> +	mutex_unlock(&cpm->i2c_mutex);
> +	return ret;
> +}
> +
> +static u32 cpm_i2c_func(struct i2c_adapter *adap)
> +{
> +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;

Actually I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK)
according to my comment above.

> +}
> +
> +/* -----exported algorithm data: -------------------------------------	*/
> +
> +static const struct i2c_algorithm cpm_i2c_algo = {
> +	.master_xfer = cpm_i2c_xfer,
> +	.functionality = cpm_i2c_func,
> +};
> +
> +static const struct i2c_adapter cpm_ops = {
> +	.owner		= THIS_MODULE,
> +	.name		= "i2c-cpm",
> +	.id		= I2C_HW_MPC8XX_EPON,

Not defined anywhere, so this won't build. This ID is optional, so if
you don't need it, just don't set it. With the advent of new-style i2c
device drivers, the use of these IDs will hopefully phase out.

> +	.algo		= &cpm_i2c_algo,
> +	.class		= I2C_CLASS_HWMON,
> +};
> +
> +static int cpm_i2c_setup(struct cpm_i2c *cpm)

Could be __devinit.

> +{
> +	struct of_device *ofdev = cpm->ofdev;
> +	const u32 *data;
> +	int len, ret, i;
> +	void __iomem *i2c_base;
> +	cbd_t *tbdf, *rbdf;
> +	unsigned char brg;
> +
> +	pr_debug("i2c-cpm: cpm_i2c_setup()\n");

dev_dbg()

> +
> +	init_waitqueue_head(&cpm->i2c_wait);
> +	mutex_init(&cpm->i2c_mutex);
> +
> +	cpm->irq = of_irq_to_resource(ofdev->node, 0, NULL);
> +	if (cpm->irq == NO_IRQ)
> +		return -EINVAL;
> +
> +	/* Install interrupt handler. */
> +	ret = request_irq(cpm->irq, cpm_i2c_interrupt, 0, "cpm_i2c",
> +			  &cpm->adap);
> +	if (ret)
> +		goto out_irq;
> +
> +	/* IIC parameter RAM */
> +	i2c_base = of_iomap(ofdev->node, 1);
> +	if (i2c_base == NULL) {
> +		ret = -EINVAL;
> +		goto out_irq;
> +	}
> +
> +	if (of_device_is_compatible(ofdev->node, "fsl,cpm1-i2c")) {
> +
> +		/* Check for and use a microcode relocation patch. */
> +		cpm->i2c_ram = i2c_base;
> +		cpm->i2c_addr = in_be16(&cpm->i2c_ram->rpbase);
> +
> +		/*
> +		 * Maybe should use cpm_muram_alloc instead of hardcoding
> +		 * this in micropatch.c
> +		 */
> +		if (cpm->i2c_addr) {
> +			cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
> +			iounmap(i2c_base);
> +		}
> +
> +		cpm->version = 1;
> +
> +	} else if (of_device_is_compatible(ofdev->node, "fsl,cpm2-i2c")) {
> +		cpm->i2c_addr = cpm_muram_alloc(sizeof(struct i2c_ram), 64);
> +		cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
> +		out_be16(i2c_base, cpm->i2c_addr);
> +		iounmap(i2c_base);
> +
> +		cpm->version = 2;
> +
> +	} else {
> +		iounmap(i2c_base);
> +		ret = -EINVAL;
> +		goto out_irq;
> +	}
> +
> +	/* I2C control/status registers */
> +	cpm->i2c_reg = of_iomap(ofdev->node, 0);
> +	if (cpm->i2c_reg == NULL) {
> +		ret = -EINVAL;
> +		goto out_ram;
> +	}
> +
> +	data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
> +	if (!data || len != 4) {
> +		ret = -EINVAL;
> +		goto out_reg;
> +	}
> +	cpm->cp_command = *data;
> +
> +	data = of_get_property(ofdev->node, "linux,i2c-class", &len);
> +	if (data && len == 4)
> +		cpm->adap.class = *data;
> +
> +	/*
> +	 * Allocate space for CPM_MAXBD transmit and receive buffer
> +	 * descriptors in the DP ram.
> +	 */
> +	cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8);
> +	if (!cpm->dp_addr) {
> +		ret = -ENOMEM;
> +		goto out_reg;
> +	}
> +
> +	/* Initialize Tx/Rx parameters. */
> +
> +	cpm_reset_i2c_params(cpm);
> +
> +	pr_debug("i2c-cpm: i2c_ram %x, dp_addr 0x%x\n", (uint) cpm->i2c_ram,
> +		cpm->dp_addr);
> +	pr_debug("i2c-cpm: tbase %d, rbase %d\n",
> +		in_be16(&cpm->i2c_ram->tbase), in_be16(&cpm->i2c_ram->rbase));

dev_dbg()

> +
> +	tbdf = (cbd_t *) cpm_muram_addr(in_be16(&cpm->i2c_ram->tbase));
> +	rbdf = (cbd_t *) cpm_muram_addr(in_be16(&cpm->i2c_ram->rbase));
> +
> +	/* Allocate TX and RX buffers */
> +
> +	for (i = 0; i < CPM_MAXBD; i++) {
> +		cpm->rxbuf[i] = dma_alloc_coherent(
> +			NULL, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL);
> +		if (!cpm->rxbuf[i]) {
> +			ret = -ENOMEM;
> +			goto out_muram;
> +		}
> +		rbdf[i].cbd_bufaddr = ((cpm->rxdma[i] + 1) & ~1);
> +		cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(
> +			NULL, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL);
> +		if (!cpm->txbuf[i]) {
> +			ret = -ENOMEM;
> +			goto out_muram;
> +		}
> +		tbdf[i].cbd_bufaddr = cpm->txdma[i];
> +	}
> +
> +	cpm_command(cpm->cp_command, CPM_CR_INIT_TRX);
> +
> +	/*
> +	 * Select an invalid address. Just make sure we don't use loopback mode
> +	 */
> +	out_8(&cpm->i2c_reg->i2add, 0xfe);
> +
> +	/* Make clock run at 60 kHz. */
> +
> +	brg = get_brgfreq() / (32 * 2 * 60000) - 3;
> +	out_8(&cpm->i2c_reg->i2brg, brg);
> +
> +	out_8(&cpm->i2c_reg->i2mod, 0x00);
> +	out_8(&cpm->i2c_reg->i2com, 0x01);	/* Master mode */
> +
> +	/* Disable interrupts. */
> +	out_8(&cpm->i2c_reg->i2cmr, 0);
> +	out_8(&cpm->i2c_reg->i2cer, 0xff);
> +
> +	return 0;
> +
> +out_muram:
> +	for (i = 0; i < CPM_MAXBD; i++) {
> +		if (cpm->rxbuf[i])
> +			dma_free_coherent(NULL, CPM_MAX_READ + 1,
> +				cpm->rxbuf[i], cpm->rxdma[i]);
> +		if (cpm->txbuf[i])
> +			dma_free_coherent(NULL, CPM_MAX_READ + 1,
> +				cpm->txbuf[i], cpm->txdma[i]);
> +	}
> +	cpm_muram_free(cpm->dp_addr);
> +out_reg:
> +	iounmap(cpm->i2c_reg);
> +out_ram:
> +	if ((cpm->version == 1) && (!cpm->i2c_addr))
> +		iounmap(cpm->i2c_ram);
> +	if (cpm->version == 2)
> +		cpm_muram_free(cpm->i2c_addr);
> +out_irq:
> +	free_irq(cpm->irq, &cpm->adap);
> +	return ret;
> +}
> +
> +static void cpm_i2c_shutdown(struct cpm_i2c *cpm)
> +{
> +	int i;
> +
> +	/* Shut down I2C. */
> +	out_8(&cpm->i2c_reg->i2mod, in_8(&cpm->i2c_reg->i2mod) | ~1);
> +
> +	/* Disable interrupts */
> +	out_8(&cpm->i2c_reg->i2cmr, 0);
> +	out_8(&cpm->i2c_reg->i2cer, 0xff);
> +
> +	free_irq(cpm->irq, &cpm->adap);
> +
> +	/* Free all memory */
> +	for (i = 0; i < CPM_MAXBD; i++) {
> +		dma_free_coherent(NULL, CPM_MAX_READ + 1,
> +			cpm->rxbuf[i], cpm->rxdma[i]);
> +		dma_free_coherent(NULL, CPM_MAX_READ + 1,
> +			cpm->txbuf[i], cpm->txdma[i]);
> +	}
> +
> +	cpm_muram_free(cpm->dp_addr);
> +	iounmap(cpm->i2c_reg);
> +
> +	if ((cpm->version == 1) && (!cpm->i2c_addr))
> +		iounmap(cpm->i2c_ram);
> +	if (cpm->version == 2)
> +		cpm_muram_free(cpm->i2c_addr);
> +
> +	return;
> +}
> +
> +static int __devinit cpm_i2c_probe(struct of_device *ofdev,
> +			 const struct of_device_id *match)
> +{
> +	int result;
> +	struct cpm_i2c *cpm;
> +
> +	cpm = kzalloc(sizeof(struct cpm_i2c), GFP_KERNEL);
> +	if (!cpm)
> +		return -ENOMEM;
> +
> +	cpm->ofdev = ofdev;
> +
> +	dev_set_drvdata(&ofdev->dev, cpm);
> +
> +	cpm->adap = cpm_ops;
> +	i2c_set_adapdata(&cpm->adap, cpm);
> +	cpm->adap.dev.parent = &ofdev->dev;
> +
> +	result = cpm_i2c_setup(cpm);
> +	if (result) {
> +		printk(KERN_ERR "i2c-cpm: Unable to init hardware\n");

dev_err()

> +		goto out;
> +	}
> +
> +	/* register new adapter to i2c module... */
> +
> +	result = i2c_add_adapter(&cpm->adap);
> +	if (result < 0) {
> +		printk(KERN_ERR "i2c-cpm: Unable to register with I2C\n");

dev_err()

> +		goto out2;
> +	}
> +
> +	pr_debug("i2c-cpm: hw routines for %s registered.\n", cpm->adap.name);

dev_dbg()

> +
> +	/*
> +	 * Wait for patch from Jon Smirl
> +	 * of_register_i2c_devices(&cpm->adap, ofdev->node);
> +	 */

Again I won't merge this comment upstream.

> +
> +	return 0;
> +out2:
> +	cpm_i2c_shutdown(cpm);
> +out:

Better give more explicit names to your labels (for example
err_shutdown and err_free).

> +	dev_set_drvdata(&ofdev->dev, NULL);
> +	kfree(cpm);
> +
> +	return result;
> +}
> +
> +static int __devexit cpm_i2c_remove(struct of_device *ofdev)
> +{
> +	struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev);
> +
> +	i2c_del_adapter(&cpm->adap);
> +
> +	cpm_i2c_shutdown(cpm);
> +
> +	dev_set_drvdata(&ofdev->dev, NULL);
> +	kfree(cpm);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id cpm_i2c_match[] = {
> +	{
> +		.compatible = "fsl,cpm-i2c",
> +	},
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, cpm_i2c_match);
> +
> +static struct of_platform_driver cpm_i2c_driver = {
> +	.match_table	= cpm_i2c_match,
> +	.probe		= cpm_i2c_probe,
> +	.remove		= __devexit_p(cpm_i2c_remove),
> +	.driver		= {
> +		.name	= "fsl-i2c-cpm",
> +		.owner	= THIS_MODULE,
> +	}
> +};
> +
> +static int __init cpm_i2c_init(void)
> +{
> +	return of_register_platform_driver(&cpm_i2c_driver);
> +}
> +
> +static void __exit cpm_i2c_exit(void)
> +{
> +	of_unregister_platform_driver(&cpm_i2c_driver);
> +}
> +
> +module_init(cpm_i2c_init);
> +module_exit(cpm_i2c_exit);
> +
> +MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");

Why not your own name?

> +MODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards");
> +MODULE_LICENSE("GPL");


-- 
Jean Delvare

^ permalink raw reply

* Re: Please pull powerpc.git merge branch
From: Paul Mackerras @ 2008-02-21 12:15 UTC (permalink / raw)
  To: torvalds; +Cc: linuxppc-dev, akpm, linux-kernel
In-Reply-To: <18363.41603.210217.163071@cargo.ozlabs.ibm.com>

Linus,

Since I send the last pull request I have added four more commits to
the powerpc.git merge branch, two from Olof Johansson fixing a bug and
a warning for the pasemi platform, and two spufs bugfixes from Jeremy
Kerr.

Please do:

git pull \
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge

The diffstat and log below reflect all the outstanding commits, not
just the new four.

Thanks,
Paul.

 arch/powerpc/boot/Makefile                 |    8 
 arch/powerpc/boot/dts/bamboo.dts           |    3 
 arch/powerpc/boot/dts/ebony.dts            |    2 
 arch/powerpc/boot/dts/katmai.dts           |    2 
 arch/powerpc/boot/dts/kilauea.dts          |    3 
 arch/powerpc/boot/dts/makalu.dts           |    3 
 arch/powerpc/boot/dts/rainier.dts          |    4 
 arch/powerpc/boot/dts/sequoia.dts          |    4 
 arch/powerpc/boot/dts/taishan.dts          |    4 
 arch/powerpc/configs/bamboo_defconfig      |   81 ++-
 arch/powerpc/configs/ebony_defconfig       |   79 ++
 arch/powerpc/configs/ep405_defconfig       |   92 ++-
 arch/powerpc/configs/kilauea_defconfig     |   69 +-
 arch/powerpc/configs/makalu_defconfig      |   69 +-
 arch/powerpc/configs/ppc44x_defconfig      |  904 ++++++++++++++++++++++++++++
 arch/powerpc/configs/rainier_defconfig     |   82 ++-
 arch/powerpc/configs/sequoia_defconfig     |   77 ++
 arch/powerpc/configs/taishan_defconfig     |   81 ++-
 arch/powerpc/configs/walnut_defconfig      |   81 ++-
 arch/powerpc/configs/warp_defconfig        |  139 +++-
 arch/powerpc/kernel/kprobes.c              |    9 
 arch/powerpc/kernel/prom.c                 |   13 
 arch/powerpc/platforms/44x/Kconfig         |   10 
 arch/powerpc/platforms/cell/spu_base.c     |   12 
 arch/powerpc/platforms/cell/spufs/run.c    |    1 
 arch/powerpc/platforms/cell/spufs/sched.c  |    8 
 arch/powerpc/platforms/cell/spufs/switch.c |    6 
 arch/powerpc/platforms/pasemi/Makefile     |    2 
 arch/powerpc/platforms/pasemi/misc.c       |   97 +++
 arch/powerpc/platforms/pseries/power.c     |    2 
 arch/powerpc/sysdev/mpic_pasemi_msi.c      |    5 
 arch/ppc/platforms/4xx/ibm440ep.c          |    6 
 drivers/net/ibm_newemac/rgmii.c            |    1 
 include/asm-powerpc/spu.h                  |    3 
 34 files changed, 1605 insertions(+), 357 deletions(-)
 create mode 100644 arch/powerpc/configs/ppc44x_defconfig
 create mode 100644 arch/powerpc/platforms/pasemi/misc.c

Ananth N Mavinakayanahalli (1):
      [POWERPC] Kill sparse warnings in kprobes

Andre Detsch (1):
      [POWERPC] cell: fix spurious false return from spu_trap_data_{map,seg}

Becky Bruce (1):
      [POWERPC] Fix dt_mem_next_cell() to read the full address

Jeremy Kerr (1):
      [POWERPC] spufs: fix scheduler starvation by idle contexts

Josh Boyer (4):
      [POWERPC] 4xx: Update defconfigs for 2.6.25
      [POWERPC] 44x: Fix Kconfig formatting
      [POWERPC] 44x: Add multiplatform defconfig
      [POWERPC] Fix bootwrapper builds with older gcc versions

Olof Johansson (2):
      [POWERPC] pasemi: Register i2c devices at boot
      [POWERPC] pasemi: Remove warning in mpic_pasemi_msi.c

Stefan Roese (2):
      [POWERPC] net: NEWEMAC: Remove "rgmii-interface" from rgmii matching table
      [POWERPC] 4xx: Remove "i2c" and "xxmii-interface" device_types from dts

Stephen Rothwell (1):
      [POWERPC] Fix warning in pseries/power.c

Wolfgang Ocker (1):
      [POWERPC] PPC440EP Interrupt Triggering and Level Settings

^ permalink raw reply

* Re: [PATCH 1/1] [PPC] 8xx swap bug-fix
From: Wolfgang Denk @ 2008-02-21 12:21 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: dzu, linuxppc-dev, Mackerras, Paul, Scott Wood
In-Reply-To: <20080205013857.47ebe544@kernel.crashing.org>

Dear Vitaly,

in message <20080205013857.47ebe544@kernel.crashing.org> you wrote:
> On Mon, 4 Feb 2008 12:24:21 -0600
> Scott Wood wrote:
> 
> > On Sat, Feb 02, 2008 at 12:22:17PM +0100, Jochen Friedrich wrote:
> > > Hi Yuri,
> > > 
> > > >  Here is the patch which makes Linux-2.6 swap routines operate
> > > > correctly on the ppc-8xx-based machines.
> > > 
> > > is there any 8xx board left which isn't ported to ARCH=powerpc?
> > 
> > More importantly, is this something that is also broken in
> > arch/powerpc?  It looks like it has the same code...
> > 
> yes, it is. Though there is currently no best-at-all solution, this looks worth trying.
> I'll have a look how the 8xx feels under load and report back.

Have you been able to check if arch/powerpc needs similar fixing?


Also, what is the current state of this patch? I would like to avoid
that it get's lost completeley.


BenH commented on Tue, 05 Feb 2008 18:37:07 +1100:

> Best is to just remove writeback completely and let the generic
> code handle it.

Has this been considered / tested by anybody?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Man did not weave the web of life; he  is  merely  a  strand  in  it.
Whatever he does to the web, he does to himself.     - Seattle [1854]

^ permalink raw reply

* [PATCH 1/5] [POWERPC] Add AMCC 460EX/460GT support to cputable.c & cpu_setup_44x.S
From: Stefan Roese @ 2008-02-21 14:00 UTC (permalink / raw)
  To: linuxppc-dev

Signed-off-by: Stefan Roese <sr@denx.de>
---
 arch/powerpc/kernel/cpu_setup_44x.S |    5 ++++-
 arch/powerpc/kernel/cputable.c      |   28 +++++++++++++++++++++++++++-
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
index 6250443..5465e8d 100644
--- a/arch/powerpc/kernel/cpu_setup_44x.S
+++ b/arch/powerpc/kernel/cpu_setup_44x.S
@@ -3,7 +3,7 @@
  * Valentine Barshak <vbarshak@ru.mvista.com>
  * MontaVista Software, Inc (c) 2007
  *
- * Based on cpu_setup_6xx code by 
+ * Based on cpu_setup_6xx code by
  * Benjamin Herrenschmidt <benh@kernel.crashing.org>
  *
  * This program is free software; you can redistribute it and/or
@@ -32,6 +32,9 @@ _GLOBAL(__setup_cpu_440grx)
 	bl	__fixup_440A_mcheck
 	mtlr	r4
 	blr
+_GLOBAL(__setup_cpu_460ex)
+_GLOBAL(__setup_cpu_460gt)
+	b	__init_fpu_44x
 _GLOBAL(__setup_cpu_440gx)
 _GLOBAL(__setup_cpu_440spe)
 	b	__fixup_440A_mcheck
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 2a8f5cc..26ffb44 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -36,6 +36,8 @@ extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -1397,6 +1399,30 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.machine_check		= machine_check_440A,
 		.platform		= "ppc440",
 	},
+	{ /* 460EX */
+		.pvr_mask		= 0xffff0002,
+		.pvr_value		= 0x13020002,
+		.cpu_name		= "460EX",
+		.cpu_features		= CPU_FTRS_44X,
+		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_460ex,
+		.machine_check		= machine_check_440A,
+		.platform		= "ppc440",
+	},
+	{ /* 460GT */
+		.pvr_mask		= 0xffff0002,
+		.pvr_value		= 0x13020000,
+		.cpu_name		= "460GT",
+		.cpu_features		= CPU_FTRS_44X,
+		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_460gt,
+		.machine_check		= machine_check_440A,
+		.platform		= "ppc440",
+	},
 #endif /* CONFIG_44x */
 #ifdef CONFIG_FSL_BOOKE
 #ifdef CONFIG_E200
@@ -1512,7 +1538,7 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
 				*t = *s;
 			*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
 #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
-			/* ppc64 and booke expect identify_cpu to also call 
+			/* ppc64 and booke expect identify_cpu to also call
 			 * setup_cpu for that processor. I will consolidate
 			 * that at a later time, for now, just use #ifdef.
 			 * we also don't need to PTRRELOC the function pointer
-- 
1.5.4.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox