diff options
Diffstat (limited to 'drivers/usb/musb/sunxi.c')
-rw-r--r-- | drivers/usb/musb/sunxi.c | 99 |
1 files changed, 70 insertions, 29 deletions
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index 7f9a999cd5ff..9b622cd9b2bd 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/phy/phy-sun4i-usb.h> #include <linux/platform_device.h> #include <linux/reset.h> @@ -67,6 +68,13 @@ #define SUNXI_MUSB_FL_NO_CONFIGDATA 7 #define SUNXI_MUSB_FL_PHY_MODE_PEND 8 +struct sunxi_musb_cfg { + const struct musb_hdrc_config *hdrc_config; + bool has_sram; + bool has_reset; + bool no_configdata; +}; + /* Our read/write methods need access and do not get passed in a musb ref :| */ static struct musb *sunxi_musb; @@ -621,11 +629,10 @@ static const struct musb_platform_ops sunxi_musb_ops = { .post_root_reset_end = sunxi_musb_post_root_reset_end, }; -/* Allwinner OTG supports up to 5 endpoints */ -#define SUNXI_MUSB_MAX_EP_NUM 6 #define SUNXI_MUSB_RAM_BITS 11 -static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = { +/* Allwinner OTG supports up to 5 endpoints */ +static struct musb_fifo_cfg sunxi_musb_mode_cfg_5eps[] = { MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), @@ -639,9 +646,7 @@ static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = { }; /* H3/V3s OTG supports only 4 endpoints */ -#define SUNXI_MUSB_MAX_EP_NUM_H3 5 - -static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = { +static struct musb_fifo_cfg sunxi_musb_mode_cfg_4eps[] = { MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), @@ -652,31 +657,33 @@ static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = { MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), }; -static const struct musb_hdrc_config sunxi_musb_hdrc_config = { - .fifo_cfg = sunxi_musb_mode_cfg, - .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), +static const struct musb_hdrc_config sunxi_musb_hdrc_config_5eps = { + .fifo_cfg = sunxi_musb_mode_cfg_5eps, + .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_5eps), .multipoint = true, .dyn_fifo = true, - .num_eps = SUNXI_MUSB_MAX_EP_NUM, + /* Two FIFOs per endpoint, plus ep_0. */ + .num_eps = (ARRAY_SIZE(sunxi_musb_mode_cfg_5eps) / 2) + 1, .ram_bits = SUNXI_MUSB_RAM_BITS, }; -static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = { - .fifo_cfg = sunxi_musb_mode_cfg_h3, - .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3), +static const struct musb_hdrc_config sunxi_musb_hdrc_config_4eps = { + .fifo_cfg = sunxi_musb_mode_cfg_4eps, + .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_4eps), .multipoint = true, .dyn_fifo = true, - .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3, + /* Two FIFOs per endpoint, plus ep_0. */ + .num_eps = (ARRAY_SIZE(sunxi_musb_mode_cfg_4eps) / 2) + 1, .ram_bits = SUNXI_MUSB_RAM_BITS, }; - static int sunxi_musb_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data pdata; struct platform_device_info pinfo; struct sunxi_glue *glue; struct device_node *np = pdev->dev.of_node; + const struct sunxi_musb_cfg *cfg; int ret; if (!np) { @@ -713,26 +720,25 @@ static int sunxi_musb_probe(struct platform_device *pdev) return -EINVAL; } pdata.platform_ops = &sunxi_musb_ops; - if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) - pdata.config = &sunxi_musb_hdrc_config; - else - pdata.config = &sunxi_musb_hdrc_config_h3; + + cfg = of_device_get_match_data(&pdev->dev); + if (!cfg) + return -EINVAL; + + pdata.config = cfg->hdrc_config; glue->dev = &pdev->dev; INIT_WORK(&glue->work, sunxi_musb_work); glue->host_nb.notifier_call = sunxi_musb_host_notifier; - if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb")) + if (cfg->has_sram) set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags); - if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb")) + if (cfg->has_reset) set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); - if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") || - of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) { - set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); + if (cfg->no_configdata) set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags); - } glue->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(glue->clk)) { @@ -810,11 +816,46 @@ static int sunxi_musb_remove(struct platform_device *pdev) return 0; } +static const struct sunxi_musb_cfg sun4i_a10_musb_cfg = { + .hdrc_config = &sunxi_musb_hdrc_config_5eps, + .has_sram = true, +}; + +static const struct sunxi_musb_cfg sun6i_a31_musb_cfg = { + .hdrc_config = &sunxi_musb_hdrc_config_5eps, + .has_reset = true, +}; + +static const struct sunxi_musb_cfg sun8i_a33_musb_cfg = { + .hdrc_config = &sunxi_musb_hdrc_config_5eps, + .has_reset = true, + .no_configdata = true, +}; + +static const struct sunxi_musb_cfg sun8i_h3_musb_cfg = { + .hdrc_config = &sunxi_musb_hdrc_config_4eps, + .has_reset = true, + .no_configdata = true, +}; + +static const struct sunxi_musb_cfg suniv_f1c100s_musb_cfg = { + .hdrc_config = &sunxi_musb_hdrc_config_5eps, + .has_sram = true, + .has_reset = true, + .no_configdata = true, +}; + static const struct of_device_id sunxi_musb_match[] = { - { .compatible = "allwinner,sun4i-a10-musb", }, - { .compatible = "allwinner,sun6i-a31-musb", }, - { .compatible = "allwinner,sun8i-a33-musb", }, - { .compatible = "allwinner,sun8i-h3-musb", }, + { .compatible = "allwinner,sun4i-a10-musb", + .data = &sun4i_a10_musb_cfg, }, + { .compatible = "allwinner,sun6i-a31-musb", + .data = &sun6i_a31_musb_cfg, }, + { .compatible = "allwinner,sun8i-a33-musb", + .data = &sun8i_a33_musb_cfg, }, + { .compatible = "allwinner,sun8i-h3-musb", + .data = &sun8i_h3_musb_cfg, }, + { .compatible = "allwinner,suniv-f1c100s-musb", + .data = &suniv_f1c100s_musb_cfg, }, {} }; MODULE_DEVICE_TABLE(of, sunxi_musb_match); |