linux/arch/m68knommu/platform/5307/nettel.c
<<
>>
Prefs
   1/***************************************************************************/
   2
   3/*
   4 *      nettel.c -- startup code support for the NETtel boards
   5 *
   6 *      Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
   7 */
   8
   9/***************************************************************************/
  10
  11#include <linux/kernel.h>
  12#include <linux/param.h>
  13#include <linux/init.h>
  14#include <linux/io.h>
  15#include <linux/platform_device.h>
  16#include <asm/coldfire.h>
  17#include <asm/mcfsim.h>
  18#include <asm/nettel.h>
  19
  20/***************************************************************************/
  21
  22/*
  23 * Define the IO and interrupt resources of the 2 SMC9196 interfaces.
  24 */
  25#define NETTEL_SMC0_ADDR        0x30600300
  26#define NETTEL_SMC0_IRQ         29
  27
  28#define NETTEL_SMC1_ADDR        0x30600000
  29#define NETTEL_SMC1_IRQ         27
  30
  31/*
  32 * We need some access into the SMC9196 registers. Define those registers
  33 * we will need here (including the smc91x.h doesn't seem to give us these
  34 * in a simple form).
  35 */
  36#define SMC91xx_BANKSELECT      14
  37#define SMC91xx_BASEADDR        2
  38#define SMC91xx_BASEMAC         4
  39
  40/***************************************************************************/
  41
  42static struct resource nettel_smc91x_0_resources[] = {
  43        {
  44                .start          = NETTEL_SMC0_ADDR,
  45                .end            = NETTEL_SMC0_ADDR + 0x20,
  46                .flags          = IORESOURCE_MEM,
  47        },
  48        {
  49                .start          = NETTEL_SMC0_IRQ,
  50                .end            = NETTEL_SMC0_IRQ,
  51                .flags          = IORESOURCE_IRQ,
  52        },
  53};
  54
  55static struct resource nettel_smc91x_1_resources[] = {
  56        {
  57                .start          = NETTEL_SMC1_ADDR,
  58                .end            = NETTEL_SMC1_ADDR + 0x20,
  59                .flags          = IORESOURCE_MEM,
  60        },
  61        {
  62                .start          = NETTEL_SMC1_IRQ,
  63                .end            = NETTEL_SMC1_IRQ,
  64                .flags          = IORESOURCE_IRQ,
  65        },
  66};
  67
  68static struct platform_device nettel_smc91x[] = {
  69        {
  70                .name                   = "smc91x",
  71                .id                     = 0,
  72                .num_resources          = ARRAY_SIZE(nettel_smc91x_0_resources),
  73                .resource               = nettel_smc91x_0_resources,
  74        },
  75        {
  76                .name                   = "smc91x",
  77                .id                     = 1,
  78                .num_resources          = ARRAY_SIZE(nettel_smc91x_1_resources),
  79                .resource               = nettel_smc91x_1_resources,
  80        },
  81};
  82
  83static struct platform_device *nettel_devices[] __initdata = {
  84        &nettel_smc91x[0],
  85        &nettel_smc91x[1],
  86};
  87
  88/***************************************************************************/
  89
  90static u8 nettel_macdefault[] __initdata = {
  91        0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01,
  92};
  93
  94/*
  95 * Set flash contained MAC address into SMC9196 core. Make sure the flash
  96 * MAC address is sane, and not an empty flash. If no good use the Moreton
  97 * Bay default MAC address instead.
  98 */
  99
 100static void __init nettel_smc91x_setmac(unsigned int ioaddr, unsigned int flashaddr)
 101{
 102        u16 *macp;
 103
 104        macp = (u16 *) flashaddr;
 105        if ((macp[0] == 0xffff) && (macp[1] == 0xffff) && (macp[2] == 0xffff))
 106                macp = (u16 *) &nettel_macdefault[0];
 107
 108        writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
 109        writew(macp[0], ioaddr + SMC91xx_BASEMAC);
 110        writew(macp[1], ioaddr + SMC91xx_BASEMAC + 2);
 111        writew(macp[2], ioaddr + SMC91xx_BASEMAC + 4);
 112}
 113
 114/***************************************************************************/
 115
 116/*
 117 * Re-map the address space of at least one of the SMC ethernet
 118 * parts. Both parts power up decoding the same address, so we
 119 * need to move one of them first, before doing anything else.
 120 */
 121
 122static void __init nettel_smc91x_init(void)
 123{
 124        writew(0x00ec, MCF_MBAR + MCFSIM_PADDR);
 125        mcf_setppdata(0, 0x0080);
 126        writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
 127        writew(0x0067, NETTEL_SMC0_ADDR + SMC91xx_BASEADDR);
 128        mcf_setppdata(0x0080, 0);
 129
 130        /* Set correct chip select timing for SMC9196 accesses */
 131        writew(0x1180, MCF_MBAR + MCFSIM_CSCR3);
 132
 133        /* Set the SMC interrupts to be auto-vectored */
 134        mcf_autovector(NETTEL_SMC0_IRQ);
 135        mcf_autovector(NETTEL_SMC1_IRQ);
 136
 137        /* Set MAC addresses from flash for both interfaces */
 138        nettel_smc91x_setmac(NETTEL_SMC0_ADDR, 0xf0006000);
 139        nettel_smc91x_setmac(NETTEL_SMC1_ADDR, 0xf0006006);
 140}
 141
 142/***************************************************************************/
 143
 144static int __init init_nettel(void)
 145{
 146        nettel_smc91x_init();
 147        platform_add_devices(nettel_devices, ARRAY_SIZE(nettel_devices));
 148        return 0;
 149}
 150
 151arch_initcall(init_nettel);
 152
 153/***************************************************************************/
 154