Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // Gateworks I2C PLD GPIO expander
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) // Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) // Based on code and know-how from the OpenWrt driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) // Copyright (C) 2009 Gateworks Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) // Authors: Chris Lang, Imre Kaloz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/bits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * struct gw_pld - State container for Gateworks PLD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * @chip: GPIO chip instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * @client: I2C client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * @out: shadow register for the output bute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) struct gw_pld {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	u8 out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * The Gateworks I2C PLD chip only expose one read and one write register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * Writing a "one" bit (to match the reset state) lets that pin be used as an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * input. It is an open-drain model.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static int gw_pld_input8(struct gpio_chip *gc, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct gw_pld *gw = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	gw->out |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	return i2c_smbus_write_byte(gw->client, gw->out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static int gw_pld_get8(struct gpio_chip *gc, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	struct gw_pld *gw = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	s32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	val = i2c_smbus_read_byte(gw->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	return (val < 0) ? 0 : !!(val & BIT(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) static int gw_pld_output8(struct gpio_chip *gc, unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct gw_pld *gw = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		gw->out |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		gw->out &= ~BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	return i2c_smbus_write_byte(gw->client, gw->out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static void gw_pld_set8(struct gpio_chip *gc, unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	gw_pld_output8(gc, offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static int gw_pld_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct gw_pld *gw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	gw = devm_kzalloc(dev, sizeof(*gw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (!gw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	gw->chip.base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	gw->chip.can_sleep = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	gw->chip.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	gw->chip.of_node = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	gw->chip.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	gw->chip.label = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	gw->chip.ngpio = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	gw->chip.direction_input = gw_pld_input8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	gw->chip.get = gw_pld_get8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	gw->chip.direction_output = gw_pld_output8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	gw->chip.set = gw_pld_set8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	gw->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	 * The Gateworks I2C PLD chip does not properly send the acknowledge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	 * bit at all times, but we can still use the standard i2c_smbus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	 * functions by simply ignoring this bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	client->flags |= I2C_M_IGNORE_NAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	gw->out = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	i2c_set_clientdata(client, gw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	ret = devm_gpiochip_add_data(dev, &gw->chip, gw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	dev_info(dev, "registered Gateworks PLD GPIO device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const struct i2c_device_id gw_pld_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	{ "gw-pld", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) MODULE_DEVICE_TABLE(i2c, gw_pld_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static const struct of_device_id gw_pld_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	{ .compatible = "gateworks,pld-gpio", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) MODULE_DEVICE_TABLE(of, gw_pld_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static struct i2c_driver gw_pld_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		.name = "gw_pld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		.of_match_table = gw_pld_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	.probe = gw_pld_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	.id_table = gw_pld_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) module_i2c_driver(gw_pld_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");