// SPDX-License-Identifier: GPL-2.0 /* * i2c.c - Hardware Dependent Module for I2C Interface * * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG */ #define pr_fmt(fmt) … #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/most.h> enum { … }; #define MAX_BUFFERS_CONTROL … #define MAX_BUF_SIZE_CONTROL … /** * list_first_mbo - get the first mbo from a list * @ptr: the list head to take the mbo from. */ #define list_first_mbo(ptr) … static unsigned int polling_rate; module_param(polling_rate, uint, 0644); MODULE_PARM_DESC(…) …; struct hdm_i2c { … }; static inline struct hdm_i2c *to_hdm(struct most_interface *iface) { … } static irqreturn_t most_irq_handler(int, void *); static void pending_rx_work(struct work_struct *); /** * configure_channel - called from MOST core to configure a channel * @most_iface: interface the channel belongs to * @ch_idx: channel to be configured * @channel_config: structure that holds the configuration information * * Return 0 on success, negative on failure. * * Receives configuration information from MOST core and initialize the * corresponding channel. */ static int configure_channel(struct most_interface *most_iface, int ch_idx, struct most_channel_config *channel_config) { … } /** * enqueue - called from MOST core to enqueue a buffer for data transfer * @most_iface: intended interface * @ch_idx: ID of the channel the buffer is intended for * @mbo: pointer to the buffer object * * Return 0 on success, negative on failure. * * Transmit the data over I2C if it is a "write" request or push the buffer into * list if it is an "read" request */ static int enqueue(struct most_interface *most_iface, int ch_idx, struct mbo *mbo) { … } /** * poison_channel - called from MOST core to poison buffers of a channel * @most_iface: pointer to the interface the channel to be poisoned belongs to * @ch_idx: corresponding channel ID * * Return 0 on success, negative on failure. * * If channel direction is RX, complete the buffers in list with * status MBO_E_CLOSE */ static int poison_channel(struct most_interface *most_iface, int ch_idx) { … } static void do_rx_work(struct hdm_i2c *dev) { … } /** * pending_rx_work - Read pending messages through I2C * @work: definition of this work item * * Invoked by the Interrupt Service Routine, most_irq_handler() */ static void pending_rx_work(struct work_struct *work) { … } /* * most_irq_handler - Interrupt Service Routine * @irq: irq number * @_dev: private data * * Schedules a delayed work * * By default the interrupt line behavior is Active Low. Once an interrupt is * generated by the device, until driver clears the interrupt (by reading * the PMP message), device keeps the interrupt line in low state. Since i2c * read is done in work queue, the interrupt line must be disabled temporarily * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue, * after reading the message. * * Note: If we use the interrupt line in Falling edge mode, there is a * possibility to miss interrupts when ISR is getting executed. * */ static irqreturn_t most_irq_handler(int irq, void *_dev) { … } /* * i2c_probe - i2c probe handler * @client: i2c client device structure * @id: i2c client device id * * Return 0 on success, negative on failure. * * Register the i2c client device as a MOST interface */ static int i2c_probe(struct i2c_client *client) { … } /* * i2c_remove - i2c remove handler * @client: i2c client device structure * * Return 0 on success. * * Unregister the i2c client device as a MOST interface */ static void i2c_remove(struct i2c_client *client) { … } static const struct i2c_device_id i2c_id[] = …; MODULE_DEVICE_TABLE(i2c, i2c_id); static struct i2c_driver i2c_driver = …; module_i2c_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;