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