Files
vi-kernel/vvcam/native/csi/dw-dphy-sysfs.c
2022-09-13 10:34:22 +08:00

265 lines
6.8 KiB
C
Executable File

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI D-PHY controller driver.
* SysFS components for the platform driver
*
* Author: Luis Oliveira <luis.oliveira@synopsys.com>
*/
//#define DEBUG 1
#include "dw-dphy-rx.h"
#include "bm_csi_hw.h"
static ssize_t dphy_reset_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[15];
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
usleep_range(100, 200);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t dphy_freq_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
int ret;
unsigned long freq;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
ret = kstrtoul(buf, 10, &freq);
if (ret < 0)
return ret;
if (freq > 2500) {
dev_info(dev, "Freq must be under 2500 Mhz\n");
return count;
}
if (freq < 80) {
dev_info(dev, "Freq must be over 80 Mhz\n");
return count;
}
dev_vdbg(dev, "Data Rate %lu Mbps\n", freq);
dphy->dphy_freq = freq*1000;
return count;
}
static ssize_t dphy_freq_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[15];
snprintf(buffer,
sizeof(buffer),
"Freq %d\n", dphy->dphy_freq);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t dphy_addr_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long addr;
int ret;
ret = kstrtoul(buf, 10, &addr);
if (ret < 0)
return ret;
//payload = (u16)val;
//addr = (u16)(val >> 16);
//dev_vdbg(dev, "addr 0x%lX\n", val);
//dev_vdbg(dev, "payload: 0x%X\n", addr);
//dev_vdbg(dev, "Addr [0x%x] -> 0x%x\n", (unsigned int)addr,
// dw_dphy_te_read(dphy, addr));
printk("<0>""addr 0x%lX\n", addr);
printk("<0>""Addr [0x%x] -> 0x%x\n", (unsigned int)addr,
dw_dphy_te_read(dphy, addr));
return count;
}
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
#if 0
static ssize_t idelay_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[15];
snprintf(buffer,
sizeof(buffer), "idelay %d\n", dw_dphy_if_get_idelay(dphy));
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t idelay_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long val;
u8 lane, delay;
int ret;
ret = kstrtoul(buf, 16, &val);
if (ret < 0)
return ret;
lane = (u8)val;
delay = (u8)(val >> 8);
dev_vdbg(dev, "Lanes %u\n", lane);
dev_vdbg(dev, "Delay %u\n", delay);
dw_dphy_if_set_idelay_lane(dphy, delay, lane);
return count;
}
#endif
#endif
static ssize_t len_config_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long length;
int ret;
ret = kstrtoul(buf, 10, &length);
if (ret < 0)
return ret;
if (length == BIT8)
dev_vdbg(dev, "Configured for 8-bit interface\n");
else if (length == BIT12)
dev_vdbg(dev, "Configured for 12-bit interface\n");
else
return count;
dphy->dphy_te_len = length;
return count;
}
static ssize_t len_config_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[20];
snprintf(buffer, sizeof(buffer), "Length %d\n", dphy->dphy_te_len);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t dw_dphy_g118_settle_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long lp_time;
int ret;
ret = kstrtoul(buf, 10, &lp_time);
if (ret < 0)
return ret;
if (lp_time > 1 && lp_time < 10000) {
dphy->lp_time = lp_time;
} else {
dev_vdbg(dev, "Invalid Value configuring for 1000 ns\n");
dphy->lp_time = 1000;
}
dphy->lp_time = lp_time;
return count;
}
static ssize_t dw_dphy_g118_settle_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[10];
snprintf(buffer, sizeof(buffer), "Settle %d ns\n", dphy->lp_time);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static DEVICE_ATTR_RO(dphy_reset);
static DEVICE_ATTR_RW(dphy_freq);
static DEVICE_ATTR_WO(dphy_addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
//static DEVICE_ATTR_RW(idelay);
#endif
static DEVICE_ATTR_RW(len_config);
static DEVICE_ATTR_RW(dw_dphy_g118_settle);
int dw_dphy_create_capabilities_sysfs(struct platform_device *pdev)
{
device_create_file(&pdev->dev, &dev_attr_dphy_reset);
device_create_file(&pdev->dev, &dev_attr_dphy_freq);
device_create_file(&pdev->dev, &dev_attr_dphy_addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
// device_create_file(&pdev->dev, &dev_attr_idelay);
#endif
device_create_file(&pdev->dev, &dev_attr_len_config);
device_create_file(&pdev->dev, &dev_attr_dw_dphy_g118_settle);
return 0;
}
int dw_dphy_remove_capabilities_sysfs(struct platform_device *pdev)
{
device_remove_file(&pdev->dev, &dev_attr_dphy_reset);
device_remove_file(&pdev->dev, &dev_attr_dphy_freq);
device_remove_file(&pdev->dev, &dev_attr_dphy_addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
// device_create_file(&pdev->dev, &dev_attr_idelay);
#endif
device_remove_file(&pdev->dev, &dev_attr_len_config);
device_remove_file(&pdev->dev, &dev_attr_dw_dphy_g118_settle);
return 0;
}