xref: /rk3399_rockchip-uboot/drivers/misc/smsc_sio1007.c (revision 98af34f897a6ef5de253806049d033471b02479f)
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