brintos

brintos / linux-shallow public Read only

0
0
Text · 4.9 KiB · 57ef5d3 Raw
233 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * CZ.NIC's Turris Omnia MCU driver4 *5 * 2024 by Marek Behún <kabel@kernel.org>6 */7 8#ifndef __TURRIS_OMNIA_MCU_H9#define __TURRIS_OMNIA_MCU_H10 11#include <linux/bitops.h>12#include <linux/completion.h>13#include <linux/gpio/driver.h>14#include <linux/hw_random.h>15#include <linux/if_ether.h>16#include <linux/mutex.h>17#include <linux/types.h>18#include <linux/watchdog.h>19#include <linux/workqueue.h>20#include <asm/byteorder.h>21#include <linux/unaligned.h>22 23struct i2c_client;24struct rtc_device;25 26struct omnia_mcu {27	struct i2c_client *client;28	const char *type;29	u32 features;30 31	/* board information */32	u64 board_serial_number;33	u8 board_first_mac[ETH_ALEN];34	u8 board_revision;35 36#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO37	/* GPIO chip */38	struct gpio_chip gc;39	struct mutex lock;40	unsigned long mask, rising, falling, both, cached, is_cached;41	/* Old MCU firmware handling needs the following */42	struct delayed_work button_release_emul_work;43	unsigned long last_status;44	bool button_pressed_emul;45#endif46 47#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP48	/* RTC device for configuring wake-up */49	struct rtc_device *rtcdev;50	u32 rtc_alarm;51	bool front_button_poweron;52#endif53 54#ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG55	/* MCU watchdog */56	struct watchdog_device wdt;57#endif58 59#ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG60	/* true random number generator */61	struct hwrng trng;62	struct completion trng_entropy_ready;63#endif64};65 66int omnia_cmd_write_read(const struct i2c_client *client,67			 void *cmd, unsigned int cmd_len,68			 void *reply, unsigned int reply_len);69 70static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,71				  unsigned int len)72{73	return omnia_cmd_write_read(client, cmd, len, NULL, 0);74}75 76static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,77				     u8 val)78{79	u8 buf[2] = { cmd, val };80 81	return omnia_cmd_write(client, buf, sizeof(buf));82}83 84static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,85				      u16 val)86{87	u8 buf[3];88 89	buf[0] = cmd;90	put_unaligned_le16(val, &buf[1]);91 92	return omnia_cmd_write(client, buf, sizeof(buf));93}94 95static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,96				      u32 val)97{98	u8 buf[5];99 100	buf[0] = cmd;101	put_unaligned_le32(val, &buf[1]);102 103	return omnia_cmd_write(client, buf, sizeof(buf));104}105 106static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,107				 void *reply, unsigned int len)108{109	return omnia_cmd_write_read(client, &cmd, 1, reply, len);110}111 112static inline unsigned int113omnia_compute_reply_length(unsigned long mask, bool interleaved,114			   unsigned int offset)115{116	if (!mask)117		return 0;118 119	return ((__fls(mask) >> 3) << interleaved) + 1 + offset;120}121 122/* Returns 0 on success */123static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,124				      unsigned long bits, unsigned long *dst)125{126	__le32 reply;127	int err;128 129	if (!bits) {130		*dst = 0;131		return 0;132	}133 134	err = omnia_cmd_read(client, cmd, &reply,135			     omnia_compute_reply_length(bits, false, 0));136	if (err)137		return err;138 139	*dst = le32_to_cpu(reply) & bits;140 141	return 0;142}143 144static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,145				     unsigned long bit)146{147	unsigned long reply;148	int err;149 150	err = omnia_cmd_read_bits(client, cmd, bit, &reply);151	if (err)152		return err;153 154	return !!reply;155}156 157static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,158				     u32 *dst)159{160	__le32 reply;161	int err;162 163	err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));164	if (err)165		return err;166 167	*dst = le32_to_cpu(reply);168 169	return 0;170}171 172static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,173				     u16 *dst)174{175	__le16 reply;176	int err;177 178	err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));179	if (err)180		return err;181 182	*dst = le16_to_cpu(reply);183 184	return 0;185}186 187static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,188				    u8 *reply)189{190	return omnia_cmd_read(client, cmd, reply, sizeof(*reply));191}192 193#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO194extern const u8 omnia_int_to_gpio_idx[32];195extern const struct attribute_group omnia_mcu_gpio_group;196int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);197#else198static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)199{200	return 0;201}202#endif203 204#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP205extern const struct attribute_group omnia_mcu_poweroff_group;206int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);207#else208static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)209{210	return 0;211}212#endif213 214#ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG215int omnia_mcu_register_trng(struct omnia_mcu *mcu);216#else217static inline int omnia_mcu_register_trng(struct omnia_mcu *mcu)218{219	return 0;220}221#endif222 223#ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG224int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);225#else226static inline int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)227{228	return 0;229}230#endif231 232#endif /* __TURRIS_OMNIA_MCU_H */233