mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-22 14:23:58 +00:00
phy-sun4i-usb: Use of_match_node to get model specific config data
Use of_match_node instead of calling of_device_is_compatible a ton of times to get model specific config data. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
This commit is contained in:
parent
75f072f9ea
commit
68dbc2ce77
1 changed files with 79 additions and 42 deletions
|
@ -32,6 +32,7 @@
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/phy/phy.h>
|
#include <linux/phy/phy.h>
|
||||||
#include <linux/phy/phy-sun4i-usb.h>
|
#include <linux/phy/phy-sun4i-usb.h>
|
||||||
|
@ -88,12 +89,23 @@
|
||||||
#define DEBOUNCE_TIME msecs_to_jiffies(50)
|
#define DEBOUNCE_TIME msecs_to_jiffies(50)
|
||||||
#define POLL_TIME msecs_to_jiffies(250)
|
#define POLL_TIME msecs_to_jiffies(250)
|
||||||
|
|
||||||
|
enum sun4i_usb_phy_type {
|
||||||
|
sun4i_a10_phy,
|
||||||
|
sun8i_a33_phy,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sun4i_usb_phy_cfg {
|
||||||
|
int num_phys;
|
||||||
|
enum sun4i_usb_phy_type type;
|
||||||
|
u32 disc_thresh;
|
||||||
|
u8 phyctl_offset;
|
||||||
|
bool dedicated_clocks;
|
||||||
|
};
|
||||||
|
|
||||||
struct sun4i_usb_phy_data {
|
struct sun4i_usb_phy_data {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
const struct sun4i_usb_phy_cfg *cfg;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
int num_phys;
|
|
||||||
u32 disc_thresh;
|
|
||||||
bool has_a33_phyctl;
|
|
||||||
struct sun4i_usb_phy {
|
struct sun4i_usb_phy {
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
void __iomem *pmu;
|
void __iomem *pmu;
|
||||||
|
@ -159,17 +171,14 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
|
||||||
{
|
{
|
||||||
struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
|
struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
|
||||||
u32 temp, usbc_bit = BIT(phy->index * 2);
|
u32 temp, usbc_bit = BIT(phy->index * 2);
|
||||||
void *phyctl;
|
void *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mutex_lock(&phy_data->mutex);
|
mutex_lock(&phy_data->mutex);
|
||||||
|
|
||||||
if (phy_data->has_a33_phyctl) {
|
if (phy_data->cfg->type == sun8i_a33_phy) {
|
||||||
phyctl = phy_data->base + REG_PHYCTL_A33;
|
|
||||||
/* A33 needs us to set phyctl to 0 explicitly */
|
/* A33 needs us to set phyctl to 0 explicitly */
|
||||||
writel(0, phyctl);
|
writel(0, phyctl);
|
||||||
} else {
|
|
||||||
phyctl = phy_data->base + REG_PHYCTL_A10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
|
@ -249,7 +258,8 @@ static int sun4i_usb_phy_init(struct phy *_phy)
|
||||||
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
|
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
|
||||||
|
|
||||||
/* Disconnect threshold adjustment */
|
/* Disconnect threshold adjustment */
|
||||||
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2);
|
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
|
||||||
|
data->cfg->disc_thresh, 2);
|
||||||
|
|
||||||
sun4i_usb_phy_passby(phy, 1);
|
sun4i_usb_phy_passby(phy, 1);
|
||||||
|
|
||||||
|
@ -476,7 +486,7 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
|
||||||
{
|
{
|
||||||
struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
|
struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (args->args[0] >= data->num_phys)
|
if (args->args[0] >= data->cfg->num_phys)
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
return data->phys[args->args[0]].phy;
|
return data->phys[args->args[0]].phy;
|
||||||
|
@ -511,7 +521,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct device_node *np = dev->of_node;
|
struct device_node *np = dev->of_node;
|
||||||
struct phy_provider *phy_provider;
|
struct phy_provider *phy_provider;
|
||||||
bool dedicated_clocks;
|
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
|
@ -522,29 +531,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
||||||
mutex_init(&data->mutex);
|
mutex_init(&data->mutex);
|
||||||
INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
|
INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
|
||||||
dev_set_drvdata(dev, data);
|
dev_set_drvdata(dev, data);
|
||||||
|
data->cfg = of_device_get_match_data(dev);
|
||||||
if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
|
if (!data->cfg)
|
||||||
of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
|
return -EINVAL;
|
||||||
of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
|
|
||||||
data->num_phys = 2;
|
|
||||||
else
|
|
||||||
data->num_phys = 3;
|
|
||||||
|
|
||||||
if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
|
|
||||||
of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy"))
|
|
||||||
data->disc_thresh = 2;
|
|
||||||
else
|
|
||||||
data->disc_thresh = 3;
|
|
||||||
|
|
||||||
if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") ||
|
|
||||||
of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
|
|
||||||
of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
|
|
||||||
dedicated_clocks = true;
|
|
||||||
else
|
|
||||||
dedicated_clocks = false;
|
|
||||||
|
|
||||||
if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
|
|
||||||
data->has_a33_phyctl = true;
|
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
|
||||||
data->base = devm_ioremap_resource(dev, res);
|
data->base = devm_ioremap_resource(dev, res);
|
||||||
|
@ -590,7 +579,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < data->num_phys; i++) {
|
for (i = 0; i < data->cfg->num_phys; i++) {
|
||||||
struct sun4i_usb_phy *phy = data->phys + i;
|
struct sun4i_usb_phy *phy = data->phys + i;
|
||||||
char name[16];
|
char name[16];
|
||||||
|
|
||||||
|
@ -602,7 +591,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
||||||
phy->vbus = NULL;
|
phy->vbus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dedicated_clocks)
|
if (data->cfg->dedicated_clocks)
|
||||||
snprintf(name, sizeof(name), "usb%d_phy", i);
|
snprintf(name, sizeof(name), "usb%d_phy", i);
|
||||||
else
|
else
|
||||||
strlcpy(name, "usb_phy", sizeof(name));
|
strlcpy(name, "usb_phy", sizeof(name));
|
||||||
|
@ -689,13 +678,61 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
|
||||||
|
.num_phys = 3,
|
||||||
|
.type = sun4i_a10_phy,
|
||||||
|
.disc_thresh = 3,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A10,
|
||||||
|
.dedicated_clocks = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
|
||||||
|
.num_phys = 2,
|
||||||
|
.type = sun4i_a10_phy,
|
||||||
|
.disc_thresh = 2,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A10,
|
||||||
|
.dedicated_clocks = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
|
||||||
|
.num_phys = 3,
|
||||||
|
.type = sun4i_a10_phy,
|
||||||
|
.disc_thresh = 3,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A10,
|
||||||
|
.dedicated_clocks = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
|
||||||
|
.num_phys = 3,
|
||||||
|
.type = sun4i_a10_phy,
|
||||||
|
.disc_thresh = 2,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A10,
|
||||||
|
.dedicated_clocks = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
|
||||||
|
.num_phys = 2,
|
||||||
|
.type = sun4i_a10_phy,
|
||||||
|
.disc_thresh = 3,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A10,
|
||||||
|
.dedicated_clocks = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
|
||||||
|
.num_phys = 2,
|
||||||
|
.type = sun8i_a33_phy,
|
||||||
|
.disc_thresh = 3,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A33,
|
||||||
|
.dedicated_clocks = true,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id sun4i_usb_phy_of_match[] = {
|
static const struct of_device_id sun4i_usb_phy_of_match[] = {
|
||||||
{ .compatible = "allwinner,sun4i-a10-usb-phy" },
|
{ .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
|
||||||
{ .compatible = "allwinner,sun5i-a13-usb-phy" },
|
{ .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
|
||||||
{ .compatible = "allwinner,sun6i-a31-usb-phy" },
|
{ .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
|
||||||
{ .compatible = "allwinner,sun7i-a20-usb-phy" },
|
{ .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
|
||||||
{ .compatible = "allwinner,sun8i-a23-usb-phy" },
|
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
|
||||||
{ .compatible = "allwinner,sun8i-a33-usb-phy" },
|
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
|
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
|
||||||
|
|
Loading…
Add table
Reference in a new issue