mirror of
https://github.com/thead-yocto-mirror/vi-kernel
synced 2026-07-20 14:58:10 +02:00
265 lines
6.8 KiB
C
Executable File
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;
|
|
}
|