1 /* 2 * TI/National Semiconductor LP3943 GPIO driver 3 * 4 * Copyright 2013 Texas Instruments 5 * 6 * Author: Milo Kim <milo.kim@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2. 11 */ 12 13 #include <linux/bitops.h> 14 #include <linux/err.h> 15 #include <linux/gpio.h> 16 #include <linux/i2c.h> 17 #include <linux/mfd/lp3943.h> 18 #include <linux/module.h> 19 #include <linux/platform_device.h> 20 #include <linux/slab.h> 21 22 enum lp3943_gpios { 23 LP3943_GPIO1, 24 LP3943_GPIO2, 25 LP3943_GPIO3, 26 LP3943_GPIO4, 27 LP3943_GPIO5, 28 LP3943_GPIO6, 29 LP3943_GPIO7, 30 LP3943_GPIO8, 31 LP3943_GPIO9, 32 LP3943_GPIO10, 33 LP3943_GPIO11, 34 LP3943_GPIO12, 35 LP3943_GPIO13, 36 LP3943_GPIO14, 37 LP3943_GPIO15, 38 LP3943_GPIO16, 39 LP3943_MAX_GPIO, 40 }; 41 42 struct lp3943_gpio { 43 struct gpio_chip chip; 44 struct lp3943 *lp3943; 45 u16 input_mask; /* 1 = GPIO is input direction, 0 = output */ 46 }; 47 48 static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip) 49 { 50 return container_of(_chip, struct lp3943_gpio, chip); 51 } 52 53 static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset) 54 { 55 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); 56 struct lp3943 *lp3943 = lp3943_gpio->lp3943; 57 58 /* Return an error if the pin is already assigned */ 59 if (test_and_set_bit(offset, &lp3943->pin_used)) 60 return -EBUSY; 61 62 return 0; 63 } 64 65 static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset) 66 { 67 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); 68 struct lp3943 *lp3943 = lp3943_gpio->lp3943; 69 70 clear_bit(offset, &lp3943->pin_used); 71 } 72 73 static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset, 74 u8 val) 75 { 76 struct lp3943 *lp3943 = lp3943_gpio->lp3943; 77 const struct lp3943_reg_cfg *mux = lp3943->mux_cfg; 78 79 return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask, 80 val << mux[offset].shift); 81 } 82 83 static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 84 { 85 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); 86 87 lp3943_gpio->input_mask |= BIT(offset); 88 89 return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN); 90 } 91 92 static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio, 93 struct gpio_chip *chip, unsigned offset) 94 { 95 u8 addr, read; 96 int err; 97 98 switch (offset) { 99 case LP3943_GPIO1 ... LP3943_GPIO8: 100 addr = LP3943_REG_GPIO_A; 101 break; 102 case LP3943_GPIO9 ... LP3943_GPIO16: 103 addr = LP3943_REG_GPIO_B; 104 offset = offset - 8; 105 break; 106 default: 107 return -EINVAL; 108 } 109 110 err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read); 111 if (err) 112 return err; 113 114 return !!(read & BIT(offset)); 115 } 116 117 static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio, 118 struct gpio_chip *chip, unsigned offset) 119 { 120 struct lp3943 *lp3943 = lp3943_gpio->lp3943; 121 const struct lp3943_reg_cfg *mux = lp3943->mux_cfg; 122 u8 read; 123 int err; 124 125 err = lp3943_read_byte(lp3943, mux[offset].reg, &read); 126 if (err) 127 return err; 128 129 read = (read & mux[offset].mask) >> mux[offset].shift; 130 131 if (read == LP3943_GPIO_OUT_HIGH) 132 return 1; 133 else if (read == LP3943_GPIO_OUT_LOW) 134 return 0; 135 else 136 return -EINVAL; 137 } 138 139 static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset) 140 { 141 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); 142 143 /* 144 * Limitation: 145 * LP3943 doesn't have the GPIO direction register. It provides 146 * only input and output status registers. 147 * So, direction info is required to handle the 'get' operation. 148 * This variable is updated whenever the direction is changed and 149 * it is used here. 150 */ 151 152 if (lp3943_gpio->input_mask & BIT(offset)) 153 return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset); 154 else 155 return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset); 156 } 157 158 static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 159 { 160 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); 161 u8 data; 162 163 if (value) 164 data = LP3943_GPIO_OUT_HIGH; 165 else 166 data = LP3943_GPIO_OUT_LOW; 167 168 lp3943_gpio_set_mode(lp3943_gpio, offset, data); 169 } 170 171 static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 172 int value) 173 { 174 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); 175 176 lp3943_gpio_set(chip, offset, value); 177 lp3943_gpio->input_mask &= ~BIT(offset); 178 179 return 0; 180 } 181 182 static const struct gpio_chip lp3943_gpio_chip = { 183 .label = "lp3943", 184 .owner = THIS_MODULE, 185 .request = lp3943_gpio_request, 186 .free = lp3943_gpio_free, 187 .direction_input = lp3943_gpio_direction_input, 188 .get = lp3943_gpio_get, 189 .direction_output = lp3943_gpio_direction_output, 190 .set = lp3943_gpio_set, 191 .base = -1, 192 .ngpio = LP3943_MAX_GPIO, 193 .can_sleep = 1, 194 }; 195 196 static int lp3943_gpio_probe(struct platform_device *pdev) 197 { 198 struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent); 199 struct lp3943_gpio *lp3943_gpio; 200 201 lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio), 202 GFP_KERNEL); 203 if (!lp3943_gpio) 204 return -ENOMEM; 205 206 lp3943_gpio->lp3943 = lp3943; 207 lp3943_gpio->chip = lp3943_gpio_chip; 208 lp3943_gpio->chip.dev = &pdev->dev; 209 210 platform_set_drvdata(pdev, lp3943_gpio); 211 212 return gpiochip_add(&lp3943_gpio->chip); 213 } 214 215 static int lp3943_gpio_remove(struct platform_device *pdev) 216 { 217 struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev); 218 219 gpiochip_remove(&lp3943_gpio->chip); 220 return 0; 221 } 222 223 static const struct of_device_id lp3943_gpio_of_match[] = { 224 { .compatible = "ti,lp3943-gpio", }, 225 { } 226 }; 227 MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match); 228 229 static struct platform_driver lp3943_gpio_driver = { 230 .probe = lp3943_gpio_probe, 231 .remove = lp3943_gpio_remove, 232 .driver = { 233 .name = "lp3943-gpio", 234 .of_match_table = lp3943_gpio_of_match, 235 }, 236 }; 237 module_platform_driver(lp3943_gpio_driver); 238 239 MODULE_DESCRIPTION("LP3943 GPIO driver"); 240 MODULE_ALIAS("platform:lp3943-gpio"); 241 MODULE_AUTHOR("Milo Kim"); 242 MODULE_LICENSE("GPL"); 243