diff options
Diffstat (limited to 'drivers/ata/sata_gemini.c')
| -rw-r--r-- | drivers/ata/sata_gemini.c | 129 |
1 files changed, 47 insertions, 82 deletions
diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c index 8c704523bae7..530ee26b3012 100644 --- a/drivers/ata/sata_gemini.c +++ b/drivers/ata/sata_gemini.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Cortina Systems Gemini SATA bridge add-on to Faraday FTIDE010 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> @@ -10,11 +11,10 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/delay.h> -#include <linux/reset.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/pinctrl/consumer.h> #include "sata_gemini.h" #define DRV_NAME "gemini_sata_bridge" @@ -26,8 +26,6 @@ * @muxmode: the current muxing mode * @ide_pins: if the device is using the plain IDE interface pins * @sata_bridge: if the device enables the SATA bridge - * @sata0_reset: SATA0 reset handler - * @sata1_reset: SATA1 reset handler * @sata0_pclk: SATA0 PCLK handler * @sata1_pclk: SATA1 PCLK handler */ @@ -37,23 +35,10 @@ struct sata_gemini { enum gemini_muxmode muxmode; bool ide_pins; bool sata_bridge; - struct reset_control *sata0_reset; - struct reset_control *sata1_reset; struct clk *sata0_pclk; struct clk *sata1_pclk; }; -/* Global IDE PAD Skew Control Register */ -#define GEMINI_GLOBAL_IDE_SKEW_CTRL 0x18 -#define GEMINI_IDE1_HOST_STROBE_DELAY_SHIFT 28 -#define GEMINI_IDE1_DEVICE_STROBE_DELAY_SHIFT 24 -#define GEMINI_IDE1_OUTPUT_IO_SKEW_SHIFT 20 -#define GEMINI_IDE1_INPUT_IO_SKEW_SHIFT 16 -#define GEMINI_IDE0_HOST_STROBE_DELAY_SHIFT 12 -#define GEMINI_IDE0_DEVICE_STROBE_DELAY_SHIFT 8 -#define GEMINI_IDE0_OUTPUT_IO_SKEW_SHIFT 4 -#define GEMINI_IDE0_INPUT_IO_SKEW_SHIFT 0 - /* Miscellaneous Control Register */ #define GEMINI_GLOBAL_MISC_CTRL 0x30 /* @@ -91,8 +76,6 @@ struct sata_gemini { #define GEMINI_IDE_IOMUX_MODE2 (2 << 24) #define GEMINI_IDE_IOMUX_MODE3 (3 << 24) #define GEMINI_IDE_IOMUX_SHIFT (24) -#define GEMINI_IDE_PADS_ENABLE BIT(4) -#define GEMINI_PFLASH_PADS_DISABLE BIT(1) /* * Registers directly controlling the PATA<->SATA adapters @@ -212,7 +195,10 @@ int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge) pclk = sg->sata0_pclk; else pclk = sg->sata1_pclk; - clk_enable(pclk); + ret = clk_enable(pclk); + if (ret) + return ret; + msleep(10); /* Do not keep clocking a bridge that is not online */ @@ -233,18 +219,6 @@ void gemini_sata_stop_bridge(struct sata_gemini *sg, unsigned int bridge) } EXPORT_SYMBOL(gemini_sata_stop_bridge); -int gemini_sata_reset_bridge(struct sata_gemini *sg, - unsigned int bridge) -{ - if (bridge == 0) - reset_control_reset(sg->sata0_reset); - else - reset_control_reset(sg->sata1_reset); - msleep(10); - return gemini_sata_setup_bridge(sg, bridge); -} -EXPORT_SYMBOL(gemini_sata_reset_bridge); - static int gemini_sata_bridge_init(struct sata_gemini *sg) { struct device *dev = sg->dev; @@ -264,31 +238,16 @@ static int gemini_sata_bridge_init(struct sata_gemini *sg) ret = clk_prepare_enable(sg->sata0_pclk); if (ret) { - pr_err("failed to enable SATA0 PCLK\n"); + dev_err(dev, "failed to enable SATA0 PCLK\n"); return ret; } ret = clk_prepare_enable(sg->sata1_pclk); if (ret) { - pr_err("failed to enable SATA1 PCLK\n"); + dev_err(dev, "failed to enable SATA1 PCLK\n"); clk_disable_unprepare(sg->sata0_pclk); return ret; } - sg->sata0_reset = devm_reset_control_get(dev, "sata0"); - if (IS_ERR(sg->sata0_reset)) { - dev_err(dev, "no SATA0 reset controller\n"); - clk_disable_unprepare(sg->sata1_pclk); - clk_disable_unprepare(sg->sata0_pclk); - return PTR_ERR(sg->sata0_reset); - } - sg->sata1_reset = devm_reset_control_get(dev, "sata1"); - if (IS_ERR(sg->sata1_reset)) { - dev_err(dev, "no SATA1 reset controller\n"); - clk_disable_unprepare(sg->sata1_pclk); - clk_disable_unprepare(sg->sata0_pclk); - return PTR_ERR(sg->sata1_reset); - } - sata_id = readl(sg->base + GEMINI_SATA_ID); sata_phy_id = readl(sg->base + GEMINI_SATA_PHY_ID); sg->sata_bridge = true; @@ -300,17 +259,38 @@ static int gemini_sata_bridge_init(struct sata_gemini *sg) return 0; } +static int gemini_setup_ide_pins(struct device *dev) +{ + struct pinctrl *p; + struct pinctrl_state *ide_state; + int ret; + + p = devm_pinctrl_get(dev); + if (IS_ERR(p)) + return PTR_ERR(p); + + ide_state = pinctrl_lookup_state(p, "ide"); + if (IS_ERR(ide_state)) + return PTR_ERR(ide_state); + + ret = pinctrl_select_state(p, ide_state); + if (ret) { + dev_err(dev, "could not select IDE state\n"); + return ret; + } + + return 0; +} + static int gemini_sata_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct sata_gemini *sg; - static struct regmap *map; - struct resource *res; + struct regmap *map; enum gemini_muxmode muxmode; u32 gmode; u32 gmask; - u32 val; int ret; sg = devm_kzalloc(dev, sizeof(*sg), GFP_KERNEL); @@ -318,11 +298,7 @@ static int gemini_sata_probe(struct platform_device *pdev) return -ENOMEM; sg->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - sg->base = devm_ioremap_resource(dev, res); + sg->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sg->base)) return PTR_ERR(sg->base); @@ -362,16 +338,6 @@ static int gemini_sata_probe(struct platform_device *pdev) gmask = GEMINI_IDE_IOMUX_MASK; gmode = (muxmode << GEMINI_IDE_IOMUX_SHIFT); - /* - * If we mux out the IDE, parallel flash must be disabled. - * SATA0 and SATA1 have dedicated pins and may coexist with - * parallel flash. - */ - if (sg->ide_pins) - gmode |= GEMINI_IDE_PADS_ENABLE | GEMINI_PFLASH_PADS_DISABLE; - else - gmask |= GEMINI_IDE_PADS_ENABLE; - ret = regmap_update_bits(map, GEMINI_GLOBAL_MISC_CTRL, gmask, gmode); if (ret) { dev_err(dev, "unable to set up IDE muxing\n"); @@ -379,14 +345,15 @@ static int gemini_sata_probe(struct platform_device *pdev) goto out_unprep_clk; } - /* FIXME: add more elaborate IDE skew control handling */ + /* + * Route out the IDE pins if desired. + * This is done by looking up a special pin control state called + * "ide" that will route out the IDE pins. + */ if (sg->ide_pins) { - ret = regmap_read(map, GEMINI_GLOBAL_IDE_SKEW_CTRL, &val); - if (ret) { - dev_err(dev, "cannot read IDE skew control register\n"); + ret = gemini_setup_ide_pins(dev); + if (ret) return ret; - } - dev_info(dev, "IDE skew control: %08x\n", val); } dev_info(dev, "set up the Gemini IDE/SATA nexus\n"); @@ -403,7 +370,7 @@ out_unprep_clk: return ret; } -static int gemini_sata_remove(struct platform_device *pdev) +static void gemini_sata_remove(struct platform_device *pdev) { struct sata_gemini *sg = platform_get_drvdata(pdev); @@ -412,27 +379,25 @@ static int gemini_sata_remove(struct platform_device *pdev) clk_unprepare(sg->sata0_pclk); } sg_singleton = NULL; - - return 0; } static const struct of_device_id gemini_sata_of_match[] = { - { - .compatible = "cortina,gemini-sata-bridge", - }, - {}, + { .compatible = "cortina,gemini-sata-bridge", }, + { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, gemini_sata_of_match); static struct platform_driver gemini_sata_driver = { .driver = { .name = DRV_NAME, - .of_match_table = of_match_ptr(gemini_sata_of_match), + .of_match_table = gemini_sata_of_match, }, .probe = gemini_sata_probe, .remove = gemini_sata_remove, }; module_platform_driver(gemini_sata_driver); +MODULE_DESCRIPTION("low level driver for Cortina Systems Gemini SATA bridge"); MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); |
