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 22enum 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 42struct lp3943_gpio { 43 struct gpio_chip chip; 44 struct lp3943 *lp3943; 45 u16 input_mask; /* 1 = GPIO is input direction, 0 = output */ 46}; 47 48static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip) 49{ 50 return container_of(_chip, struct lp3943_gpio, chip); 51} 52 53static 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 65static 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 73static 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 83static 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 92static 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 117static 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 139static 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 158static 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 171static 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 182static 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 196static 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 215static 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 223static const struct of_device_id lp3943_gpio_of_match[] = { 224 { .compatible = "ti,lp3943-gpio", }, 225 { } 226}; 227MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match); 228 229static 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}; 237module_platform_driver(lp3943_gpio_driver); 238 239MODULE_DESCRIPTION("LP3943 GPIO driver"); 240MODULE_ALIAS("platform:lp3943-gpio"); 241MODULE_AUTHOR("Milo Kim"); 242MODULE_LICENSE("GPL"); 243