linux/arch/mips/basler/excite/excite_device.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2004 by Basler Vision Technologies AG
   3 *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
   4 *
   5 *  This program is free software; you can redistribute it and/or modify
   6 *  it under the terms of the GNU General Public License as published by
   7 *  the Free Software Foundation; either version 2 of the License, or
   8 *  (at your option) any later version.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *  GNU General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/init.h>
  22#include <linux/platform_device.h>
  23#include <linux/ioport.h>
  24#include <linux/err.h>
  25#include <linux/jiffies.h>
  26#include <linux/sched.h>
  27#include <asm/types.h>
  28#include <asm/rm9k-ocd.h>
  29
  30#include <excite.h>
  31#include <rm9k_eth.h>
  32#include <rm9k_wdt.h>
  33#include <rm9k_xicap.h>
  34#include <excite_nandflash.h>
  35
  36#include "excite_iodev.h"
  37
  38#define RM9K_GE_UNIT    0
  39#define XICAP_UNIT      0
  40#define NAND_UNIT       0
  41
  42#define DLL_TIMEOUT     3               /* seconds */
  43
  44
  45#define RINIT(__start__, __end__, __name__, __parent__) {       \
  46        .name   = __name__ "_0",                                \
  47        .start  = (__start__),                                  \
  48        .end    = (__end__),                                    \
  49        .flags  = 0,                                            \
  50        .parent = (__parent__)                                  \
  51}
  52
  53#define RINIT_IRQ(__irq__, __name__) {  \
  54        .name   = __name__ "_0",        \
  55        .start  = (__irq__),            \
  56        .end    = (__irq__),            \
  57        .flags  = IORESOURCE_IRQ,       \
  58        .parent = NULL                  \
  59}
  60
  61
  62
  63enum {
  64        slice_xicap,
  65        slice_eth
  66};
  67
  68
  69
  70static struct resource
  71        excite_ctr_resource __maybe_unused = {
  72                .name           = "GPI counters",
  73                .start          = 0,
  74                .end            = 5,
  75                .flags          = 0,
  76                .parent         = NULL,
  77                .sibling        = NULL,
  78                .child          = NULL
  79        },
  80        excite_gpislice_resource __maybe_unused = {
  81                .name           = "GPI slices",
  82                .start          = 0,
  83                .end            = 1,
  84                .flags          = 0,
  85                .parent         = NULL,
  86                .sibling        = NULL,
  87                .child          = NULL
  88        },
  89        excite_mdio_channel_resource __maybe_unused = {
  90                .name           = "MDIO channels",
  91                .start          = 0,
  92                .end            = 1,
  93                .flags          = 0,
  94                .parent         = NULL,
  95                .sibling        = NULL,
  96                .child          = NULL
  97        },
  98        excite_fifomem_resource __maybe_unused = {
  99                .name           = "FIFO memory",
 100                .start          = 0,
 101                .end            = 767,
 102                .flags          = 0,
 103                .parent         = NULL,
 104                .sibling        = NULL,
 105                .child          = NULL
 106        },
 107        excite_scram_resource __maybe_unused = {
 108                .name           = "Scratch RAM",
 109                .start          = EXCITE_PHYS_SCRAM,
 110                .end            = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
 111                .flags          = IORESOURCE_MEM,
 112                .parent         = NULL,
 113                .sibling        = NULL,
 114                .child          = NULL
 115        },
 116        excite_fpga_resource __maybe_unused = {
 117                .name           = "System FPGA",
 118                .start          = EXCITE_PHYS_FPGA,
 119                .end            = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
 120                .flags          = IORESOURCE_MEM,
 121                .parent         = NULL,
 122                .sibling        = NULL,
 123                .child          = NULL
 124        },
 125        excite_nand_resource __maybe_unused = {
 126                .name           = "NAND flash control",
 127                .start          = EXCITE_PHYS_NAND,
 128                .end            = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
 129                .flags          = IORESOURCE_MEM,
 130                .parent         = NULL,
 131                .sibling        = NULL,
 132                .child          = NULL
 133        },
 134        excite_titan_resource __maybe_unused = {
 135                .name           = "TITAN registers",
 136                .start          = EXCITE_PHYS_TITAN,
 137                .end            = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
 138                .flags          = IORESOURCE_MEM,
 139                .parent         = NULL,
 140                .sibling        = NULL,
 141                .child          = NULL
 142        };
 143
 144
 145
 146static void adjust_resources(struct resource *res, unsigned int n)
 147{
 148        struct resource *p;
 149        const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM
 150                                   | IORESOURCE_IRQ | IORESOURCE_DMA;
 151
 152        for (p = res; p < res + n; p++) {
 153                const struct resource * const parent = p->parent;
 154                if (parent) {
 155                        p->start += parent->start;
 156                        p->end   += parent->start;
 157                        p->flags =  parent->flags & mask;
 158                }
 159        }
 160}
 161
 162
 163
 164#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE)
 165static struct resource xicap_rsrc[] = {
 166        RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource),
 167        RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource),
 168        RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource),
 169        RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource),
 170        RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource),
 171        RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource),
 172        RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
 173        RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource),
 174        RINIT_IRQ(TITAN_IRQ,  XICAP_RESOURCE_IRQ)
 175};
 176
 177static struct platform_device xicap_pdev = {
 178        .name           = XICAP_NAME,
 179        .id             = XICAP_UNIT,
 180        .num_resources  = ARRAY_SIZE(xicap_rsrc),
 181        .resource       = xicap_rsrc
 182};
 183
 184/*
 185 * Create a platform device for the GPI port that receives the
 186 * image data from the embedded camera.
 187 */
 188static int __init xicap_devinit(void)
 189{
 190        unsigned long tend;
 191        u32 reg;
 192        int retval;
 193
 194        adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc));
 195
 196        /* Power up the slice and configure it. */
 197        reg = titan_readl(CPTC1R);
 198        reg &= ~(0x11100 << slice_xicap);
 199        titan_writel(reg, CPTC1R);
 200
 201        /* Enable slice & DLL. */
 202        reg= titan_readl(CPRR);
 203        reg &= ~(0x00030003 << (slice_xicap * 2));
 204        titan_writel(reg, CPRR);
 205
 206        /* Wait for DLLs to lock */
 207        tend = jiffies + DLL_TIMEOUT * HZ;
 208        while (time_before(jiffies, tend)) {
 209                if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))))
 210                        break;
 211                yield();
 212        }
 213
 214        if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) {
 215                printk(KERN_ERR "%s: DLL not locked after %u seconds\n",
 216                       xicap_pdev.name, DLL_TIMEOUT);
 217                retval = -ETIME;
 218        } else {
 219                /* Register platform device */
 220                retval = platform_device_register(&xicap_pdev);
 221        }
 222
 223        return retval;
 224}
 225
 226device_initcall(xicap_devinit);
 227#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */
 228
 229
 230
 231#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE)
 232static struct resource wdt_rsrc[] = {
 233        RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource),
 234        RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource),
 235        RINIT_IRQ(TITAN_IRQ,  WDT_RESOURCE_IRQ)
 236};
 237
 238static struct platform_device wdt_pdev = {
 239        .name           = WDT_NAME,
 240        .id             = -1,
 241        .num_resources  = ARRAY_SIZE(wdt_rsrc),
 242        .resource       = wdt_rsrc
 243};
 244
 245/*
 246 * Create a platform device for the GPI port that receives the
 247 * image data from the embedded camera.
 248 */
 249static int __init wdt_devinit(void)
 250{
 251        adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc));
 252        return platform_device_register(&wdt_pdev);
 253}
 254
 255device_initcall(wdt_devinit);
 256#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */
 257
 258
 259
 260static struct resource excite_nandflash_rsrc[] = {
 261        RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS,  &excite_nand_resource)
 262};
 263
 264static struct platform_device excite_nandflash_pdev = {
 265        .name           = "excite_nand",
 266        .id             = NAND_UNIT,
 267        .num_resources  = ARRAY_SIZE(excite_nandflash_rsrc),
 268        .resource       = excite_nandflash_rsrc
 269};
 270
 271/*
 272 * Create a platform device for the access to the nand-flash
 273 * port
 274 */
 275static int __init excite_nandflash_devinit(void)
 276{
 277        adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc));
 278
 279        /* nothing to be done here */
 280
 281        /* Register platform device */
 282        return platform_device_register(&excite_nandflash_pdev);
 283}
 284
 285device_initcall(excite_nandflash_devinit);
 286
 287
 288
 289static struct resource iodev_rsrc[] = {
 290        RINIT_IRQ(FPGA1_IRQ,  IODEV_RESOURCE_IRQ)
 291};
 292
 293static struct platform_device io_pdev = {
 294        .name           = IODEV_NAME,
 295        .id             = -1,
 296        .num_resources  = ARRAY_SIZE(iodev_rsrc),
 297        .resource       = iodev_rsrc
 298};
 299
 300/*
 301 * Create a platform device for the external I/O ports.
 302 */
 303static int __init io_devinit(void)
 304{
 305        adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc));
 306        return platform_device_register(&io_pdev);
 307}
 308
 309device_initcall(io_devinit);
 310
 311
 312
 313
 314#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE)
 315static struct resource rm9k_ge_rsrc[] = {
 316        RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource),
 317        RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource),
 318        RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource),
 319        RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource),
 320        RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource),
 321        RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource),
 322        RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource),
 323        RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource),
 324        RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource),
 325        RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource),
 326        RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource),
 327        RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
 328        RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource),
 329        RINIT_IRQ(TITAN_IRQ,  RM9K_GE_RESOURCE_IRQ_MAIN),
 330        RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY)
 331};
 332
 333static struct platform_device rm9k_ge_pdev = {
 334        .name           = RM9K_GE_NAME,
 335        .id             = RM9K_GE_UNIT,
 336        .num_resources  = ARRAY_SIZE(rm9k_ge_rsrc),
 337        .resource       = rm9k_ge_rsrc
 338};
 339
 340
 341
 342/*
 343 * Create a platform device for the Ethernet port.
 344 */
 345static int __init rm9k_ge_devinit(void)
 346{
 347        u32 reg;
 348
 349        adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc));
 350
 351        /* Power up the slice and configure it. */
 352        reg = titan_readl(CPTC1R);
 353        reg &= ~(0x11000 << slice_eth);
 354        reg |= 0x100 << slice_eth;
 355        titan_writel(reg, CPTC1R);
 356
 357        /* Take the MAC out of reset, reset the DLLs. */
 358        reg = titan_readl(CPRR);
 359        reg &= ~(0x00030000 << (slice_eth * 2));
 360        reg |= 0x3 << (slice_eth * 2);
 361        titan_writel(reg, CPRR);
 362
 363        return platform_device_register(&rm9k_ge_pdev);
 364}
 365
 366device_initcall(rm9k_ge_devinit);
 367#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */
 368
 369
 370
 371static int __init excite_setup_devs(void)
 372{
 373        int res;
 374        u32 reg;
 375
 376        /* Enable xdma and fifo interrupts */
 377        reg = titan_readl(0x0050);
 378        titan_writel(reg | 0x18000000, 0x0050);
 379
 380        res = request_resource(&iomem_resource, &excite_titan_resource);
 381        if (res)
 382                return res;
 383        res = request_resource(&iomem_resource, &excite_scram_resource);
 384        if (res)
 385                return res;
 386        res = request_resource(&iomem_resource, &excite_fpga_resource);
 387        if (res)
 388                return res;
 389        res = request_resource(&iomem_resource, &excite_nand_resource);
 390        if (res)
 391                return res;
 392        excite_fpga_resource.flags = excite_fpga_resource.parent->flags &
 393                                   ( IORESOURCE_IO | IORESOURCE_MEM
 394                                   | IORESOURCE_IRQ | IORESOURCE_DMA);
 395        excite_nand_resource.flags = excite_nand_resource.parent->flags &
 396                                   ( IORESOURCE_IO | IORESOURCE_MEM
 397                                   | IORESOURCE_IRQ | IORESOURCE_DMA);
 398
 399        return 0;
 400}
 401
 402arch_initcall(excite_setup_devs);
 403
 404