0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/fs.h>
0014 #include <linux/delay.h>
0015 #include <linux/uaccess.h>
0016
0017 #include "solo6x10.h"
0018
0019 static void solo_gpio_mode(struct solo_dev *solo_dev,
0020 unsigned int port_mask, unsigned int mode)
0021 {
0022 int port;
0023 unsigned int ret;
0024
0025 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
0026
0027
0028 for (port = 0; port < 16; port++) {
0029 if (!((1 << port) & port_mask))
0030 continue;
0031
0032 ret &= (~(3 << (port << 1)));
0033 ret |= ((mode & 3) << (port << 1));
0034 }
0035
0036 solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret);
0037
0038
0039 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
0040
0041 for (port = 0; port < 16; port++) {
0042 if (!((1UL << (port + 16)) & port_mask))
0043 continue;
0044
0045 if (!mode)
0046 ret &= ~(1UL << port);
0047 else
0048 ret |= 1UL << port;
0049 }
0050
0051
0052 ret |= 0xffff0000;
0053
0054 solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret);
0055 }
0056
0057 static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value)
0058 {
0059 solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
0060 solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value);
0061 }
0062
0063 static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value)
0064 {
0065 solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
0066 solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value);
0067 }
0068
0069 static void solo_gpio_config(struct solo_dev *solo_dev)
0070 {
0071
0072 solo_gpio_mode(solo_dev, 0x30, 1);
0073 solo_gpio_clear(solo_dev, 0x30);
0074 udelay(100);
0075 solo_gpio_set(solo_dev, 0x30);
0076 udelay(100);
0077
0078
0079
0080 solo_gpio_mode(solo_dev, 0x0f, 2);
0081
0082
0083 solo_gpio_mode(solo_dev, 0xff00, 1);
0084
0085
0086 solo_gpio_clear(solo_dev, 0xff00);
0087
0088
0089 solo_gpio_mode(solo_dev, 0xffff0000, 0);
0090 }
0091
0092 #ifdef CONFIG_GPIOLIB
0093
0094
0095
0096
0097 static int solo_gpiochip_get_direction(struct gpio_chip *chip,
0098 unsigned int offset)
0099 {
0100 int ret, mode;
0101 struct solo_dev *solo_dev = gpiochip_get_data(chip);
0102
0103 if (offset < 8) {
0104 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
0105 mode = 3 & (ret >> ((offset + 8) * 2));
0106 } else {
0107 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
0108 mode = 1 & (ret >> (offset - 8));
0109 }
0110
0111 if (!mode)
0112 return 1;
0113 else if (mode == 1)
0114 return 0;
0115
0116 return -1;
0117 }
0118
0119 static int solo_gpiochip_direction_input(struct gpio_chip *chip,
0120 unsigned int offset)
0121 {
0122 return -1;
0123 }
0124
0125 static int solo_gpiochip_direction_output(struct gpio_chip *chip,
0126 unsigned int offset, int value)
0127 {
0128 return -1;
0129 }
0130
0131 static int solo_gpiochip_get(struct gpio_chip *chip,
0132 unsigned int offset)
0133 {
0134 int ret;
0135 struct solo_dev *solo_dev = gpiochip_get_data(chip);
0136
0137 ret = solo_reg_read(solo_dev, SOLO_GPIO_DATA_IN);
0138
0139 return 1 & (ret >> (offset + 8));
0140 }
0141
0142 static void solo_gpiochip_set(struct gpio_chip *chip,
0143 unsigned int offset, int value)
0144 {
0145 struct solo_dev *solo_dev = gpiochip_get_data(chip);
0146
0147 if (value)
0148 solo_gpio_set(solo_dev, 1 << (offset + 8));
0149 else
0150 solo_gpio_clear(solo_dev, 1 << (offset + 8));
0151 }
0152 #endif
0153
0154 int solo_gpio_init(struct solo_dev *solo_dev)
0155 {
0156 #ifdef CONFIG_GPIOLIB
0157 int ret;
0158 #endif
0159
0160 solo_gpio_config(solo_dev);
0161 #ifdef CONFIG_GPIOLIB
0162 solo_dev->gpio_dev.label = SOLO6X10_NAME"_gpio";
0163 solo_dev->gpio_dev.parent = &solo_dev->pdev->dev;
0164 solo_dev->gpio_dev.owner = THIS_MODULE;
0165 solo_dev->gpio_dev.base = -1;
0166 solo_dev->gpio_dev.ngpio = 24;
0167 solo_dev->gpio_dev.can_sleep = 0;
0168
0169 solo_dev->gpio_dev.get_direction = solo_gpiochip_get_direction;
0170 solo_dev->gpio_dev.direction_input = solo_gpiochip_direction_input;
0171 solo_dev->gpio_dev.direction_output = solo_gpiochip_direction_output;
0172 solo_dev->gpio_dev.get = solo_gpiochip_get;
0173 solo_dev->gpio_dev.set = solo_gpiochip_set;
0174
0175 ret = gpiochip_add_data(&solo_dev->gpio_dev, solo_dev);
0176
0177 if (ret) {
0178 solo_dev->gpio_dev.label = NULL;
0179 return -1;
0180 }
0181 #endif
0182 return 0;
0183 }
0184
0185 void solo_gpio_exit(struct solo_dev *solo_dev)
0186 {
0187 #ifdef CONFIG_GPIOLIB
0188 if (solo_dev->gpio_dev.label) {
0189 gpiochip_remove(&solo_dev->gpio_dev);
0190 solo_dev->gpio_dev.label = NULL;
0191 }
0192 #endif
0193 solo_gpio_clear(solo_dev, 0x30);
0194 solo_gpio_config(solo_dev);
0195 }