1
0
This repository has been archived on 2025-07-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
orange_kernel/drivers/usb/misc/ky_onboard_hub.h
2025-03-18 10:29:27 +08:00

187 lines
4.3 KiB
C

#include <linux/property.h>
#include <linux/delay.h>
#include <linux/usb.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
struct ky_hub_priv {
struct device *dev;
bool is_hub_on;
bool is_vbus_on;
struct gpio_descs *hub_gpios;
struct gpio_descs *vbus_gpios;
bool hub_gpio_active_low;
bool vbus_gpio_active_low;
u32 hub_inter_delay_ms;
u32 vbus_delay_ms;
u32 vbus_inter_delay_ms;
bool suspend_power_on;
struct mutex hub_mutex;
};
static void ky_hub_enable(struct ky_hub_priv *ky, bool on);
static void ky_hub_vbus_enable(struct ky_hub_priv *ky,
bool on);
static int ky_hub_enable_show(struct seq_file *s, void *unused)
{
struct ky_hub_priv *ky = s->private;
mutex_lock(&ky->hub_mutex);
seq_puts(s, ky->is_hub_on ? "true\n" : "false\n");
mutex_unlock(&ky->hub_mutex);
return 0;
}
static ssize_t ky_hub_enable_write(struct file *file,
const char __user *ubuf, size_t count,
loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ky_hub_priv *ky = s->private;
bool on = false;
char buf[32];
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if ((!strncmp(buf, "true", 4)) || (!strncmp(buf, "1", 1)))
on = true;
if ((!strncmp(buf, "false", 5)) || !strncmp(buf, "0", 1))
on = false;
mutex_lock(&ky->hub_mutex);
if (on != ky->is_hub_on) {
ky_hub_enable(ky, on);
}
mutex_unlock(&ky->hub_mutex);
return count;
}
static int ky_hub_enable_open(struct inode *inode, struct file *file)
{
return single_open(file, ky_hub_enable_show, inode->i_private);
}
struct file_operations ky_hub_enable_fops = {
.open = ky_hub_enable_open,
.write = ky_hub_enable_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int ky_hub_vbus_show(struct seq_file *s, void *unused)
{
struct ky_hub_priv *ky = s->private;
mutex_lock(&ky->hub_mutex);
seq_puts(s, ky->is_vbus_on ? "true\n" : "false\n");
mutex_unlock(&ky->hub_mutex);
return 0;
}
static ssize_t ky_hub_vbus_write(struct file *file,
const char __user *ubuf, size_t count,
loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ky_hub_priv *ky = s->private;
bool on = false;
char buf[32];
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if ((!strncmp(buf, "true", 4)) || (!strncmp(buf, "1", 1)))
on = true;
if ((!strncmp(buf, "false", 5)) || !strncmp(buf, "0", 1))
on = false;
mutex_lock(&ky->hub_mutex);
if (on != ky->is_vbus_on) {
ky_hub_vbus_enable(ky, on);
}
mutex_unlock(&ky->hub_mutex);
return count;
}
static int ky_hub_vbus_open(struct inode *inode, struct file *file)
{
return single_open(file, ky_hub_vbus_show, inode->i_private);
}
struct file_operations ky_hub_vbus_fops = {
.open = ky_hub_vbus_open,
.write = ky_hub_vbus_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int ky_hub_suspend_show(struct seq_file *s, void *unused)
{
struct ky_hub_priv *ky = s->private;
mutex_lock(&ky->hub_mutex);
seq_puts(s, ky->suspend_power_on ? "true\n" : "false\n");
mutex_unlock(&ky->hub_mutex);
return 0;
}
static ssize_t ky_hub_suspend_write(struct file *file,
const char __user *ubuf, size_t count,
loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ky_hub_priv *ky = s->private;
bool on = false;
char buf[32];
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if ((!strncmp(buf, "true", 4)) || (!strncmp(buf, "1", 1)))
on = true;
if ((!strncmp(buf, "false", 5)) || !strncmp(buf, "0", 1))
on = false;
mutex_lock(&ky->hub_mutex);
ky->suspend_power_on = on;
mutex_unlock(&ky->hub_mutex);
return count;
}
static int ky_hub_suspend_open(struct inode *inode, struct file *file)
{
return single_open(file, ky_hub_suspend_show, inode->i_private);
}
struct file_operations ky_hub_suspend_fops = {
.open = ky_hub_suspend_open,
.write = ky_hub_suspend_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void ky_hub_debugfs_init(struct ky_hub_priv *ky)
{
struct dentry *root;
root = debugfs_create_dir(dev_name(ky->dev), usb_debug_root);
debugfs_create_file("vbus_on", 0644, root, ky,
&ky_hub_vbus_fops);
debugfs_create_file("hub_on", 0644, root, ky,
&ky_hub_enable_fops);
debugfs_create_file("suspend_power_on", 0644, root, ky,
&ky_hub_suspend_fops);
}