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