/* * Google LWIS I2C Bus Manager * * Copyright (c) 2023 Google, LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef LWIS_I2C_BUS_MANAGER_H_ #define LWIS_I2C_BUS_MANAGER_H_ #include "lwis_device.h" #include "lwis_util.h" #include "lwis_periodic_io.h" #include "lwis_transaction.h" /* enum lwis_i2c_device_priority_level: * Defines the I2C device priority level * in which the requests will be executed */ enum lwis_i2c_device_priority_level { I2C_DEVICE_HIGH_PRIORITY = 0, I2C_DEVICE_MEDIUM_PRIORITY = 1, I2C_DEVICE_LOW_PRIORITY = 2, I2C_MAX_PRIORITY_LEVELS = 3 }; // Forward declaration struct lwis_i2c_device; /* struct lwis_i2c_bus_manager_list: * Holds I2C bus manager list */ struct lwis_i2c_bus_manager_list { struct list_head i2c_bus_manager_list_head; }; /* struct lwis_i2c_bus_manager_identifier: * Holds a pointer to the I2C bus manager */ struct lwis_i2c_bus_manager_identifier { struct list_head i2c_bus_manager_list_node; struct lwis_i2c_bus_manager *i2c_bus_manager; int i2c_bus_manager_handle; }; /* lwis_i2c_process_queue: * This maintains the process queue for a given I2C bus. * This is a collection of process request nodes that identify * the lwis device requests in order they were queued. * The scheduler is set to operate requests in a * first in-first out manner, starting and updating the head * and working towards the tail end. */ struct lwis_i2c_process_queue { /* Head node for the process queue */ struct list_head head; /* Total number of devices that are queued to be processed */ int number_of_nodes; }; /* * struct lwis_i2c_bus_manager * This defines the main attributes for I2C Bus Manager. */ struct lwis_i2c_bus_manager { /* Unique identifier for this I2C bus manager */ int i2c_bus_id; /* Name of I2C Bus manager corresponds to the name of the I2C Bus*/ char i2c_bus_name[LWIS_MAX_NAME_STRING_LEN]; /* Lock to control access to bus transfers */ struct mutex i2c_bus_lock; /* Lock to control access to the I2C process queue for this bus */ struct mutex i2c_process_queue_lock; /* I2C Bus thread priority */ u32 i2c_bus_thread_priority; /* Worker thread */ struct kthread_worker i2c_bus_worker; struct task_struct *i2c_bus_worker_thread; /* Queue of all I2C devices that have data to transfer in their process queues */ struct lwis_i2c_process_queue i2c_bus_process_queue[I2C_MAX_PRIORITY_LEVELS]; /* List of I2C devices using this bus */ struct list_head i2c_connected_devices; /* Total number of physically connected devices to the bus * This count is set while probe/unprobe sequence */ int number_of_connected_devices; }; /* This maintains the structure to identify the connected devices to a given I2C bus. * This will be used to guard the bus against processing any illegal device entries */ struct lwis_i2c_connected_device { struct lwis_device *connected_device; struct list_head connected_device_node; }; void lwis_i2c_bus_manager_lock_i2c_bus(struct lwis_device *lwis_dev); void lwis_i2c_bus_manager_unlock_i2c_bus(struct lwis_device *lwis_dev); struct lwis_i2c_bus_manager *lwis_i2c_bus_manager_get_manager(struct lwis_device *lwis_dev); int lwis_i2c_bus_manager_create(struct lwis_i2c_device *i2c_dev); void lwis_i2c_bus_manager_disconnect(struct lwis_device *lwis_dev); void lwis_i2c_bus_manager_process_worker_queue(struct lwis_client *client); void lwis_i2c_bus_manager_flush_i2c_worker(struct lwis_device *lwis_dev); void lwis_i2c_bus_manager_list_initialize(void); void lwis_i2c_bus_manager_list_deinitialize(void); int lwis_i2c_bus_manager_connect_client(struct lwis_client *connecting_client); void lwis_i2c_bus_manager_disconnect_client(struct lwis_client *disconnecting_client); #endif /* LWIS_I2C_BUS_MANAGER_H */