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