Commit 98af34f897a6ef5de253806049d033471b02479f
1 parent
4374139627
Exists in
v2017.01-smarct4x
and in
30 other branches
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 |