Commit 98af34f897a6ef5de253806049d033471b02479f

Authored by Bin Meng
1 parent 4374139627

superio: Add SMSC SIO1007 driver

The SMSC SIO1007 superio chipset integrates two ns16550 compatible
serial ports for legacy applications, 16 GPIO pins and some other
functionalities like power management.

This adds a simple driver to enable serial port and handle GPIO.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 3 changed files with 242 additions and 0 deletions Inline Diff

drivers/misc/Makefile
1 # 1 #
2 # (C) Copyright 2000-2007 2 # (C) Copyright 2000-2007
3 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 # 4 #
5 # SPDX-License-Identifier: GPL-2.0+ 5 # SPDX-License-Identifier: GPL-2.0+
6 # 6 #
7 7
8 obj-$(CONFIG_MISC) += misc-uclass.o 8 obj-$(CONFIG_MISC) += misc-uclass.o
9 obj-$(CONFIG_ALI152X) += ali512x.o 9 obj-$(CONFIG_ALI152X) += ali512x.o
10 obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o 10 obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
11 obj-$(CONFIG_DS4510) += ds4510.o 11 obj-$(CONFIG_DS4510) += ds4510.o
12 obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o 12 obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
13 ifndef CONFIG_SPL_BUILD 13 ifndef CONFIG_SPL_BUILD
14 obj-$(CONFIG_CROS_EC) += cros_ec.o 14 obj-$(CONFIG_CROS_EC) += cros_ec.o
15 obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o 15 obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
16 obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o 16 obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
17 obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o 17 obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
18 obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o 18 obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
19 endif 19 endif
20 obj-$(CONFIG_FSL_DEBUG_SERVER) += fsl_debug_server.o 20 obj-$(CONFIG_FSL_DEBUG_SERVER) += fsl_debug_server.o
21 obj-$(CONFIG_FSL_IIM) += fsl_iim.o 21 obj-$(CONFIG_FSL_IIM) += fsl_iim.o
22 obj-$(CONFIG_GPIO_LED) += gpio_led.o 22 obj-$(CONFIG_GPIO_LED) += gpio_led.o
23 obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o 23 obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o
24 obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o 24 obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
25 obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o 25 obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
26 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o 26 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
27 obj-$(CONFIG_NS87308) += ns87308.o 27 obj-$(CONFIG_NS87308) += ns87308.o
28 obj-$(CONFIG_PDSP188x) += pdsp188x.o 28 obj-$(CONFIG_PDSP188x) += pdsp188x.o
29 obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o 29 obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
30 obj-$(CONFIG_SANDBOX) += reset_sandbox.o 30 obj-$(CONFIG_SANDBOX) += reset_sandbox.o
31 ifdef CONFIG_DM_I2C 31 ifdef CONFIG_DM_I2C
32 obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o 32 obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
33 endif 33 endif
34 obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o 34 obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
35 obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
35 obj-$(CONFIG_STATUS_LED) += status_led.o 36 obj-$(CONFIG_STATUS_LED) += status_led.o
36 obj-$(CONFIG_SANDBOX) += swap_case.o 37 obj-$(CONFIG_SANDBOX) += swap_case.o
37 obj-$(CONFIG_SANDBOX) += syscon_sandbox.o 38 obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
38 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o 39 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
39 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o 40 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
40 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o 41 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
41 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o 42 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
42 obj-$(CONFIG_RESET) += reset-uclass.o 43 obj-$(CONFIG_RESET) += reset-uclass.o
43 obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o 44 obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o
44 obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o 45 obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
45 46
drivers/misc/smsc_sio1007.c
File was created 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
12 static inline u8 sio1007_read(int port, int reg)
13 {
14 outb(reg, port);
15
16 return inb(port + 1);
17 }
18
19 static inline void sio1007_write(int port, int reg, int val)
20 {
21 outb(reg, port);
22 outb(val, port + 1);
23 }
24
25 static 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
30 void 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
53 void 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
68 void 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
91 int 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
110 void 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
include/smsc_sio1007.h
File was created 1 /*
2 * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #ifndef _SMSC_SIO1007_H_
8 #define _SMSC_SIO1007_H_
9
10 /*
11 * The I/O base address of SIO1007 at power-up is determined by the SYSOPT0
12 * and SYSOPT1 pins at the deasserting edge of PCIRST#. The combination of
13 * SYSOPT0 and SYSOPT1 determines one of the following addresses.
14 */
15 #define SIO1007_IOPORT0 0x002e
16 #define SIO1007_IOPORT1 0x004e
17 #define SIO1007_IOPORT2 0x162e
18 #define SIO1007_IOPORT3 0x164e
19
20 /* SIO1007 registers */
21
22 #define DEV_POWER_CTRL 0x02
23 #define UART1_POWER_ON (1 << 3)
24 #define UART2_POWER_ON (1 << 7)
25
26 #define UART1_IOBASE 0x24
27 #define UART2_IOBASE 0x25
28 #define UART_IRQ 0x28
29
30 #define RTR_IOBASE_HIGH 0x21
31 #define RTR_IOBASE_LOW 0x30
32
33 #define GPIO0_DIR 0x31
34 #define GPIO1_DIR 0x35
35 #define GPIO_DIR_INPUT 0
36 #define GPIO_DIR_OUTPUT 1
37
38 #define GPIO0_POL 0x32
39 #define GPIO1_POL 0x36
40 #define GPIO_POL_NO_INVERT 0
41 #define GPIO_POL_INVERT 1
42
43 #define GPIO0_TYPE 0x33
44 #define GPIO1_TYPE 0x37
45 #define GPIO_TYPE_PUSH_PULL 0
46 #define GPIO_TYPE_OPEN_DRAIN 1
47
48 #define DEV_ACTIVATE 0x3a
49 #define RTR_EN (1 << 1)
50
51 /* Runtime register offset */
52
53 #define GPIO0_DATA 0xc
54 #define GPIO1_DATA 0xe
55
56 /* Number of serial ports supported */
57 #define SIO1007_UART_NUM 2
58
59 /* Number of gpio pins supported */
60 #define GPIO_NUM_PER_GROUP 8
61 #define GPIO_GROUP_NUM 2
62 #define SIO1007_GPIO_NUM (GPIO_NUM_PER_GROUP * GPIO_GROUP_NUM)
63
64 /**
65 * Configure the I/O port address of the specified serial device and
66 * enable the serial device.
67 *
68 * @port: SIO1007 I/O port address
69 * @num: serial device number (0 or 1)
70 * @iobase: processor I/O port address to assign to this serial device
71 * @irq: processor IRQ number to assign to this serial device
72 */
73 void sio1007_enable_serial(int port, int num, int iobase, int irq);
74
75 /**
76 * Configure the I/O port address of the runtime register block and
77 * enable the address decoding.
78 *
79 * @port: SIO1007 I/O port address
80 * @iobase: processor I/O port address to assign to the runtime registers
81 */
82 void sio1007_enable_runtime(int port, int iobase);
83
84 /**
85 * Configure the direction/polority/type of a specified GPIO pin
86 *
87 * @port: SIO1007 I/O port address
88 * @gpio: GPIO number (0-7 for GP10-GP17, 8-15 for GP30-GP37)
89 * @dir: GPIO_DIR_INPUT or GPIO_DIR_OUTPUT
90 * @pol: GPIO_POL_NO_INVERT or GPIO_POL_INVERT
91 * @type: GPIO_TYPE_PUSH_PULL or GPIO_TYPE_OPEN_DRAIN
92 */
93 void sio1007_gpio_config(int port, int gpio, int dir, int pol, int type);
94
95 /**
96 * Get a GPIO pin value.
97 * This will work whether the GPIO is an input or an output.
98 *
99 * @port: runtime register block I/O port address
100 * @gpio: GPIO number (0-7 for GP10-GP17, 8-15 for GP30-GP37)
101 * @return: 0 if low, 1 if high, -EINVAL if gpio number is invalid
102 */
103 int sio1007_gpio_get_value(int port, int gpio);
104
105 /**
106 * Set a GPIO pin value.
107 * This will only work when the GPIO is configured as an output.
108 *
109 * @port: runtime register block I/O port address
110 * @gpio: GPIO number (0-7 for GP10-GP17, 8-15 for GP30-GP37)
111 * @val: 0 if low, 1 if high
112 */
113 void sio1007_gpio_set_value(int port, int gpio, int val);
114
115 #endif /* _SMSC_SIO1007_H_ */
116