linux/arch/powerpc/platforms/wsp/h8.c
<<
>>
Prefs
   1/*
   2 * Copyright 2008-2011, IBM Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * as published by the Free Software Foundation; either version
   7 * 2 of the License, or (at your option) any later version.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/of.h>
  12#include <linux/io.h>
  13
  14#include "wsp.h"
  15
  16/*
  17 * The UART connection to the H8 is over ttyS1 which is just a 16550.
  18 * We assume that FW has it setup right and no one messes with it.
  19 */
  20
  21
  22static u8 __iomem *h8;
  23
  24#define RBR 0           /* Receiver Buffer Register */
  25#define THR 0           /* Transmitter Holding Register */
  26#define LSR 5           /* Line Status Register */
  27#define LSR_DR 0x01     /* LSR value for Data-Ready */
  28#define LSR_THRE 0x20   /* LSR value for Transmitter-Holding-Register-Empty */
  29static void wsp_h8_putc(int c)
  30{
  31        u8 lsr;
  32
  33        do {
  34                lsr = readb(h8 + LSR);
  35        } while ((lsr & LSR_THRE) != LSR_THRE);
  36        writeb(c, h8 + THR);
  37}
  38
  39static int wsp_h8_getc(void)
  40{
  41        u8 lsr;
  42
  43        do {
  44                lsr = readb(h8 + LSR);
  45        } while ((lsr & LSR_DR) != LSR_DR);
  46
  47        return readb(h8 + RBR);
  48}
  49
  50static void wsp_h8_puts(const char *s, int sz)
  51{
  52        int i;
  53
  54        for (i = 0; i < sz; i++) {
  55                wsp_h8_putc(s[i]);
  56
  57                /* no flow control so wait for echo */
  58                wsp_h8_getc();
  59        }
  60        wsp_h8_putc('\r');
  61        wsp_h8_putc('\n');
  62}
  63
  64static void wsp_h8_terminal_cmd(const char *cmd, int sz)
  65{
  66        hard_irq_disable();
  67        wsp_h8_puts(cmd, sz);
  68        /* should never return, but just in case */
  69        for (;;)
  70                continue;
  71}
  72
  73
  74void wsp_h8_restart(char *cmd)
  75{
  76        static const char restart[] = "warm-reset";
  77
  78        (void)cmd;
  79        wsp_h8_terminal_cmd(restart, sizeof(restart) - 1);
  80}
  81
  82void wsp_h8_power_off(void)
  83{
  84        static const char off[] = "power-off";
  85
  86        wsp_h8_terminal_cmd(off, sizeof(off) - 1);
  87}
  88
  89static void __iomem *wsp_h8_getaddr(void)
  90{
  91        struct device_node *aliases;
  92        struct device_node *uart;
  93        struct property *path;
  94        void __iomem *va = NULL;
  95
  96        /*
  97         * there is nothing in the devtree to tell us which is mapped
  98         * to the H8, but se know it is the second serial port.
  99         */
 100
 101        aliases = of_find_node_by_path("/aliases");
 102        if (aliases == NULL)
 103                return NULL;
 104
 105        path = of_find_property(aliases, "serial1", NULL);
 106        if (path == NULL)
 107                goto out;
 108
 109        uart = of_find_node_by_path(path->value);
 110        if (uart == NULL)
 111                goto out;
 112
 113        va = of_iomap(uart, 0);
 114
 115        /* remove it so no one messes with it */
 116        of_detach_node(uart);
 117        of_node_put(uart);
 118
 119out:
 120        of_node_put(aliases);
 121
 122        return va;
 123}
 124
 125void __init wsp_setup_h8(void)
 126{
 127        h8 = wsp_h8_getaddr();
 128
 129        /* Devtree change? lets hard map it anyway */
 130        if (h8 == NULL) {
 131                pr_warn("UART to H8 could not be found");
 132                h8 = ioremap(0xffc0008000ULL, 0x100);
 133        }
 134}
 135