linux/arch/mips/mti-sead3/sead3-pic32-bus.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
   7 */
   8#include <linux/delay.h>
   9#include <linux/kernel.h>
  10#include <linux/spinlock.h>
  11#include <linux/io.h>
  12#include <linux/errno.h>
  13
  14#define PIC32_NULL      0x00
  15#define PIC32_RD        0x01
  16#define PIC32_SYSRD     0x02
  17#define PIC32_WR        0x10
  18#define PIC32_SYSWR     0x20
  19#define PIC32_IRQ_CLR   0x40
  20#define PIC32_STATUS    0x80
  21
  22#define DELAY() udelay(100)     /* FIXME: needed? */
  23
  24/* spinlock to ensure atomic access to PIC32 */
  25static DEFINE_SPINLOCK(pic32_bus_lock);
  26
  27/* FIXME: io_remap these */
  28static void __iomem *bus_xfer   = (void __iomem *)0xbf000600;
  29static void __iomem *bus_status = (void __iomem *)0xbf000060;
  30
  31static inline unsigned int ioready(void)
  32{
  33        return readl(bus_status) & 1;
  34}
  35
  36static inline void wait_ioready(void)
  37{
  38        do { } while (!ioready());
  39}
  40
  41static inline void wait_ioclear(void)
  42{
  43        do { } while (ioready());
  44}
  45
  46static inline void check_ioclear(void)
  47{
  48        if (ioready()) {
  49                pr_debug("ioclear: initially busy\n");
  50                do {
  51                        (void) readl(bus_xfer);
  52                        DELAY();
  53                } while (ioready());
  54                pr_debug("ioclear: cleared busy\n");
  55        }
  56}
  57
  58u32 pic32_bus_readl(u32 reg)
  59{
  60        unsigned long flags;
  61        u32 status, val;
  62
  63        spin_lock_irqsave(&pic32_bus_lock, flags);
  64
  65        check_ioclear();
  66
  67        writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
  68        DELAY();
  69        wait_ioready();
  70        status = readl(bus_xfer);
  71        DELAY();
  72        val = readl(bus_xfer);
  73        wait_ioclear();
  74
  75        pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
  76
  77        spin_unlock_irqrestore(&pic32_bus_lock, flags);
  78
  79        return val;
  80}
  81
  82void pic32_bus_writel(u32 val, u32 reg)
  83{
  84        unsigned long flags;
  85        u32 status;
  86
  87        spin_lock_irqsave(&pic32_bus_lock, flags);
  88
  89        check_ioclear();
  90
  91        writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
  92        DELAY();
  93        writel(val, bus_xfer);
  94        DELAY();
  95        wait_ioready();
  96        status = readl(bus_xfer);
  97        wait_ioclear();
  98
  99        pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
 100
 101        spin_unlock_irqrestore(&pic32_bus_lock, flags);
 102}
 103