mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Add support for GPIOs connected to the MCU on the Turris Omnia board. This includes: - front button pin - enable pins for USB regulators - MiniPCIe / mSATA card presence pins in MiniPCIe port 0 - LED output pins from WAN ethernet PHY, LAN switch and MiniPCIe ports - on board revisions 32+ also various peripheral resets and another voltage regulator enable pin Signed-off-by: Marek Behún <kabel@kernel.org> Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Link: https://lore.kernel.org/r/20240701113010.16447-4-kabel@kernel.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
parent
992f1a3d4e
commit
dfa556e45a
@ -22,6 +22,22 @@ Description: (RO) Contains device first MAC address. Each Turris Omnia is
|
||||
|
||||
Format: %pM.
|
||||
|
||||
What: /sys/bus/i2c/devices/<mcu_device>/front_button_mode
|
||||
Date: September 2024
|
||||
KernelVersion: 6.11
|
||||
Contact: Marek Behún <kabel@kernel.org>
|
||||
Description: (RW) The front button on the Turris Omnia router can be
|
||||
configured either to change the intensity of all the LEDs on the
|
||||
front panel, or to send the press event to the CPU as an
|
||||
interrupt.
|
||||
|
||||
This file switches between these two modes:
|
||||
- "mcu" makes the button press event be handled by the MCU to
|
||||
change the LEDs panel intensity.
|
||||
- "cpu" makes the button press event be handled by the CPU.
|
||||
|
||||
Format: %s.
|
||||
|
||||
What: /sys/bus/i2c/devices/<mcu_device>/fw_features
|
||||
Date: September 2024
|
||||
KernelVersion: 6.11
|
||||
|
@ -16,9 +16,24 @@ config TURRIS_OMNIA_MCU
|
||||
tristate "Turris Omnia MCU driver"
|
||||
depends on MACH_ARMADA_38X || COMPILE_TEST
|
||||
depends on I2C
|
||||
select GPIOLIB
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say Y here to add support for the features implemented by the
|
||||
microcontroller on the CZ.NIC's Turris Omnia SOHO router.
|
||||
The features include:
|
||||
- GPIO pins
|
||||
- to get front button press events (the front button can be
|
||||
configured either to generate press events to the CPU or to change
|
||||
front LEDs panel brightness)
|
||||
- to enable / disable USB port voltage regulators and to detect
|
||||
USB overcurrent
|
||||
- to detect MiniPCIe / mSATA card presence in MiniPCIe port 0
|
||||
- to configure resets of various peripherals on board revisions 32+
|
||||
- to enable / disable the VHV voltage regulator to the SOC in order
|
||||
to be able to program SOC's OTP on board revisions 32+
|
||||
- to get input from the LED output pins of the WAN ethernet PHY, LAN
|
||||
switch and MiniPCIe ports
|
||||
To compile this driver as a module, choose M here; the module will be
|
||||
called turris-omnia-mcu.
|
||||
|
||||
|
@ -2,3 +2,4 @@
|
||||
|
||||
obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o
|
||||
turris-omnia-mcu-y := turris-omnia-mcu-base.o
|
||||
turris-omnia-mcu-y += turris-omnia-mcu-gpio.o
|
||||
|
@ -197,6 +197,7 @@ static const struct attribute_group omnia_mcu_base_group = {
|
||||
|
||||
static const struct attribute_group *omnia_mcu_groups[] = {
|
||||
&omnia_mcu_base_group,
|
||||
&omnia_mcu_gpio_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -371,7 +372,7 @@ static int omnia_mcu_probe(struct i2c_client *client)
|
||||
"Cannot read board info\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return omnia_mcu_register_gpiochip(mcu);
|
||||
}
|
||||
|
||||
static const struct of_device_id of_omnia_mcu_match[] = {
|
||||
|
1095
drivers/platform/cznic/turris-omnia-mcu-gpio.c
Normal file
1095
drivers/platform/cznic/turris-omnia-mcu-gpio.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,12 @@
|
||||
#ifndef __TURRIS_OMNIA_MCU_H
|
||||
#define __TURRIS_OMNIA_MCU_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
struct i2c_client;
|
||||
@ -23,18 +27,78 @@ struct omnia_mcu {
|
||||
u64 board_serial_number;
|
||||
u8 board_first_mac[ETH_ALEN];
|
||||
u8 board_revision;
|
||||
|
||||
/* GPIO chip */
|
||||
struct gpio_chip gc;
|
||||
struct mutex lock;
|
||||
unsigned long mask, rising, falling, both, cached, is_cached;
|
||||
/* Old MCU firmware handling needs the following */
|
||||
struct delayed_work button_release_emul_work;
|
||||
unsigned long last_status;
|
||||
bool button_pressed_emul;
|
||||
};
|
||||
|
||||
int omnia_cmd_write_read(const struct i2c_client *client,
|
||||
void *cmd, unsigned int cmd_len,
|
||||
void *reply, unsigned int reply_len);
|
||||
|
||||
static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
|
||||
unsigned int len)
|
||||
{
|
||||
return omnia_cmd_write_read(client, cmd, len, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
|
||||
void *reply, unsigned int len)
|
||||
{
|
||||
return omnia_cmd_write_read(client, &cmd, 1, reply, len);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
omnia_compute_reply_length(unsigned long mask, bool interleaved,
|
||||
unsigned int offset)
|
||||
{
|
||||
if (!mask)
|
||||
return 0;
|
||||
|
||||
return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
|
||||
}
|
||||
|
||||
/* Returns 0 on success */
|
||||
static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,
|
||||
unsigned long bits, unsigned long *dst)
|
||||
{
|
||||
__le32 reply;
|
||||
int err;
|
||||
|
||||
if (!bits) {
|
||||
*dst = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = omnia_cmd_read(client, cmd, &reply,
|
||||
omnia_compute_reply_length(bits, false, 0));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*dst = le32_to_cpu(reply) & bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,
|
||||
unsigned long bit)
|
||||
{
|
||||
unsigned long reply;
|
||||
int err;
|
||||
|
||||
err = omnia_cmd_read_bits(client, cmd, bit, &reply);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return !!reply;
|
||||
}
|
||||
|
||||
static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
|
||||
u32 *dst)
|
||||
{
|
||||
@ -71,4 +135,8 @@ static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
|
||||
return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
|
||||
}
|
||||
|
||||
extern const struct attribute_group omnia_mcu_gpio_group;
|
||||
|
||||
int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
|
||||
|
||||
#endif /* __TURRIS_OMNIA_MCU_H */
|
||||
|
Loading…
Reference in New Issue
Block a user