Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
  4 *
  5 * Author: Wu Guoxing <b39297@freescale.com>
  6 */
  7
  8#include <linux/kernel.h>
  9#include <linux/init.h>
 10#include <linux/slab.h>
 11#include <linux/i2c.h>
 12#include <linux/gpio/driver.h>
 13
 14#define GPIO_GROUP_NUM 2
 15#define GPIO_NUM_PER_GROUP 8
 16#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
 17
 18struct mc9s08dz60 {
 19	struct i2c_client *client;
 20	struct gpio_chip chip;
 21};
 22
 23static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
 24{
 25	*reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
 26	*bit = offset % GPIO_NUM_PER_GROUP;
 27}
 28
 29static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
 30{
 31	u8 reg, bit;
 32	s32 value;
 33	struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
 34
 35	mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
 36	value = i2c_smbus_read_byte_data(mc9s->client, reg);
 37
 38	return (value >= 0) ? (value >> bit) & 0x1 : 0;
 39}
 40
 41static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
 42{
 43	u8 reg, bit;
 44	s32 value;
 45
 46	mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
 47	value = i2c_smbus_read_byte_data(mc9s->client, reg);
 48	if (value >= 0) {
 49		if (val)
 50			value |= 1 << bit;
 51		else
 52			value &= ~(1 << bit);
 53
 54		return i2c_smbus_write_byte_data(mc9s->client, reg, value);
 55	} else
 56		return value;
 57
 58}
 59
 60
 61static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
 62{
 63	struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
 64
 65	mc9s08dz60_set(mc9s, offset, val);
 66}
 67
 68static int mc9s08dz60_direction_output(struct gpio_chip *gc,
 69				       unsigned offset, int val)
 70{
 71	struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
 72
 73	return mc9s08dz60_set(mc9s, offset, val);
 74}
 75
 76static int mc9s08dz60_probe(struct i2c_client *client,
 77			    const struct i2c_device_id *id)
 78{
 79	struct mc9s08dz60 *mc9s;
 80
 81	mc9s = devm_kzalloc(&client->dev, sizeof(*mc9s), GFP_KERNEL);
 82	if (!mc9s)
 83		return -ENOMEM;
 84
 85	mc9s->chip.label = client->name;
 86	mc9s->chip.base = -1;
 87	mc9s->chip.parent = &client->dev;
 88	mc9s->chip.owner = THIS_MODULE;
 89	mc9s->chip.ngpio = GPIO_NUM;
 90	mc9s->chip.can_sleep = true;
 91	mc9s->chip.get = mc9s08dz60_get_value;
 92	mc9s->chip.set = mc9s08dz60_set_value;
 93	mc9s->chip.direction_output = mc9s08dz60_direction_output;
 94	mc9s->client = client;
 95	i2c_set_clientdata(client, mc9s);
 96
 97	return devm_gpiochip_add_data(&client->dev, &mc9s->chip, mc9s);
 98}
 99
100static const struct i2c_device_id mc9s08dz60_id[] = {
101	{"mc9s08dz60", 0},
102	{},
103};
104
105static struct i2c_driver mc9s08dz60_i2c_driver = {
106	.driver = {
107		.name = "mc9s08dz60",
108	},
109	.probe = mc9s08dz60_probe,
110	.id_table = mc9s08dz60_id,
111};
112builtin_i2c_driver(mc9s08dz60_i2c_driver);