uboot/drivers/misc/smsc_sio1007.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <errno.h>
  10#include <smsc_sio1007.h>
  11
  12static inline u8 sio1007_read(int port, int reg)
  13{
  14        outb(reg, port);
  15
  16        return inb(port + 1);
  17}
  18
  19static inline void sio1007_write(int port, int reg, int val)
  20{
  21        outb(reg, port);
  22        outb(val, port + 1);
  23}
  24
  25static inline void sio1007_clrsetbits(int port, int reg, u8 clr, u8 set)
  26{
  27        sio1007_write(port, reg, (sio1007_read(port, reg) & ~clr) | set);
  28}
  29
  30void sio1007_enable_serial(int port, int num, int iobase, int irq)
  31{
  32        if (num < 0 || num > SIO1007_UART_NUM)
  33                return;
  34
  35        /* enter configuration state */
  36        outb(0x55, port);
  37
  38        /* power on serial port and set up its i/o base & irq */
  39        if (!num) {
  40                sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART1_POWER_ON);
  41                sio1007_clrsetbits(port, UART1_IOBASE, 0xfe, iobase >> 2);
  42                sio1007_clrsetbits(port, UART_IRQ, 0xf0, irq << 4);
  43        } else {
  44                sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART2_POWER_ON);
  45                sio1007_clrsetbits(port, UART2_IOBASE, 0xfe, iobase >> 2);
  46                sio1007_clrsetbits(port, UART_IRQ, 0x0f, irq);
  47        }
  48
  49        /* exit configuration state */
  50        outb(0xaa, port);
  51}
  52
  53void sio1007_enable_runtime(int port, int iobase)
  54{
  55        /* enter configuration state */
  56        outb(0x55, port);
  57
  58        /* set i/o base for the runtime register block */
  59        sio1007_clrsetbits(port, RTR_IOBASE_LOW, 0, iobase >> 4);
  60        sio1007_clrsetbits(port, RTR_IOBASE_HIGH, 0, iobase >> 12);
  61        /* turn on address decoding for this block */
  62        sio1007_clrsetbits(port, DEV_ACTIVATE, 0, RTR_EN);
  63
  64        /* exit configuration state */
  65        outb(0xaa, port);
  66}
  67
  68void sio1007_gpio_config(int port, int gpio, int dir, int pol, int type)
  69{
  70        int reg = GPIO0_DIR;
  71
  72        if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
  73                return;
  74        if (gpio >= GPIO_NUM_PER_GROUP) {
  75                reg = GPIO1_DIR;
  76                gpio -= GPIO_NUM_PER_GROUP;
  77        }
  78
  79        /* enter configuration state */
  80        outb(0x55, port);
  81
  82        /* set gpio pin direction, polority and type */
  83        sio1007_clrsetbits(port, reg, 1 << gpio, dir << gpio);
  84        sio1007_clrsetbits(port, reg + 1, 1 << gpio, pol << gpio);
  85        sio1007_clrsetbits(port, reg + 2, 1 << gpio, type << gpio);
  86
  87        /* exit configuration state */
  88        outb(0xaa, port);
  89}
  90
  91int sio1007_gpio_get_value(int port, int gpio)
  92{
  93        int reg = GPIO0_DATA;
  94        int val;
  95
  96        if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
  97                return -EINVAL;
  98        if (gpio >= GPIO_NUM_PER_GROUP) {
  99                reg = GPIO1_DATA;
 100                gpio -= GPIO_NUM_PER_GROUP;
 101        }
 102
 103        val = inb(port + reg);
 104        if (val & (1 << gpio))
 105                return 1;
 106        else
 107                return 0;
 108}
 109
 110void sio1007_gpio_set_value(int port, int gpio, int val)
 111{
 112        int reg = GPIO0_DATA;
 113        u8 data;
 114
 115        if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
 116                return;
 117        if (gpio >= GPIO_NUM_PER_GROUP) {
 118                reg = GPIO1_DATA;
 119                gpio -= GPIO_NUM_PER_GROUP;
 120        }
 121
 122        data = inb(port + reg);
 123        data &= ~(1 << gpio);
 124        data |= (val << gpio);
 125        outb(data, port + reg);
 126}
 127