Signed-off-by: Paul Butler <paul.but...@windriver.com>
---
 drivers/net/ethernet/lsi/lsi_acp_mdio.c | 243 ++++++++++++++++++++++++++++++++
 1 file changed, 243 insertions(+)
 create mode 100644 drivers/net/ethernet/lsi/lsi_acp_mdio.c

diff --git a/drivers/net/ethernet/lsi/lsi_acp_mdio.c 
b/drivers/net/ethernet/lsi/lsi_acp_mdio.c
new file mode 100644
index 0000000..dc4e353
--- /dev/null
+++ b/drivers/net/ethernet/lsi/lsi_acp_mdio.c
@@ -0,0 +1,243 @@
+/*
+ * drivers/net/ethernet/lsi/lsi_acp_mdio.c
+ *
+ * Copyright (C) 2010 LSI
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307        
 USA
+ */
+
+#if defined(CONFIG_ARCH_AXXIA) && defined(CONFIG_ARM)
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <asm/irq.h>
+#include <asm/lsi/acp_ncr.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/irqdomain.h>
+
+/*
+  
==============================================================================
+  
==============================================================================
+  MDIO Access
+  
==============================================================================
+  
==============================================================================
+*/
+
+#ifndef CONFIG_ACPISS
+
+#define BZ33327_WA
+
+static unsigned long mdio_base;
+static DEFINE_SPINLOCK(mdio_lock);
+
+#define MDIO_CONTROL_RD_DATA ((void *)(mdio_base + 0x0))
+#define MDIO_STATUS_RD_DATA  ((void *)(mdio_base + 0x4))
+#define MDIO_CLK_OFFSET      ((void *)(mdio_base + 0x8))
+#define MDIO_CLK_PERIOD      ((void *)(mdio_base + 0xc))
+
+#ifdef CONFIG_ARM
+#define READ(a) readl((a))
+#define WRITE(a, v) writel((v), (a))
+#else
+#define READ(a) in_le32((a))
+#define WRITE(a, v) out_le32((a), (v))
+#endif
+
+/*
+  
------------------------------------------------------------------------------
+  acp_mdio_read
+*/
+
+int
+acp_mdio_read(unsigned long address, unsigned long offset,
+             unsigned short *value)
+{
+       unsigned long command = 0;
+       unsigned long status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdio_lock, flags);
+#if defined(BZ33327_WA)
+       /* Set the mdio_busy (status) bit. */
+       status = READ(MDIO_STATUS_RD_DATA);
+       status |= 0x40000000;
+       WRITE(MDIO_STATUS_RD_DATA, status);
+#endif                         /* BZ33327_WA */
+
+       /* Write the command. */
+       command |= 0x10000000;  /* op_code: read */
+       command |= (address & 0x1f) << 16;      /* port_addr (target device) */
+       command |= (offset & 0x1f) << 21;/* device_addr (target register) */
+       WRITE(MDIO_CONTROL_RD_DATA, command);
+
+#if defined(BZ33327_WA)
+       /* Wait for the mdio_busy (status) bit to clear. */
+       do {
+               status = READ(MDIO_STATUS_RD_DATA);
+       } while (0 != (status & 0x40000000));
+#endif                         /* BZ33327_WA */
+
+       /* Wait for the mdio_busy (control) bit to clear. */
+       do {
+               command = READ(MDIO_CONTROL_RD_DATA);
+       } while (0 != (command & 0x80000000));
+
+       *value = (unsigned short)(command & 0xffff);
+       spin_unlock_irqrestore(&mdio_lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(acp_mdio_read);
+
+/*
+  
------------------------------------------------------------------------------
+  acp_mdio_write
+*/
+
+int
+acp_mdio_write(unsigned long address, unsigned long offset,
+              unsigned short value)
+{
+       unsigned long command = 0;
+       unsigned long status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdio_lock, flags);
+
+       /* Wait for mdio_busy (control) to be clear. */
+       do {
+               command = READ(MDIO_CONTROL_RD_DATA);
+       } while (0 != (command & 0x80000000));
+
+#if defined(BZ33327_WA)
+       /* Set the mdio_busy (status) bit. */
+       status = READ(MDIO_STATUS_RD_DATA);
+       status |= 0x40000000;
+       WRITE(MDIO_STATUS_RD_DATA, status);
+#endif                         /* BZ33327_WA */
+
+       /* Write the command. */
+       command = 0x08000000;   /* op_code: write */
+       command |= (address & 0x1f) << 16;      /* port_addr (target device) */
+       command |= (offset & 0x1f) << 21;/* device_addr (target register) */
+       command |= (value & 0xffff);    /* value */
+       WRITE(MDIO_CONTROL_RD_DATA, command);
+
+#if defined(BZ33327_WA)
+       /* Wait for the mdio_busy (status) bit to clear. */
+       do {
+               status = READ(MDIO_STATUS_RD_DATA);
+       } while (0 != (status & 0x40000000));
+#endif                         /* BZ33327_WA */
+
+       /* Wait for the mdio_busy (control) bit to clear. */
+       do {
+               command = READ(MDIO_CONTROL_RD_DATA);
+       } while (0 != (command & 0x80000000));
+
+       spin_unlock_irqrestore(&mdio_lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(acp_mdio_write);
+
+/*
+  
------------------------------------------------------------------------------
+  acp_mdio_initialize
+*/
+
+static int
+acp_mdio_initialize(void)
+{
+       WRITE(MDIO_CLK_OFFSET, 0x10);
+       WRITE(MDIO_CLK_PERIOD, 0x2c);
+
+       return 0;
+}
+
+#endif /* ! CONFIG_ACPISS */
+
+/*
+  
==============================================================================
+  
==============================================================================
+  Interrupts
+  
==============================================================================
+  
==============================================================================
+*/
+
+/*
+  
------------------------------------------------------------------------------
+  acp_irq_create_mapping
+*/
+
+unsigned int
+acp_irq_create_mapping(struct irq_domain *host, irq_hw_number_t hwirq)
+{
+       return irq_create_mapping(host, hwirq);
+}
+EXPORT_SYMBOL(acp_irq_create_mapping);
+
+/*
+  
------------------------------------------------------------------------------
+  acp_wrappers_init
+*/
+
+int __init
+acp_wrappers_init(void)
+{
+       int rc = -ENODEV;
+       struct device_node *np = NULL;
+       const u32 *field;
+       u64 mdio_address;
+       u32 mdio_size;
+
+       printk(KERN_INFO "Initializing Axxia Wrappers.\n");
+
+#ifndef CONFIG_ACPISS
+       np = of_find_node_by_type(np, "network");
+
+       while (np && !of_device_is_compatible(np, "acp-femac"))
+               np = of_find_node_by_type(np, "network");
+
+       if (!np)
+               goto error;
+
+       field = of_get_property(np, "mdio-reg", NULL);
+
+       if (!field)
+               goto error;
+
+       mdio_address = of_translate_address(np, field);
+       mdio_size = field[1];
+       mdio_base = (unsigned long)ioremap(mdio_address, mdio_size);
+       printk(KERN_INFO "%s:%d - mdio_address=0x%llx mdio_size=0x%x 
mdio_base=0x%x\n",
+              __FILE__, __LINE__, mdio_address, mdio_size, mdio_base);
+       rc = acp_mdio_initialize();
+#else
+       rc = 0;
+#endif
+
+error:
+
+       return rc;
+}
+module_init(acp_wrappers_init);
+
+MODULE_AUTHOR("LSI Corporation");
+MODULE_DESCRIPTION("Timing Test");
+MODULE_LICENSE("GPL");
+
+#endif
-- 
1.8.3.4

_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to