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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * tps6507x.c  --  TPS6507x chip family multi-function driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Copyright (c) 2010 RidgeRun (todd.fischer@ridgerun.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Author: Todd Fischer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *         todd.fischer@ridgerun.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Credits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *    Using code from wm831x-*.c, wm8400-core, Wolfson Microelectronics PLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * For licencing details see kernel-base/COPYING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/mfd/tps6507x.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static const struct mfd_cell tps6507x_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		.name = "tps6507x-pmic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		.name = "tps6507x-ts",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static int tps6507x_i2c_read_device(struct tps6507x_dev *tps6507x, char reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 				  int bytes, void *dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct i2c_client *i2c = tps6507x->i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	struct i2c_msg xfer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	/* Write register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	xfer[0].addr = i2c->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	xfer[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	xfer[0].len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	xfer[0].buf = &reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	/* Read data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	xfer[1].addr = i2c->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	xfer[1].flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	xfer[1].len = bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	xfer[1].buf = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	ret = i2c_transfer(i2c->adapter, xfer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (ret == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	else if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	return ret;
^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 int tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				   int bytes, void *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct i2c_client *i2c = tps6507x->i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	/* we add 1 byte for device register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	u8 msg[TPS6507X_MAX_REGISTER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (bytes > TPS6507X_MAX_REGISTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	msg[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	memcpy(&msg[1], src, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	ret = i2c_master_send(i2c, msg, bytes + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (ret != bytes + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static int tps6507x_i2c_probe(struct i2c_client *i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			    const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct tps6507x_dev *tps6507x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	tps6507x = devm_kzalloc(&i2c->dev, sizeof(struct tps6507x_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 				GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (tps6507x == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	i2c_set_clientdata(i2c, tps6507x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	tps6507x->dev = &i2c->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	tps6507x->i2c_client = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	tps6507x->read_dev = tps6507x_i2c_read_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	tps6507x->write_dev = tps6507x_i2c_write_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	return devm_mfd_add_devices(tps6507x->dev, -1, tps6507x_devs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 				    ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static const struct i2c_device_id tps6507x_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	{ "tps6507x", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const struct of_device_id tps6507x_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	{.compatible = "ti,tps6507x", },
^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(of, tps6507x_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static struct i2c_driver tps6507x_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		   .name = "tps6507x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		   .of_match_table = of_match_ptr(tps6507x_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	.probe = tps6507x_i2c_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	.id_table = tps6507x_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int __init tps6507x_i2c_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return i2c_add_driver(&tps6507x_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* init early so consumer devices can complete system boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) subsys_initcall(tps6507x_i2c_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void __exit tps6507x_i2c_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	i2c_del_driver(&tps6507x_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) module_exit(tps6507x_i2c_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) MODULE_DESCRIPTION("TPS6507x chip family multi-function driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) MODULE_LICENSE("GPL");