* Could you please let me know if you receive my last email, introducing myself to you, on a ( Business Opportunity)? I urgently wish to know if we can work together.
From: United Bank For Africa @ 2017-03-17 11:39 UTC (permalink / raw)
^ permalink raw reply
* Re: [PATCH] pata_pcmcia: add EBSA110's PCMCIA slot support
From: Bartlomiej Zolnierkiewicz @ 2017-03-17 11:59 UTC (permalink / raw)
To: Tejun Heo
Cc: Russell King, Sergei Shtylyov, Sekhar Nori, Arnd Bergmann,
Dmitry Eremin-Solenikov, Kevin Hilman, Olof Johansson, linux-ide,
linux-arm-kernel, linux-kernel
In-Reply-To: <20170316212654.GD1480@htj.duckdns.org>
Hi,
On Thursday, March 16, 2017 05:26:54 PM Tejun Heo wrote:
> Hello,
>
> On Tue, Mar 14, 2017 at 06:50:43PM +0100, Bartlomiej Zolnierkiewicz wrote:
> > +static struct ata_port_operations pcmcia_ebsa110_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .sff_dev_select = pmcmia_ebsa110_dev_select,
> ^^^^^^
> > + .sff_set_devctl = pcmcia_ebsa110_set_devctl,
> > + .sff_check_status = pcmcia_ebsa110_check_status,
> > + .sff_check_altstatus = pcmcia_ebsa110_check_altstatus,
> > + .sff_tf_load = pcmcia_ebsa110_tf_load,
> > + .sff_tf_read = pcmcia_ebsa110_tf_read,
> > + .sff_exec_command = pcmcia_ebsa110_exec_command,
> > + .sff_data_xfer = ata_sff_data_xfer_noirq,
> > + .softreset = pata_pcmcia_ebsa110_softreset,
> > + .cable_detect = ata_cable_40wire,
> > + .set_mode = pcmcia_set_mode,
> > +};
>
> Heh, that's a fat driver for a sff device. I suppose this is mostly
> copied from the matching ide driver but it'd be nice to explain why it
> needs duplicate most standard functions. Is it because PCMCIA
> assigned address doesn't fall under the usual read/io boundary on the
> arch?
There is no support for this device in the upstream ide driver but
Russell has a hacky patch to make it work by redefining inb()/outb()
operations globally for the whole ide subsystem, please see:
https://www.spinics.net/lists/arm-kernel/msg567454.html
and
arch/arm/mach-ebsa110/io.c
Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics
^ permalink raw reply
* Re: [PATCH v2 0/3] ATA/ARM: convert ARM/DaVinci to use libata PATA drivers
From: Tejun Heo @ 2017-03-16 21:32 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz
Cc: Russell King, Sergei Shtylyov, Arnd Bergmann,
Dmitry Eremin-Solenikov, Kevin Hilman, Sekhar Nori, linux-kernel,
linux-ide, linux-arm-kernel
In-Reply-To: <1489509414-11491-1-git-send-email-b.zolnierkie@samsung.com>
On Tue, Mar 14, 2017 at 05:36:51PM +0100, Bartlomiej Zolnierkiewicz wrote:
> Hi,
>
> This patchset adds Palmchip BK3710 IDE controller driver to
> libata and switches ARM/DaVinci to use it (instead of the old
> IDE driver).
>
> Sekhar, please check that it still works after changes, thanks.
>
> Changes since v1
> (https://www.spinics.net/lists/arm-kernel/msg567442.html):
> - addressed review comments from Sergei Shtylyov
> - fixed cycle_time unitialized variable issue
>
> Changes since v0.1 draft patch version
> (https://www.spinics.net/lists/arm-kernel/msg566932.html):
> - fixed cycle_time build warning
> - added platform support fixes from Sekhar
> - added defconfig changes from Sekhar
> - preserved platform support for the old IDE driver
> - split it on 3 patches
Looks fine to me from libata side. Once it gets tested, how should
the patches be routed? I don't think it'd make sense to route them
separately.
Thanks.
--
tejun
^ permalink raw reply
* Re: [RFC PATCH] drivers: ata: Add [save|restore]_initial_config override functions
From: Tejun Heo @ 2017-03-16 21:30 UTC (permalink / raw)
To: Anurag Kumar Vulisha
Cc: Hans de Goede, anirudh, linux-ide, linux-kernel,
Anurag Kumar Vulisha
In-Reply-To: <1489492761-815-1-git-send-email-anuragku@xilinx.com>
On Tue, Mar 14, 2017 at 05:29:21PM +0530, Anurag Kumar Vulisha wrote:
> @@ -613,7 +613,10 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
> "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
> }
>
> - ahci_save_initial_config(&pdev->dev, hpriv);
> + if (hpriv->save_initial_config == NULL)
> + ahci_save_initial_config(dev, hpriv);
> + else
> + hpriv->save_initial_config(dev, hpriv);
Can you just initialize hpriv->save_initial_config to
ahci_save_initial_config and let the init function override it as
necessary?
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH] pata_pcmcia: add EBSA110's PCMCIA slot support
From: Tejun Heo @ 2017-03-16 21:26 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz
Cc: Sergei Shtylyov, Arnd Bergmann, Dmitry Eremin-Solenikov,
Kevin Hilman, Sekhar Nori, linux-kernel, linux-ide, Russell King,
Olof Johansson, linux-arm-kernel
In-Reply-To: <3458240.9SL7iGif3L@amdc3058>
Hello,
On Tue, Mar 14, 2017 at 06:50:43PM +0100, Bartlomiej Zolnierkiewicz wrote:
> +static struct ata_port_operations pcmcia_ebsa110_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .sff_dev_select = pmcmia_ebsa110_dev_select,
^^^^^^
> + .sff_set_devctl = pcmcia_ebsa110_set_devctl,
> + .sff_check_status = pcmcia_ebsa110_check_status,
> + .sff_check_altstatus = pcmcia_ebsa110_check_altstatus,
> + .sff_tf_load = pcmcia_ebsa110_tf_load,
> + .sff_tf_read = pcmcia_ebsa110_tf_read,
> + .sff_exec_command = pcmcia_ebsa110_exec_command,
> + .sff_data_xfer = ata_sff_data_xfer_noirq,
> + .softreset = pata_pcmcia_ebsa110_softreset,
> + .cable_detect = ata_cable_40wire,
> + .set_mode = pcmcia_set_mode,
> +};
Heh, that's a fat driver for a sff device. I suppose this is mostly
copied from the matching ide driver but it'd be nice to explain why it
needs duplicate most standard functions. Is it because PCMCIA
assigned address doesn't fall under the usual read/io boundary on the
arch?
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH v2] pata: remove the at91 driver
From: Tejun Heo @ 2017-03-16 21:11 UTC (permalink / raw)
To: Boris Brezillon
Cc: Bartlomiej Zolnierkiewicz, Nicolas Ferre, linux-kernel, linux-ide,
Alexandre Belloni, linux-arm-kernel
In-Reply-To: <1489585151-16415-1-git-send-email-boris.brezillon@free-electrons.com>
On Wed, Mar 15, 2017 at 02:39:11PM +0100, Boris Brezillon wrote:
> This driver is orphan since commit b2026f708e09 ("ARM: at91: remove
> at91sam9260/at91sam9g20 legacy board support"). Given that nobody cared
> adding DT support to it, it probably means it's no longer used and is
> thus a good candidate for removal.
>
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Applied to libata/for-4.12.
Thanks.
--
tejun
^ permalink raw reply
* [PATCH v2] pata: remove the at91 driver
From: Boris Brezillon @ 2017-03-15 13:39 UTC (permalink / raw)
To: Tejun Heo, Bartlomiej Zolnierkiewicz, linux-ide
Cc: Alexandre Belloni, Nicolas Ferre, linux-kernel, linux-arm-kernel,
Boris Brezillon
This driver is orphan since commit b2026f708e09 ("ARM: at91: remove
at91sam9260/at91sam9g20 legacy board support"). Given that nobody cared
adding DT support to it, it probably means it's no longer used and is
thus a good candidate for removal.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
---
Note that I'm removing this driver because I plan to rework the macro
definitions in atmel-smc.h, and some of them are used in this driver.
Since I can't test it, and this drivers is not used anymore, it's probably
better to remove it.
Changes since v1:
- add Bartlomiej's and Nicolas' ack
- fix the commit id/message that made the pata_at91 driver orphan
---
drivers/ata/Kconfig | 8 -
drivers/ata/Makefile | 1 -
drivers/ata/pata_at91.c | 503 ------------------------------------------------
3 files changed, 512 deletions(-)
delete mode 100644 drivers/ata/pata_at91.c
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 70b57d2229d6..3c878d64449c 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -885,14 +885,6 @@ config PATA_AT32
If unsure, say N.
-config PATA_AT91
- tristate "PATA support for AT91SAM9260"
- depends on ARM && SOC_AT91SAM9
- help
- This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
-
- If unsure, say N.
-
config PATA_CMD640_PCI
tristate "CMD640 PCI PATA support (Experimental)"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 89a0a1915d36..e29feb16bda1 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -91,7 +91,6 @@ obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
# SFF PIO only
obj-$(CONFIG_PATA_AT32) += pata_at32.o
-obj-$(CONFIG_PATA_AT91) += pata_at91.o
obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o
obj-$(CONFIG_PATA_FALCON) += pata_falcon.o
obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
deleted file mode 100644
index fd5b34f0d007..000000000000
--- a/drivers/ata/pata_at91.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * PATA driver for AT91SAM9260 Static Memory Controller
- * with CompactFlash interface in True IDE mode
- *
- * Copyright (C) 2009 Matyukevich Sergey
- * 2011 Igor Plyatov
- *
- * Based on:
- * * generic platform driver by Paul Mundt: drivers/ata/pata_platform.c
- * * pata_at32 driver by Kristoffer Nyborg Gregertsen
- * * at91_ide driver by Stanislaw Gruszka
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/blkdev.h>
-#include <linux/gfp.h>
-#include <scsi/scsi_host.h>
-#include <linux/ata.h>
-#include <linux/clk.h>
-#include <linux/libata.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/atmel-smc.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/platform_data/atmel.h>
-#include <linux/regmap.h>
-#include <linux/gpio.h>
-
-#define DRV_NAME "pata_at91"
-#define DRV_VERSION "0.3"
-
-#define CF_IDE_OFFSET 0x00c00000
-#define CF_ALT_IDE_OFFSET 0x00e00000
-#define CF_IDE_RES_SIZE 0x08
-#define CS_PULSE_MAXIMUM 319
-#define ER_SMC_CALC 1
-#define ER_SMC_RECALC 2
-
-struct at91_ide_info {
- unsigned long mode;
- unsigned int cs;
- struct clk *mck;
- void __iomem *ide_addr;
- void __iomem *alt_addr;
-};
-
-/**
- * struct smc_range - range of valid values for SMC register.
- */
-struct smc_range {
- int min;
- int max;
-};
-
-struct regmap *smc;
-
-struct at91sam9_smc_generic_fields {
- struct regmap_field *setup;
- struct regmap_field *pulse;
- struct regmap_field *cycle;
- struct regmap_field *mode;
-} fields;
-
-/**
- * adjust_smc_value - adjust value for one of SMC registers.
- * @value: adjusted value
- * @range: array of SMC ranges with valid values
- * @size: SMC ranges array size
- *
- * This returns the difference between input and output value or negative
- * in case of invalid input value.
- * If negative returned, then output value = maximal possible from ranges.
- */
-static int adjust_smc_value(int *value, struct smc_range *range, int size)
-{
- int maximum = (range + size - 1)->max;
- int remainder;
-
- do {
- if (*value < range->min) {
- remainder = range->min - *value;
- *value = range->min; /* nearest valid value */
- return remainder;
- } else if ((range->min <= *value) && (*value <= range->max))
- return 0;
-
- range++;
- } while (--size);
- *value = maximum;
-
- return -1; /* invalid value */
-}
-
-/**
- * calc_smc_vals - calculate SMC register values
- * @dev: ATA device
- * @setup: SMC_SETUP register value
- * @pulse: SMC_PULSE register value
- * @cycle: SMC_CYCLE register value
- *
- * This returns negative in case of invalid values for SMC registers:
- * -ER_SMC_RECALC - recalculation required for SMC values,
- * -ER_SMC_CALC - calculation failed (invalid input values).
- *
- * SMC use special coding scheme, see "Coding and Range of Timing
- * Parameters" table from AT91SAM9 datasheets.
- *
- * SMC_SETUP = 128*setup[5] + setup[4:0]
- * SMC_PULSE = 256*pulse[6] + pulse[5:0]
- * SMC_CYCLE = 256*cycle[8:7] + cycle[6:0]
- */
-static int calc_smc_vals(struct device *dev,
- int *setup, int *pulse, int *cycle, int *cs_pulse)
-{
- int ret_val;
- int err = 0;
- struct smc_range range_setup[] = { /* SMC_SETUP valid values */
- {.min = 0, .max = 31}, /* first range */
- {.min = 128, .max = 159} /* second range */
- };
- struct smc_range range_pulse[] = { /* SMC_PULSE valid values */
- {.min = 0, .max = 63}, /* first range */
- {.min = 256, .max = 319} /* second range */
- };
- struct smc_range range_cycle[] = { /* SMC_CYCLE valid values */
- {.min = 0, .max = 127}, /* first range */
- {.min = 256, .max = 383}, /* second range */
- {.min = 512, .max = 639}, /* third range */
- {.min = 768, .max = 895} /* fourth range */
- };
-
- ret_val = adjust_smc_value(setup, range_setup, ARRAY_SIZE(range_setup));
- if (ret_val < 0)
- dev_warn(dev, "maximal SMC Setup value\n");
- else
- *cycle += ret_val;
-
- ret_val = adjust_smc_value(pulse, range_pulse, ARRAY_SIZE(range_pulse));
- if (ret_val < 0)
- dev_warn(dev, "maximal SMC Pulse value\n");
- else
- *cycle += ret_val;
-
- ret_val = adjust_smc_value(cycle, range_cycle, ARRAY_SIZE(range_cycle));
- if (ret_val < 0)
- dev_warn(dev, "maximal SMC Cycle value\n");
-
- *cs_pulse = *cycle;
- if (*cs_pulse > CS_PULSE_MAXIMUM) {
- dev_err(dev, "unable to calculate valid SMC settings\n");
- return -ER_SMC_CALC;
- }
-
- ret_val = adjust_smc_value(cs_pulse, range_pulse,
- ARRAY_SIZE(range_pulse));
- if (ret_val < 0) {
- dev_warn(dev, "maximal SMC CS Pulse value\n");
- } else if (ret_val != 0) {
- *cycle = *cs_pulse;
- dev_warn(dev, "SMC Cycle extended\n");
- err = -ER_SMC_RECALC;
- }
-
- return err;
-}
-
-/**
- * to_smc_format - convert values into SMC format
- * @setup: SETUP value of SMC Setup Register
- * @pulse: PULSE value of SMC Pulse Register
- * @cycle: CYCLE value of SMC Cycle Register
- * @cs_pulse: NCS_PULSE value of SMC Pulse Register
- */
-static void to_smc_format(int *setup, int *pulse, int *cycle, int *cs_pulse)
-{
- *setup = (*setup & 0x1f) | ((*setup & 0x80) >> 2);
- *pulse = (*pulse & 0x3f) | ((*pulse & 0x100) >> 2);
- *cycle = (*cycle & 0x7f) | ((*cycle & 0x300) >> 1);
- *cs_pulse = (*cs_pulse & 0x3f) | ((*cs_pulse & 0x100) >> 2);
-}
-
-static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
-{
- unsigned long mul;
-
- /*
- * cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] =
- * x * (f / 1_000_000_000) =
- * x * ((f * 65536) / 1_000_000_000) / 65536 =
- * x * (((f / 10_000) * 65536) / 100_000) / 65536 =
- */
-
- mul = (mck_hz / 10000) << 16;
- mul /= 100000;
-
- return (ns * mul + 65536) >> 16; /* rounding */
-}
-
-/**
- * set_smc_timing - SMC timings setup.
- * @dev: device
- * @info: AT91 IDE info
- * @ata: ATA timings
- *
- * Its assumed that write timings are same as read timings,
- * cs_setup = 0 and cs_pulse = cycle.
- */
-static void set_smc_timing(struct device *dev, struct ata_device *adev,
- struct at91_ide_info *info, const struct ata_timing *ata)
-{
- int ret = 0;
- int use_iordy;
- unsigned int t6z; /* data tristate time in ns */
- unsigned int cycle; /* SMC Cycle width in MCK ticks */
- unsigned int setup; /* SMC Setup width in MCK ticks */
- unsigned int pulse; /* CFIOR and CFIOW pulse width in MCK ticks */
- unsigned int cs_pulse; /* CS4 or CS5 pulse width in MCK ticks*/
- unsigned int tdf_cycles; /* SMC TDF MCK ticks */
- unsigned long mck_hz; /* MCK frequency in Hz */
-
- t6z = (ata->mode < XFER_PIO_5) ? 30 : 20;
- mck_hz = clk_get_rate(info->mck);
- cycle = calc_mck_cycles(ata->cyc8b, mck_hz);
- setup = calc_mck_cycles(ata->setup, mck_hz);
- pulse = calc_mck_cycles(ata->act8b, mck_hz);
- tdf_cycles = calc_mck_cycles(t6z, mck_hz);
-
- do {
- ret = calc_smc_vals(dev, &setup, &pulse, &cycle, &cs_pulse);
- } while (ret == -ER_SMC_RECALC);
-
- if (ret == -ER_SMC_CALC)
- dev_err(dev, "Interface may not operate correctly\n");
-
- dev_dbg(dev, "SMC Setup=%u, Pulse=%u, Cycle=%u, CS Pulse=%u\n",
- setup, pulse, cycle, cs_pulse);
- to_smc_format(&setup, &pulse, &cycle, &cs_pulse);
- /* disable or enable waiting for IORDY signal */
- use_iordy = ata_pio_need_iordy(adev);
- if (use_iordy)
- info->mode |= AT91_SMC_EXNWMODE_READY;
-
- if (tdf_cycles > 15) {
- tdf_cycles = 15;
- dev_warn(dev, "maximal SMC TDF Cycles value\n");
- }
-
- dev_dbg(dev, "Use IORDY=%u, TDF Cycles=%u\n", use_iordy, tdf_cycles);
-
- regmap_fields_write(fields.setup, info->cs,
- AT91SAM9_SMC_NRDSETUP(setup) |
- AT91SAM9_SMC_NWESETUP(setup) |
- AT91SAM9_SMC_NCS_NRDSETUP(0) |
- AT91SAM9_SMC_NCS_WRSETUP(0));
- regmap_fields_write(fields.pulse, info->cs,
- AT91SAM9_SMC_NRDPULSE(pulse) |
- AT91SAM9_SMC_NWEPULSE(pulse) |
- AT91SAM9_SMC_NCS_NRDPULSE(cs_pulse) |
- AT91SAM9_SMC_NCS_WRPULSE(cs_pulse));
- regmap_fields_write(fields.cycle, info->cs,
- AT91SAM9_SMC_NRDCYCLE(cycle) |
- AT91SAM9_SMC_NWECYCLE(cycle));
- regmap_fields_write(fields.mode, info->cs, info->mode |
- AT91_SMC_TDF_(tdf_cycles));
-}
-
-static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct at91_ide_info *info = ap->host->private_data;
- struct ata_timing timing;
- int ret;
-
- /* Compute ATA timing and set it to SMC */
- ret = ata_timing_compute(adev, adev->pio_mode, &timing, 1000, 0);
- if (ret) {
- dev_warn(ap->dev, "Failed to compute ATA timing %d, "
- "set PIO_0 timing\n", ret);
- timing = *ata_timing_find_mode(XFER_PIO_0);
- }
- set_smc_timing(ap->dev, adev, info, &timing);
-}
-
-static unsigned int pata_at91_data_xfer_noirq(struct ata_queued_cmd *qc,
- unsigned char *buf, unsigned int buflen, int rw)
-{
- struct at91_ide_info *info = qc->dev->link->ap->host->private_data;
- unsigned int consumed;
- unsigned int mode;
- unsigned long flags;
-
- local_irq_save(flags);
- regmap_fields_read(fields.mode, info->cs, &mode);
-
- /* set 16bit mode before writing data */
- regmap_fields_write(fields.mode, info->cs, (mode & ~AT91_SMC_DBW) |
- AT91_SMC_DBW_16);
-
- consumed = ata_sff_data_xfer(qc, buf, buflen, rw);
-
- /* restore 8bit mode after data is written */
- regmap_fields_write(fields.mode, info->cs, (mode & ~AT91_SMC_DBW) |
- AT91_SMC_DBW_8);
-
- local_irq_restore(flags);
- return consumed;
-}
-
-static struct scsi_host_template pata_at91_sht = {
- ATA_PIO_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations pata_at91_port_ops = {
- .inherits = &ata_sff_port_ops,
-
- .sff_data_xfer = pata_at91_data_xfer_noirq,
- .set_piomode = pata_at91_set_piomode,
- .cable_detect = ata_cable_40wire,
-};
-
-static int at91sam9_smc_fields_init(struct device *dev)
-{
- struct reg_field field = REG_FIELD(0, 0, 31);
-
- field.id_size = 8;
- field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ;
-
- field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC);
- fields.setup = devm_regmap_field_alloc(dev, smc, field);
- if (IS_ERR(fields.setup))
- return PTR_ERR(fields.setup);
-
- field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC);
- fields.pulse = devm_regmap_field_alloc(dev, smc, field);
- if (IS_ERR(fields.pulse))
- return PTR_ERR(fields.pulse);
-
- field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC);
- fields.cycle = devm_regmap_field_alloc(dev, smc, field);
- if (IS_ERR(fields.cycle))
- return PTR_ERR(fields.cycle);
-
- field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC);
- fields.mode = devm_regmap_field_alloc(dev, smc, field);
-
- return PTR_ERR_OR_ZERO(fields.mode);
-}
-
-static int pata_at91_probe(struct platform_device *pdev)
-{
- struct at91_cf_data *board = dev_get_platdata(&pdev->dev);
- struct device *dev = &pdev->dev;
- struct at91_ide_info *info;
- struct resource *mem_res;
- struct ata_host *host;
- struct ata_port *ap;
-
- int irq_flags = 0;
- int irq = 0;
- int ret;
-
- /* get platform resources: IO/CTL memories and irq/rst pins */
-
- if (pdev->num_resources != 1) {
- dev_err(&pdev->dev, "invalid number of resources\n");
- return -EINVAL;
- }
-
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- if (!mem_res) {
- dev_err(dev, "failed to get mem resource\n");
- return -EINVAL;
- }
-
- irq = board->irq_pin;
-
- smc = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "atmel,smc");
- if (IS_ERR(smc))
- return PTR_ERR(smc);
-
- ret = at91sam9_smc_fields_init(dev);
- if (ret < 0)
- return ret;
-
- /* init ata host */
-
- host = ata_host_alloc(dev, 1);
-
- if (!host)
- return -ENOMEM;
-
- ap = host->ports[0];
- ap->ops = &pata_at91_port_ops;
- ap->flags |= ATA_FLAG_SLAVE_POSS;
- ap->pio_mask = ATA_PIO4;
-
- if (!gpio_is_valid(irq)) {
- ap->flags |= ATA_FLAG_PIO_POLLING;
- ata_port_desc(ap, "no IRQ, using PIO polling");
- }
-
- info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
-
- if (!info) {
- dev_err(dev, "failed to allocate memory for private data\n");
- return -ENOMEM;
- }
-
- info->mck = clk_get(NULL, "mck");
-
- if (IS_ERR(info->mck)) {
- dev_err(dev, "failed to get access to mck clock\n");
- return -ENODEV;
- }
-
- info->cs = board->chipselect;
- info->mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
- AT91_SMC_EXNWMODE_READY | AT91_SMC_BAT_SELECT |
- AT91_SMC_DBW_8 | AT91_SMC_TDF_(0);
-
- info->ide_addr = devm_ioremap(dev,
- mem_res->start + CF_IDE_OFFSET, CF_IDE_RES_SIZE);
-
- if (!info->ide_addr) {
- dev_err(dev, "failed to map IO base\n");
- ret = -ENOMEM;
- goto err_put;
- }
-
- info->alt_addr = devm_ioremap(dev,
- mem_res->start + CF_ALT_IDE_OFFSET, CF_IDE_RES_SIZE);
-
- if (!info->alt_addr) {
- dev_err(dev, "failed to map CTL base\n");
- ret = -ENOMEM;
- goto err_put;
- }
-
- ap->ioaddr.cmd_addr = info->ide_addr;
- ap->ioaddr.ctl_addr = info->alt_addr + 0x06;
- ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
-
- ata_sff_std_ports(&ap->ioaddr);
-
- ata_port_desc(ap, "mmio cmd 0x%llx ctl 0x%llx",
- (unsigned long long)mem_res->start + CF_IDE_OFFSET,
- (unsigned long long)mem_res->start + CF_ALT_IDE_OFFSET);
-
- host->private_data = info;
-
- ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
- gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
- irq_flags, &pata_at91_sht);
- if (ret)
- goto err_put;
-
- return 0;
-
-err_put:
- clk_put(info->mck);
- return ret;
-}
-
-static int pata_at91_remove(struct platform_device *pdev)
-{
- struct ata_host *host = platform_get_drvdata(pdev);
- struct at91_ide_info *info;
-
- if (!host)
- return 0;
- info = host->private_data;
-
- ata_host_detach(host);
-
- if (!info)
- return 0;
-
- clk_put(info->mck);
-
- return 0;
-}
-
-static struct platform_driver pata_at91_driver = {
- .probe = pata_at91_probe,
- .remove = pata_at91_remove,
- .driver = {
- .name = DRV_NAME,
- },
-};
-
-module_platform_driver(pata_at91_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Driver for CF in True IDE mode on AT91SAM9260 SoC");
-MODULE_AUTHOR("Matyukevich Sergey");
-MODULE_VERSION(DRV_VERSION);
-
--
2.7.4
^ permalink raw reply related
* (unknown),
From: beautyink @ 2017-03-15 3:58 UTC (permalink / raw)
To: linux-ide
[-- Attachment #1: EMAIL_2088089_linux-ide.zip --]
[-- Type: application/zip, Size: 4573 bytes --]
^ permalink raw reply
* [GIT PULL] libata changes for v4.11-rc2
From: Tejun Heo @ 2017-03-14 20:57 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-ide
Hello,
Three libata fixes.
* Fix for a circular reference bug in sysfs code which prevented
pata_legacy devices from being released after probe failure, which
in turn prevented devres from releasing the associated resources.
* Drop spurious WARN in the command issue path which can be triggered
by a legitimate passthrough command.
* A ahci_qoriq specific fix.
Thanks.
The following changes since commit c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201:
Linux 4.11-rc1 (2017-03-05 12:59:56 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git for-4.11-fixes
for you to fetch changes up to 6022c5cadf1a43ca30f431f128daa6163909ad60:
ahci: qoriq: correct the sata ecc setting error (2017-03-09 11:55:23 -0500)
----------------------------------------------------------------
Gwendal Grignou (1):
libata: transport: Remove circular dependency at free time
Tejun Heo (1):
libata: drop WARN from protocol error in ata_sff_qc_issue()
Yuantian Tang (1):
ahci: qoriq: correct the sata ecc setting error
drivers/ata/ahci_qoriq.c | 6 ++++--
drivers/ata/libata-sff.c | 1 -
drivers/ata/libata-transport.c | 9 +++------
3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 85d8332..4c96f3a 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -177,7 +177,8 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
case AHCI_LS1043A:
if (!qpriv->ecc_addr)
return -EINVAL;
- writel(ECC_DIS_ARMV8_CH2, qpriv->ecc_addr);
+ writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
+ qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
@@ -194,7 +195,8 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
case AHCI_LS1046A:
if (!qpriv->ecc_addr)
return -EINVAL;
- writel(ECC_DIS_ARMV8_CH2, qpriv->ecc_addr);
+ writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
+ qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 2bd92dc..274d6d7 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1482,7 +1482,6 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
break;
default:
- WARN_ON_ONCE(1);
return AC_ERR_SYSTEM;
}
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
index 4669823..19e6e53 100644
--- a/drivers/ata/libata-transport.c
+++ b/drivers/ata/libata-transport.c
@@ -224,7 +224,6 @@ static DECLARE_TRANSPORT_CLASS(ata_port_class,
static void ata_tport_release(struct device *dev)
{
- put_device(dev->parent);
}
/**
@@ -284,7 +283,7 @@ int ata_tport_add(struct device *parent,
device_initialize(dev);
dev->type = &ata_port_type;
- dev->parent = get_device(parent);
+ dev->parent = parent;
dev->release = ata_tport_release;
dev_set_name(dev, "ata%d", ap->print_id);
transport_setup_device(dev);
@@ -348,7 +347,6 @@ static DECLARE_TRANSPORT_CLASS(ata_link_class,
static void ata_tlink_release(struct device *dev)
{
- put_device(dev->parent);
}
/**
@@ -410,7 +408,7 @@ int ata_tlink_add(struct ata_link *link)
int error;
device_initialize(dev);
- dev->parent = get_device(&ap->tdev);
+ dev->parent = &ap->tdev;
dev->release = ata_tlink_release;
if (ata_is_host_link(link))
dev_set_name(dev, "link%d", ap->print_id);
@@ -589,7 +587,6 @@ static DECLARE_TRANSPORT_CLASS(ata_dev_class,
static void ata_tdev_release(struct device *dev)
{
- put_device(dev->parent);
}
/**
@@ -662,7 +659,7 @@ static int ata_tdev_add(struct ata_device *ata_dev)
int error;
device_initialize(dev);
- dev->parent = get_device(&link->tdev);
+ dev->parent = &link->tdev;
dev->release = ata_tdev_release;
if (ata_is_host_link(link))
dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
--
tejun
^ permalink raw reply related
* [PATCH] pata_pcmcia: add EBSA110's PCMCIA slot support
From: Bartlomiej Zolnierkiewicz @ 2017-03-14 17:50 UTC (permalink / raw)
To: Russell King, Tejun Heo
Cc: Sergei Shtylyov, Sekhar Nori, Arnd Bergmann,
Dmitry Eremin-Solenikov, Kevin Hilman, Olof Johansson, linux-ide,
linux-arm-kernel, linux-kernel, b.zolnierkie
In-Reply-To: <CGME20170314175046epcas1p43f98daad14a2bac7f314e7d39e120232@epcas1p4.samsung.com>
Add EBSA110's PCMCIA slot support.
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
Cross compile tested only.
drivers/ata/pata_pcmcia.c | 297 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 294 insertions(+), 3 deletions(-)
Index: b/drivers/ata/pata_pcmcia.c
===================================================================
--- a/drivers/ata/pata_pcmcia.c 2017-03-14 18:32:21.667263033 +0100
+++ b/drivers/ata/pata_pcmcia.c 2017-03-14 18:41:48.995277320 +0100
@@ -164,6 +164,286 @@ static struct ata_port_operations pcmcia
.sff_drain_fifo = pcmcia_8bit_drain_fifo,
};
+#ifdef CONFIG_ARCH_EBSA110
+static void pmcmia_ebsa110_dev_select(struct ata_port *ap, unsigned int device)
+{
+ u8 tmp;
+
+ if (device == 0)
+ tmp = ATA_DEVICE_OBS;
+ else
+ tmp = ATA_DEVICE_OBS | ATA_DEV1;
+
+ __outb16(tmp, (unsigned long)ap->ioaddr.device_addr);
+ ata_sff_pause(ap); /* needed; also flushes, for mmio */
+}
+
+static void pcmcia_ebsa110_set_devctl(struct ata_port *ap, u8 ctl)
+{
+ __outb16(ctl, (unsigned long)ap->ioaddr.ctl_addr);
+}
+
+static u8 pcmcia_ebsa110_check_status(struct ata_port *ap)
+{
+ return __inb16((unsigned long)ap->ioaddr.status_addr);
+}
+
+static u8 pcmcia_ebsa110_check_altstatus(struct ata_port *ap)
+{
+ return __inb16((unsigned long)ap->ioaddr.altstatus_addr);
+}
+
+static void pcmcia_ebsa110_tf_load(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+ if (tf->ctl != ap->last_ctl) {
+ if (ioaddr->ctl_addr)
+ __outb16(tf->ctl, (unsigned long)ioaddr->ctl_addr);
+ ap->last_ctl = tf->ctl;
+ ata_wait_idle(ap);
+ }
+
+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ WARN_ON_ONCE(!ioaddr->ctl_addr);
+ __outb16(tf->hob_feature, (unsigned long)ioaddr->feature_addr);
+ __outb16(tf->hob_nsect, (unsigned long)ioaddr->nsect_addr);
+ __outb16(tf->hob_lbal, (unsigned long)ioaddr->lbal_addr);
+ __outb16(tf->hob_lbam, (unsigned long)ioaddr->lbam_addr);
+ __outb16(tf->hob_lbah, (unsigned long)ioaddr->lbah_addr);
+ VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+ tf->hob_feature,
+ tf->hob_nsect,
+ tf->hob_lbal,
+ tf->hob_lbam,
+ tf->hob_lbah);
+ }
+
+ if (is_addr) {
+ __outb16(tf->feature, (unsigned long)ioaddr->feature_addr);
+ __outb16(tf->nsect, (unsigned long)ioaddr->nsect_addr);
+ __outb16(tf->lbal, (unsigned long)ioaddr->lbal_addr);
+ __outb16(tf->lbam, (unsigned long)ioaddr->lbam_addr);
+ __outb16(tf->lbah, (unsigned long)ioaddr->lbah_addr);
+ VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+ tf->feature,
+ tf->nsect,
+ tf->lbal,
+ tf->lbam,
+ tf->lbah);
+ }
+
+ if (tf->flags & ATA_TFLAG_DEVICE) {
+ __outb16(tf->device, (unsigned long)ioaddr->device_addr);
+ VPRINTK("device 0x%X\n", tf->device);
+ }
+
+ ata_wait_idle(ap);
+}
+
+static void pcmcia_ebsa110_tf_read(struct ata_port *ap,
+ struct ata_taskfile *tf)
+{
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ tf->command = ata_sff_check_status(ap);
+ tf->feature = __inb16((unsigned long)ioaddr->error_addr);
+ tf->nsect = __inb16((unsigned long)ioaddr->nsect_addr);
+ tf->lbal = __inb16((unsigned long)ioaddr->lbal_addr);
+ tf->lbam = __inb16((unsigned long)ioaddr->lbam_addr);
+ tf->lbah = __inb16((unsigned long)ioaddr->lbah_addr);
+ tf->device = __inb16((unsigned long)ioaddr->device_addr);
+
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ if (likely(ioaddr->ctl_addr)) {
+ __outb16(tf->ctl | ATA_HOB, (unsigned long)ioaddr->ctl_addr);
+ tf->hob_feature = __inb16((unsigned long)ioaddr->error_addr);
+ tf->hob_nsect = __inb16((unsigned long)ioaddr->nsect_addr);
+ tf->hob_lbal = __inb16((unsigned long)ioaddr->lbal_addr);
+ tf->hob_lbam = __inb16((unsigned long)ioaddr->lbam_addr);
+ tf->hob_lbah = __inb16((unsigned long)ioaddr->lbah_addr);
+ __outb16(tf->ctl, (unsigned long)ioaddr->ctl_addr);
+ ap->last_ctl = tf->ctl;
+ } else
+ WARN_ON_ONCE(1);
+ }
+}
+
+static void pcmcia_ebsa110_exec_command(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+
+ __outb16(tf->command, (unsigned long)ap->ioaddr.command_addr);
+ ata_sff_pause(ap);
+}
+
+static unsigned int pata_pcmcia_ebsa110_devchk(struct ata_port *ap,
+ unsigned int device)
+{
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ u8 nsect, lbal;
+
+ ap->ops->sff_dev_select(ap, device);
+
+ __outb16(0x55, (unsigned long)ioaddr->nsect_addr);
+ __outb16(0xaa, (unsigned long)ioaddr->lbal_addr);
+
+ __outb16(0xaa, (unsigned long)ioaddr->nsect_addr);
+ __outb16(0x55, (unsigned long)ioaddr->lbal_addr);
+
+ __outb16(0x55, (unsigned long)ioaddr->nsect_addr);
+ __outb16(0xaa, (unsigned long)ioaddr->lbal_addr);
+
+ nsect = __inb16((unsigned long)ioaddr->nsect_addr);
+ lbal = __inb16((unsigned long)ioaddr->lbal_addr);
+
+ if ((nsect == 0x55) && (lbal == 0xaa))
+ return 1; /* we found a device */
+
+ return 0; /* nothing found */
+}
+
+static int pata_pcmcia_ebsa110_wait_after_reset(struct ata_link *link,
+ unsigned int devmask,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned int dev0 = devmask & (1 << 0);
+ unsigned int dev1 = devmask & (1 << 1);
+ int rc, ret = 0;
+
+ ata_msleep(ap, ATA_WAIT_AFTER_RESET);
+
+ /* always check readiness of the master device */
+ rc = ata_sff_wait_ready(link, deadline);
+ /* -ENODEV means the odd clown forgot the D7 pulldown resistor
+ * and TF status is 0xff, bail out on it too.
+ */
+ if (rc)
+ return rc;
+
+ /* if device 1 was found in ata_devchk, wait for register
+ * access briefly, then wait for BSY to clear.
+ */
+ if (dev1) {
+ int i;
+
+ ap->ops->sff_dev_select(ap, 1);
+
+ /* Wait for register access. Some ATAPI devices fail
+ * to set nsect/lbal after reset, so don't waste too
+ * much time on it. We're gonna wait for !BSY anyway.
+ */
+ for (i = 0; i < 2; i++) {
+ u8 nsect, lbal;
+
+ nsect = __inb16((unsigned long)ioaddr->nsect_addr);
+ lbal = __inb16((unsigned long)ioaddr->lbal_addr);
+ if ((nsect == 1) && (lbal == 1))
+ break;
+ ata_msleep(ap, 50); /* give drive a breather */
+ }
+
+ rc = ata_sff_wait_ready(link, deadline);
+ if (rc) {
+ if (rc != -ENODEV)
+ return rc;
+ ret = rc;
+ }
+ }
+
+ /* is all this really necessary? */
+ ap->ops->sff_dev_select(ap, 0);
+ if (dev1)
+ ap->ops->sff_dev_select(ap, 1);
+ if (dev0)
+ ap->ops->sff_dev_select(ap, 0);
+
+ return ret;
+}
+
+static int pata_pcmcia_ebsa110_bus_softreset(struct ata_port *ap,
+ unsigned int devmask,
+ unsigned long deadline)
+{
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
+
+ /* software reset. causes dev0 to be selected */
+ __outb16(ap->ctl, (unsigned long)ioaddr->ctl_addr);
+ udelay(20); /* FIXME: flush */
+ __outb16(ap->ctl | ATA_SRST, (unsigned long)ioaddr->ctl_addr);
+ udelay(20); /* FIXME: flush */
+ __outb16(ap->ctl, (unsigned long)ioaddr->ctl_addr);
+ ap->last_ctl = ap->ctl;
+
+ /* wait the port to become ready */
+ return pata_pcmcia_ebsa110_wait_after_reset(&ap->link, devmask,
+ deadline);
+}
+
+static int pata_pcmcia_ebsa110_softreset(struct ata_link *link,
+ unsigned int *classes,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+ unsigned int devmask = 0;
+ int rc;
+ u8 err;
+
+ DPRINTK("ENTER\n");
+
+ /* determine if device 0/1 are present */
+ if (pata_pcmcia_ebsa110_devchk(ap, 0))
+ devmask |= (1 << 0);
+ if (slave_possible && pata_pcmcia_ebsa110_devchk(ap, 1))
+ devmask |= (1 << 1);
+
+ /* select device 0 again */
+ ap->ops->sff_dev_select(ap, 0);
+
+ /* issue bus reset */
+ DPRINTK("about to softreset, devmask=%x\n", devmask);
+ rc = pata_pcmcia_ebsa110_bus_softreset(ap, devmask, deadline);
+ /* if link is occupied, -ENODEV too is an error */
+ if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
+ ata_link_err(link, "SRST failed (errno=%d)\n", rc);
+ return rc;
+ }
+
+ /* determine by signature whether we have ATA or ATAPI devices */
+ classes[0] = ata_sff_dev_classify(&link->device[0],
+ devmask & (1 << 0), &err);
+ if (slave_possible && err != 0x81)
+ classes[1] = ata_sff_dev_classify(&link->device[1],
+ devmask & (1 << 1), &err);
+
+ DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+ return 0;
+}
+
+static struct ata_port_operations pcmcia_ebsa110_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_dev_select = pmcmia_ebsa110_dev_select,
+ .sff_set_devctl = pcmcia_ebsa110_set_devctl,
+ .sff_check_status = pcmcia_ebsa110_check_status,
+ .sff_check_altstatus = pcmcia_ebsa110_check_altstatus,
+ .sff_tf_load = pcmcia_ebsa110_tf_load,
+ .sff_tf_read = pcmcia_ebsa110_tf_read,
+ .sff_exec_command = pcmcia_ebsa110_exec_command,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .softreset = pata_pcmcia_ebsa110_softreset,
+ .cable_detect = ata_cable_40wire,
+ .set_mode = pcmcia_set_mode,
+};
+#include <asm/mach-types.h>
+#endif
static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
{
@@ -242,9 +522,20 @@ static int pcmcia_init_one(struct pcmcia
goto failed;
/* Success. Disable the IRQ nIEN line, do quirks */
- iowrite8(0x02, ctl_addr);
- if (is_kme)
- iowrite8(0x81, ctl_addr + 0x01);
+#ifdef CONFIG_ARCH_EBSA110
+ if (machine_is_ebsa110()) {
+ ops = &pcmcia_ebsa110_port_ops;
+
+ __outb16(0x02, (unsigned long)ctl_addr);
+ if (is_kme)
+ __outb16(0x81, (unsigned long)ctl_addr + 0x01);
+ } else
+#endif
+ {
+ iowrite8(0x02, ctl_addr);
+ if (is_kme)
+ iowrite8(0x81, ctl_addr + 0x01);
+ }
/* FIXME: Could be more ports at base + 0x10 but we only deal with
one right now */
^ permalink raw reply
* Re: [PATCH 2/2] ata: ahci: add support for DaVinci DM816 SATA controller
From: Kevin Hilman @ 2017-03-14 17:03 UTC (permalink / raw)
To: Neil Armstrong
Cc: Sergei Shtylyov, Bartosz Golaszewski, Tejun Heo, Rob Herring,
Mark Rutland, Michael Turquette, Patrick Titiano, linux-ide,
devicetree, linux-kernel
In-Reply-To: <7ab4b440-f9d0-22fa-f463-f4c5542e21e7@baylibre.com>
Neil Armstrong <narmstrong@baylibre.com> writes:
> On 03/14/2017 09:57 AM, Sergei Shtylyov wrote:
>> Hello!
>>
>> On 3/13/2017 7:36 PM, Bartosz Golaszewski wrote:
>>
>>> This SATA controller is quite similar to the one present on the DA850
>>> SoC, but the PHY configuration is different and it supports two HBA
>>> ports.
>>>
>>> The IP suffers from the same PMP issue the DA850 does - if we enable
>>> PMP but don't use it - softreset fails. Appropriate workaround was
>>> implemented in this driver as well.
>>>
>>> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>> ---
>>> drivers/ata/Kconfig | 9 +++
>>> drivers/ata/Makefile | 1 +
>>> drivers/ata/ahci_dm816.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 210 insertions(+)
>>> create mode 100644 drivers/ata/ahci_dm816.c
>>>
>>> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
>>> index 70b57d2..7f59a7a 100644
>>> --- a/drivers/ata/Kconfig
>>> +++ b/drivers/ata/Kconfig
>>> @@ -118,6 +118,15 @@ config AHCI_DA850
>>>
>>> If unsure, say N.
>>>
>>> +config AHCI_DM816
>>> + tristate "DaVinci DM816 AHCI SATA support"
>>
>> Is it really DaVinci?
>>
>>> + depends on ARCH_OMAP2PLUS
>>
>> Especially if it depends on OMAP...
>
> Hi Sergei,
>
> Yes it's a DaVinci family SoC, but shares a lot of IPs with the OMAP family.
>
Actually, this is more of an OMAP family, which shares some IP from
DaVinci family
I think in other parts of the kernel, we refer to this as TI 816x
instead of using either DaVinci or OMAP.
Kevin
^ permalink raw reply
* [PATCH v2 3/3] ARM: davinci_all_defconfig: convert to use libata PATA
From: Bartlomiej Zolnierkiewicz @ 2017-03-14 16:36 UTC (permalink / raw)
To: Tejun Heo
Cc: Sekhar Nori, Sergei Shtylyov, Kevin Hilman, Arnd Bergmann,
Russell King, Dmitry Eremin-Solenikov, linux-ide,
linux-arm-kernel, linux-kernel, b.zolnierkie
In-Reply-To: <1489509414-11491-1-git-send-email-b.zolnierkie@samsung.com>
From: Sekhar Nori <nsekhar@ti.com>
IDE subsystem has been deprecated since 2009 and the majority
(if not all) of Linux distributions have switched to use
libata for ATA support exclusively. However there are still
some users (mostly old or/and embedded non-x86 systems) that
have not converted from using IDE subsystem to libata PATA
drivers. This doesn't seem to be good thing in the long-term
for Linux as while there is less and less PATA systems left
in use:
* testing efforts are divided between two subsystems
* having duplicate drivers for same hardware confuses users
This patch converts davinci_all_defconfig to use libata PATA
drivers.
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
[b.zolnierkie: split from bigger patch + added patch description]
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
arch/arm/configs/davinci_all_defconfig | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index c8663ea..93aab3d 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -74,12 +74,10 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_EEPROM_AT24=y
-CONFIG_IDE=m
-CONFIG_BLK_DEV_PALMCHIP_BK3710=m
-CONFIG_SCSI=m
CONFIG_BLK_DEV_SD=m
CONFIG_ATA=m
CONFIG_AHCI_DA850=m
+CONFIG_PATA_BK3710=m
CONFIG_NETDEVICES=y
CONFIG_NETCONSOLE=y
CONFIG_TUN=m
--
1.9.1
^ permalink raw reply related
* [PATCH v2 0/3] ATA/ARM: convert ARM/DaVinci to use libata PATA drivers
From: Bartlomiej Zolnierkiewicz @ 2017-03-14 16:36 UTC (permalink / raw)
To: Tejun Heo
Cc: Sekhar Nori, Sergei Shtylyov, Kevin Hilman, Arnd Bergmann,
Russell King, Dmitry Eremin-Solenikov, linux-ide,
linux-arm-kernel, linux-kernel, b.zolnierkie
In-Reply-To: <CGME20170314163738epcas5p3db719229d59550476c918a15d8c16d63@epcas5p3.samsung.com>
Hi,
This patchset adds Palmchip BK3710 IDE controller driver to
libata and switches ARM/DaVinci to use it (instead of the old
IDE driver).
Sekhar, please check that it still works after changes, thanks.
Changes since v1
(https://www.spinics.net/lists/arm-kernel/msg567442.html):
- addressed review comments from Sergei Shtylyov
- fixed cycle_time unitialized variable issue
Changes since v0.1 draft patch version
(https://www.spinics.net/lists/arm-kernel/msg566932.html):
- fixed cycle_time build warning
- added platform support fixes from Sekhar
- added defconfig changes from Sekhar
- preserved platform support for the old IDE driver
- split it on 3 patches
Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics
Bartlomiej Zolnierkiewicz (1):
ata: add Palmchip BK3710 PATA controller driver
Sekhar Nori (2):
ARM: davinci: add pata_bk3710 libata driver support
ARM: davinci_all_defconfig: convert to use libata PATA
arch/arm/configs/davinci_all_defconfig | 4 +-
arch/arm/mach-davinci/board-dm644x-evm.c | 3 +-
arch/arm/mach-davinci/board-dm646x-evm.c | 3 +-
arch/arm/mach-davinci/board-neuros-osd2.c | 3 +-
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1 +
drivers/ata/pata_bk3710.c | 386 ++++++++++++++++++++++++++++++
7 files changed, 403 insertions(+), 6 deletions(-)
create mode 100644 drivers/ata/pata_bk3710.c
--
1.9.1
^ permalink raw reply
* [PATCH v2 2/3] ARM: davinci: add pata_bk3710 libata driver support
From: Bartlomiej Zolnierkiewicz @ 2017-03-14 16:36 UTC (permalink / raw)
To: Tejun Heo
Cc: Sekhar Nori, Sergei Shtylyov, Kevin Hilman, Arnd Bergmann,
Russell King, Dmitry Eremin-Solenikov, linux-ide,
linux-arm-kernel, linux-kernel, b.zolnierkie
In-Reply-To: <1489509414-11491-1-git-send-email-b.zolnierkie@samsung.com>
From: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
[b.zolnierkie: split from bigger patch + preserved old driver support]
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
arch/arm/mach-davinci/board-dm644x-evm.c | 3 ++-
arch/arm/mach-davinci/board-dm646x-evm.c | 3 ++-
arch/arm/mach-davinci/board-neuros-osd2.c | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 023480b..20f1874 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -744,7 +744,8 @@ static int davinci_phy_fixup(struct phy_device *phydev)
return 0;
}
-#define HAS_ATA IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710)
+#define HAS_ATA (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+ IS_ENABLED(CONFIG_PATA_BK3710))
#define HAS_NOR IS_ENABLED(CONFIG_MTD_PHYSMAP)
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index f702d4f..cb17682 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -119,7 +119,8 @@
},
};
-#define HAS_ATA IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710)
+#define HAS_ATA (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+ IS_ENABLED(CONFIG_PATA_BK3710))
#ifdef CONFIG_I2C
/* CPLD Register 0 bits to control ATA */
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 0a78388..0c02aaa 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -163,7 +163,8 @@ static void __init davinci_ntosd2_map_io(void)
.wires = 4,
};
-#define HAS_ATA IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710)
+#define HAS_ATA (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+ IS_ENABLED(CONFIG_PATA_BK3710))
#define HAS_NAND IS_ENABLED(CONFIG_MTD_NAND_DAVINCI)
--
1.9.1
^ permalink raw reply related
* [PATCH v2 1/3] ata: add Palmchip BK3710 PATA controller driver
From: Bartlomiej Zolnierkiewicz @ 2017-03-14 16:36 UTC (permalink / raw)
To: Tejun Heo
Cc: Sekhar Nori, Sergei Shtylyov, Kevin Hilman, Arnd Bergmann,
Russell King, Dmitry Eremin-Solenikov, linux-ide,
linux-arm-kernel, linux-kernel, b.zolnierkie
In-Reply-To: <1489509414-11491-1-git-send-email-b.zolnierkie@samsung.com>
Add Palmchip BK3710 PATA controller driver.
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
drivers/ata/Kconfig | 9 ++
drivers/ata/Makefile | 1 +
drivers/ata/pata_bk3710.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 396 insertions(+)
create mode 100644 drivers/ata/pata_bk3710.c
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 70b57d2..38fa4ac 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -510,6 +510,15 @@ config PATA_BF54X
If unsure, say N.
+config PATA_BK3710
+ tristate "Palmchip BK3710 PATA support"
+ depends on ARCH_DAVINCI
+ help
+ This option enables support for the integrated IDE controller on
+ the TI DaVinci SoC.
+
+ If unsure, say N.
+
config PATA_CMD64X
tristate "CMD64x PATA support"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 89a0a19..9438db8 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
+obj-$(CONFIG_PATA_BK3710) += pata_bk3710.o
obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c
new file mode 100644
index 0000000..6d77217
--- /dev/null
+++ b/drivers/ata/pata_bk3710.c
@@ -0,0 +1,386 @@
+/*
+ * Palmchip BK3710 PATA controller driver
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Based on palm_bk3710.c:
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/ata.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define DRV_NAME "pata_bk3710"
+
+#define BK3710_TF_OFFSET 0x1F0
+#define BK3710_CTL_OFFSET 0x3F6
+
+#define BK3710_BMISP 0x02
+#define BK3710_IDETIMP 0x40
+#define BK3710_UDMACTL 0x48
+#define BK3710_MISCCTL 0x50
+#define BK3710_REGSTB 0x54
+#define BK3710_REGRCVR 0x58
+#define BK3710_DATSTB 0x5C
+#define BK3710_DATRCVR 0x60
+#define BK3710_DMASTB 0x64
+#define BK3710_DMARCVR 0x68
+#define BK3710_UDMASTB 0x6C
+#define BK3710_UDMATRP 0x70
+#define BK3710_UDMAENV 0x74
+#define BK3710_IORDYTMP 0x78
+
+static struct scsi_host_template pata_bk3710_sht = {
+ ATA_BMDMA_SHT(DRV_NAME),
+};
+
+static unsigned int ideclk_period; /* in nanoseconds */
+
+struct pata_bk3710_udmatiming {
+ unsigned int rptime; /* tRP -- Ready to pause time (nsec) */
+ unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
+ /* tENV is always a minimum of 20 nsec */
+};
+
+static const struct pata_bk3710_udmatiming pata_bk3710_udmatimings[6] = {
+ { 160, 240 / 2 }, /* UDMA Mode 0 */
+ { 125, 160 / 2 }, /* UDMA Mode 1 */
+ { 100, 120 / 2 }, /* UDMA Mode 2 */
+ { 100, 90 / 2 }, /* UDMA Mode 3 */
+ { 100, 60 / 2 }, /* UDMA Mode 4 */
+ { 85, 40 / 2 }, /* UDMA Mode 5 */
+};
+
+static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+ unsigned int mode)
+{
+ u32 val32;
+ u16 val16;
+ u8 tenv, trp, t0;
+
+ /* DMA Data Setup */
+ t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
+ ideclk_period) - 1;
+ tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
+ trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
+ ideclk_period) - 1;
+
+ /* udmastb Ultra DMA Access Strobe Width */
+ val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+ val32 |= t0 << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_UDMASTB);
+
+ /* udmatrp Ultra DMA Ready to Pause Time */
+ val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+ val32 |= trp << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_UDMATRP);
+
+ /* udmaenv Ultra DMA envelop Time */
+ val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+ val32 |= tenv << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_UDMAENV);
+
+ /* Enable UDMA for Device */
+ val16 = ioread16(base + BK3710_UDMACTL) | (1 << dev);
+ iowrite16(val16, base + BK3710_UDMACTL);
+}
+
+static void pata_bk3710_setmwdmamode(void __iomem *base, unsigned int dev,
+ unsigned short min_cycle,
+ unsigned int mode)
+{
+ const struct ata_timing *t;
+ int cycletime;
+ u32 val32;
+ u16 val16;
+ u8 td, tkw, t0;
+
+ t = ata_timing_find_mode(mode);
+ cycletime = max_t(int, t->cycle, min_cycle);
+
+ /* DMA Data Setup */
+ t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+ td = DIV_ROUND_UP(t->active, ideclk_period);
+ tkw = t0 - td - 1;
+ td--;
+
+ val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+ val32 |= td << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_DMASTB);
+
+ val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+ val32 |= tkw << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_DMARCVR);
+
+ /* Disable UDMA for Device */
+ val16 = ioread16(base + BK3710_UDMACTL) & ~(1 << dev);
+ iowrite16(val16, base + BK3710_UDMACTL);
+}
+
+static void pata_bk3710_set_dmamode(struct ata_port *ap,
+ struct ata_device *adev)
+{
+ void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
+ int is_slave = adev->devno;
+ const u8 xferspeed = adev->dma_mode;
+
+ if (xferspeed >= XFER_UDMA_0)
+ pata_bk3710_setudmamode(base, is_slave,
+ xferspeed - XFER_UDMA_0);
+ else
+ pata_bk3710_setmwdmamode(base, is_slave,
+ adev->id[ATA_ID_EIDE_DMA_MIN],
+ xferspeed);
+}
+
+static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
+ unsigned int dev, unsigned int cycletime,
+ unsigned int mode)
+{
+ const struct ata_timing *t;
+ u32 val32;
+ u8 t2, t2i, t0;
+
+ t = ata_timing_find_mode(XFER_PIO_0 + mode);
+
+ /* PIO Data Setup */
+ t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+ t2 = DIV_ROUND_UP(t->active, ideclk_period);
+
+ t2i = t0 - t2 - 1;
+ t2--;
+
+ val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+ val32 |= t2 << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_DATSTB);
+
+ val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+ val32 |= t2i << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_DATRCVR);
+
+ /* FIXME: this is broken also in the old driver */
+ if (pair) {
+ u8 mode2 = pair->pio_mode - XFER_PIO_0;
+
+ if (mode2 < mode)
+ mode = mode2;
+ }
+
+ /* TASKFILE Setup */
+ t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
+ t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
+
+ t2i = t0 - t2 - 1;
+ t2--;
+
+ val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+ val32 |= t2 << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_REGSTB);
+
+ val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+ val32 |= t2i << (dev ? 8 : 0);
+ iowrite32(val32, base + BK3710_REGRCVR);
+}
+
+static void pata_bk3710_set_piomode(struct ata_port *ap,
+ struct ata_device *adev)
+{
+ void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
+ struct ata_device *pair = ata_dev_pair(adev);
+ const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
+ const u16 *id = adev->id;
+ unsigned int cycle_time = 0;
+ int is_slave = adev->devno;
+ const u8 pio = adev->pio_mode - XFER_PIO_0;
+
+ if (id[ATA_ID_FIELD_VALID] & 2) {
+ if (ata_id_has_iordy(id))
+ cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
+ else
+ cycle_time = id[ATA_ID_EIDE_PIO];
+
+ /* conservative "downgrade" for all pre-ATA2 drives */
+ if (pio < 3 && cycle_time < t->cycle)
+ cycle_time = 0; /* use standard timing */
+ }
+
+ if (!cycle_time)
+ cycle_time = t->cycle;
+
+ pata_bk3710_setpiomode(base, pair, is_slave, cycle_time, pio);
+}
+
+static void pata_bk3710_chipinit(void __iomem *base)
+{
+ /*
+ * REVISIT: the ATA reset signal needs to be managed through a
+ * GPIO, which means it should come from platform_data. Until
+ * we get and use such information, we have to trust that things
+ * have been reset before we get here.
+ */
+
+ /*
+ * Program the IDETIMP Register Value based on the following assumptions
+ *
+ * (ATA_IDETIMP_IDEEN , ENABLE ) |
+ * (ATA_IDETIMP_PREPOST1 , DISABLE) |
+ * (ATA_IDETIMP_PREPOST0 , DISABLE) |
+ *
+ * DM6446 silicon rev 2.1 and earlier have no observed net benefit
+ * from enabling prefetch/postwrite.
+ */
+ iowrite16(BIT(15), base + BK3710_IDETIMP);
+
+ /*
+ * UDMACTL Ultra-ATA DMA Control
+ * (ATA_UDMACTL_UDMAP1 , 0 ) |
+ * (ATA_UDMACTL_UDMAP0 , 0 )
+ *
+ */
+ iowrite16(0, base + BK3710_UDMACTL);
+
+ /*
+ * MISCCTL Miscellaneous Conrol Register
+ * (ATA_MISCCTL_HWNHLD1P , 1 cycle)
+ * (ATA_MISCCTL_HWNHLD0P , 1 cycle)
+ * (ATA_MISCCTL_TIMORIDE , 1)
+ */
+ iowrite32(0x001, base + BK3710_MISCCTL);
+
+ /*
+ * IORDYTMP IORDY Timer for Primary Register
+ * (ATA_IORDYTMP_IORDYTMP , 0xffff )
+ */
+ iowrite32(0xFFFF, base + BK3710_IORDYTMP);
+
+ /*
+ * Configure BMISP Register
+ * (ATA_BMISP_DMAEN1 , DISABLE ) |
+ * (ATA_BMISP_DMAEN0 , DISABLE ) |
+ * (ATA_BMISP_IORDYINT , CLEAR) |
+ * (ATA_BMISP_INTRSTAT , CLEAR) |
+ * (ATA_BMISP_DMAERROR , CLEAR)
+ */
+ iowrite16(0, base + BK3710_BMISP);
+
+ pata_bk3710_setpiomode(base, NULL, 0, 600, 0);
+ pata_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+
+static struct ata_port_operations pata_bk3710_ports_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_80wire,
+
+ .set_piomode = pata_bk3710_set_piomode,
+ .set_dmamode = pata_bk3710_set_dmamode,
+};
+
+static int __init pata_bk3710_probe(struct platform_device *pdev)
+{
+ struct clk *clk;
+ struct resource *mem;
+ struct ata_host *host;
+ struct ata_port *ap;
+ void __iomem *base;
+ unsigned long rate;
+ int irq;
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return -ENODEV;
+
+ clk_enable(clk);
+ rate = clk_get_rate(clk);
+ if (!rate)
+ return -EINVAL;
+
+ /* NOTE: round *down* to meet minimum timings; we count in clocks */
+ ideclk_period = 1000000000UL / rate;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (mem == NULL) {
+ pr_err(DRV_NAME ": failed to get memory region resource\n");
+ return -ENODEV;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ pr_err(DRV_NAME ": failed to get IRQ resource\n");
+ return irq;
+ }
+
+ base = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ /* configure the Palmchip controller */
+ pata_bk3710_chipinit(base);
+
+ /* allocate host */
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ return -ENOMEM;
+ ap = host->ports[0];
+
+ ap->ops = &pata_bk3710_ports_ops;
+ ap->pio_mask = ATA_PIO4;
+ ap->mwdma_mask = ATA_MWDMA2;
+ ap->udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+
+ ap->ioaddr.data_addr = base + BK3710_TF_OFFSET;
+ ap->ioaddr.error_addr = base + BK3710_TF_OFFSET + 1;
+ ap->ioaddr.feature_addr = base + BK3710_TF_OFFSET + 1;
+ ap->ioaddr.nsect_addr = base + BK3710_TF_OFFSET + 2;
+ ap->ioaddr.lbal_addr = base + BK3710_TF_OFFSET + 3;
+ ap->ioaddr.lbam_addr = base + BK3710_TF_OFFSET + 4;
+ ap->ioaddr.lbah_addr = base + BK3710_TF_OFFSET + 5;
+ ap->ioaddr.device_addr = base + BK3710_TF_OFFSET + 6;
+ ap->ioaddr.status_addr = base + BK3710_TF_OFFSET + 7;
+ ap->ioaddr.command_addr = base + BK3710_TF_OFFSET + 7;
+
+ ap->ioaddr.altstatus_addr = base + BK3710_CTL_OFFSET;
+ ap->ioaddr.ctl_addr = base + BK3710_CTL_OFFSET;
+
+ ap->ioaddr.bmdma_addr = base;
+
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
+ (unsigned long)base + BK3710_TF_OFFSET,
+ (unsigned long)base + BK3710_CTL_OFFSET);
+
+ /* activate */
+ return ata_host_activate(host, irq, ata_sff_interrupt, 0,
+ &pata_bk3710_sht);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:palm_bk3710");
+
+static struct platform_driver pata_bk3710_driver = {
+ .driver = {
+ .name = "palm_bk3710",
+ },
+};
+
+static int __init pata_bk3710_init(void)
+{
+ return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe);
+}
+
+module_init(pata_bk3710_init);
+MODULE_LICENSE("GPL");
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 1/3] ata: add Palmchip BK3710 PATA controller driver
From: Bartlomiej Zolnierkiewicz @ 2017-03-14 16:36 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Tejun Heo, Sekhar Nori, Kevin Hilman, Arnd Bergmann, Russell King,
Dmitry Eremin-Solenikov, linux-ide, linux-arm-kernel,
linux-kernel
In-Reply-To: <c30eeadf-c4f3-3d35-9b2f-abc9eed3e4e8@cogentembedded.com>
Hi,
On Sunday, March 12, 2017 08:28:43 PM Sergei Shtylyov wrote:
> Hello!
>
> On 03/09/2017 04:01 PM, Bartlomiej Zolnierkiewicz wrote:
>
> > Add Palmchip BK3710 PATA controller driver.
> >
> > Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> [...]
> > diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c
> > new file mode 100644
> > index 0000000..65ee737
> > --- /dev/null
> > +++ b/drivers/ata/pata_bk3710.c
> > @@ -0,0 +1,395 @@
> > +/*
> > + * Palmchip BK3710 PATA controller driver
> > + *
> > + * Copyright (c) 2017 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.com
> > + *
> > + * Based on palm_bk3710.c:
> > + *
> > + * Copyright (C) 2006 Texas Instruments.
> > + * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
> > + *
> > + * This file is subject to the terms and conditions of the GNU General Public
> > + * License. See the file "COPYING" in the main directory of this archive
> > + * for more details.
> > + */
> > +
> > +#include <linux/types.h>
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/ioport.h>
> > +#include <linux/ata.h>
> > +#include <linux/libata.h>
> > +#include <linux/delay.h>
> > +#include <linux/init.h>
> > +#include <linux/clk.h>
> > +#include <linux/platform_device.h>
>
> Probably a good idea to sort the #include's alphabetically...
Done.
> > +
> > +#define DRV_NAME "pata_bk3710"
> > +#define DRV_VERSION "0.1.0"
>
> This macro isn't used anywhere, do we really need it?
Removed.
> > +
> > +#define BK3710_REG_OFFSET 0x1F0
>
> I'd call it BK3710_TF_OFFSET or something of that sort...
> The DM644x manual calls these register command block (which seems to comply
> with ATA wording)...
Renamed.
> > +#define BK3710_CTL_OFFSET 0x3F6
> > +
> > +#define BK3710_BMISP 0x02
>
> Nothing other than the BMIDE status register, dunno why they made it 16-bit...
>
> > +#define BK3710_IDETIMP 0x40
> > +#define BK3710_UDMACTL 0x48
> > +#define BK3710_MISCCTL 0x50
> > +#define BK3710_REGSTB 0x54
> > +#define BK3710_REGRCVR 0x58
> > +#define BK3710_DATSTB 0x5C
> > +#define BK3710_DATRCVR 0x60
> > +#define BK3710_DMASTB 0x64
> > +#define BK3710_DMARCVR 0x68
> > +#define BK3710_UDMASTB 0x6C
> > +#define BK3710_UDMATRP 0x70
> > +#define BK3710_UDMAENV 0x74
> > +#define BK3710_IORDYTMP 0x78
>
> I'd keep all registers declared as in the IDE driver, for the purposes of
> documentation...
Don't see much point in it as the real documentation is available.
> [...]
> > +static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
> > + unsigned int mode)
> > +{
> > + u32 val32;
> > + u16 val16;
> > + u8 tenv, trp, t0;
>
> I think DaveM prefers reverse Christmas tree order with the declarations
> but maybe that's only for the networking tree... :-)
>
> > +
> > + /* DMA Data Setup */
> > + t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
> > + ideclk_period) - 1;
> > + tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
> > + trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
> > + ideclk_period) - 1;
> > +
> > + /* udmastb Ultra DMA Access Strobe Width */
> > + val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
>
> I'd separate ioread32() and & to the different lines but as this is copied
> from the IDE driver verbatim, you can ignore me. :-)
Ignored. ;-)
> > + val32 |= (t0 << (dev ? 8 : 0));
>
> Outer parens not really needed.
Fixed.
> > + iowrite32(val32, base + BK3710_UDMASTB);
> > +
> > + /* udmatrp Ultra DMA Ready to Pause Time */
> > + val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (trp << (dev ? 8 : 0));
>
> Here as well..
ditto
> > + iowrite32(val32, base + BK3710_UDMATRP);
> > +
> > + /* udmaenv Ultra DMA envelop Time */
> > + val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (tenv << (dev ? 8 : 0));
>
> And here...
ditto
> [...]
> > +static void pata_bk3710_setdmamode(void __iomem *base, unsigned int dev,
>
> Maybe setmwdmamode()?
Renamed.
> > + unsigned short min_cycle,
> > + unsigned int mode)
> > +{
> > + const struct ata_timing *t;
> > + int cycletime;
> > + u32 val32;
> > + u16 val16;
> > + u8 td, tkw, t0;
> > +
> > + t = ata_timing_find_mode(mode);
> > + cycletime = max_t(int, t->cycle, min_cycle);
> > +
> > + /* DMA Data Setup */
> > + t0 = DIV_ROUND_UP(cycletime, ideclk_period);
> > + td = DIV_ROUND_UP(t->active, ideclk_period);
> > + tkw = t0 - td - 1;
> > + td -= 1;
>
> td--;
Fixed.
> > +
> > + val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (td << (dev ? 8 : 0));
>
> And here...
ditto
> > + iowrite32(val32, base + BK3710_DMASTB);
> > +
> > + val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (tkw << (dev ? 8 : 0));
>
> And here...
ditto
> [...]
> > +static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
> > + unsigned int dev, unsigned int cycletime,
> > + unsigned int mode)
> > +{
> > + const struct ata_timing *t;
> > + u32 val32;
> > + u8 t2, t2i, t0;
> > +
> > + t = ata_timing_find_mode(XFER_PIO_0 + mode);
> > +
> > + /* PIO Data Setup */
> > + t0 = DIV_ROUND_UP(cycletime, ideclk_period);
> > + t2 = DIV_ROUND_UP(t->active, ideclk_period);
> > +
> > + t2i = t0 - t2 - 1;
> > + t2 -= 1;
>
> t2--;
ditto
> > +
> > + val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (t2 << (dev ? 8 : 0));
>
> Outer parens not needed.
ditto
> > + iowrite32(val32, base + BK3710_DATSTB);
> > +
> > + val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (t2i << (dev ? 8 : 0));
>
> Here too..
ditto
> > + iowrite32(val32, base + BK3710_DATRCVR);
> > +
> > + /* FIXME: this is broken also in the old driver */
>
> What's wrong with this logic BTW?
Two things:
- it happens too late, after "mode" variable has been read
- we should probably just merge timings instead of downgrading PIO mode
> > + if (pair) {
> > + u8 mode2 = pair->pio_mode - XFER_PIO_0;
> > +
> > + if (mode2 < mode)
> > + mode = mode2;
> > + }
> > +
> > + /* TASKFILE Setup */
> > + t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
> > + t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
> > +
> > + t2i = t0 - t2 - 1;
> > + t2 -= 1;
>
> t2--;
Fixed.
> > +
> > + val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (t2 << (dev ? 8 : 0));
>
> Outer parens again...
ditto
> > + iowrite32(val32, base + BK3710_REGSTB);
> > +
> > + val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
> > + val32 |= (t2i << (dev ? 8 : 0));
>
> And again...
ditto
> > + iowrite32(val32, base + BK3710_REGRCVR);
> > +}
> > +
> > +static void pata_bk3710_set_piomode(struct ata_port *ap,
> > + struct ata_device *adev)
> > +{
> > + void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
> > + struct ata_device *pair = ata_dev_pair(adev);
> > + const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
> > + const u16 *id = adev->id;
> > + unsigned int cycle_time;
> > + int is_slave = adev->devno;
> > + const u8 pio = adev->pio_mode - XFER_PIO_0;
> > +
> > + if (id[ATA_ID_FIELD_VALID] & 2) {
> > + if (ata_id_has_iordy(id))
> > + cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
> > + else
> > + cycle_time = id[ATA_ID_EIDE_PIO];
> > +
> > + /* conservative "downgrade" for all pre-ATA2 drives */
> > + if (pio < 3 && cycle_time < t->cycle)
> > + cycle_time = 0; /* use standard timing */
> > + }
> > +
> > + if (!cycle_time)
> > + cycle_time = t->cycle;
>
> This seems like a helper needed by libata in general but OK...
I need to think about this a bit more..
[...]
> > +static int __init pata_bk3710_probe(struct platform_device *pdev)
> > +{
> > + struct clk *clk;
> > + struct resource *mem, *irq;
> > + struct ata_host *host;
> > + struct ata_port *ap;
> > + void __iomem *base;
> > + unsigned long rate, mem_size;
> > +
> > + clk = clk_get(&pdev->dev, NULL);
>
> devm_clk_get()?
Fixed.
> > + if (IS_ERR(clk))
> > + return -ENODEV;
> > +
> > + clk_enable(clk);
> > + rate = clk_get_rate(clk);
> > + if (!rate)
> > + return -EINVAL;
> > +
> > + /* NOTE: round *down* to meet minimum timings; we count in clocks */
> > + ideclk_period = 1000000000UL / rate;
> > +
> > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + if (mem == NULL) {
> > + pr_err(DRV_NAME ": failed to get memory region resource\n");
> > + return -ENODEV;
> > + }
> > +
> > + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>
> How about platform_get_irq()? I've fixed it... :-)
Converted.
> > + if (irq == NULL) {
> > + pr_err(DRV_NAME ": failed to get IRQ resource\n");
> > + return -ENODEV;
> > + }
> > +
> > + mem_size = resource_size(mem);
> > + if (!devm_request_mem_region(&pdev->dev, mem->start, mem_size,
> > + DRV_NAME)) {
> > + pr_err(DRV_NAME ": failed to request memory region\n");
> > + return -EBUSY;
> > + }
> > +
> > + base = ioremap(mem->start, mem_size);
>
> How about devm_ioremap_resource() instead of the above?
ditto
> > + if (!base) {
> > + pr_err(DRV_NAME ": failed to map IO memory\n");
> > + return -ENOMEM;
> > + }
> > +
> > + /* Configure the Palm Chip controller */
>
> It's Palmchip. :-)
Fixed.
[...]
Thanks for review!
Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics
^ permalink raw reply
* Re: [PATCH 2/4] ARM: dts: dm8168-evm: add the external reference clock for SATA
From: Tony Lindgren @ 2017-03-14 15:05 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Paul Walmsley, linux-ide,
linux-devicetree, LKML, arm-soc, linux-omap
In-Reply-To: <CAMpxmJW5f5foYbFv_FsQPibDamT4hCJSywnELdLmXpQg_oKohQ@mail.gmail.com>
* Bartosz Golaszewski <bgolaszewski@baylibre.com> [170314 08:03]:
> 2017-03-13 22:34 GMT+01:00 Tony Lindgren <tony@atomide.com>:
> > * Bartosz Golaszewski <bgolaszewski@baylibre.com> [170313 09:45]:
> >> This board has an external oscillator supplying the reference clock
> >> signal for SATA. Its rate is fixed at 100Mhz. Add a corresponding
> >> device tree node.
> >
> > Is this the 100MHz clock from PCIe? Just like on dm814x-evm as noted
> > in the workaround thread below:
> >
> > http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/p/181083/671141
> >
> > Regards,
> >
> > Tony
> >
>
> Hi Tony,
>
> these signals come from a TI CDCM61002 (U30 on the board's
> schematics). It's hardwired to 100mHZ output.
Oh OK thanks.
Tony
^ permalink raw reply
* Re: [PATCH 2/4] ARM: dts: dm8168-evm: add the external reference clock for SATA
From: Bartosz Golaszewski @ 2017-03-14 15:01 UTC (permalink / raw)
To: Tony Lindgren
Cc: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Paul Walmsley, linux-ide,
linux-devicetree, LKML, arm-soc, linux-omap
In-Reply-To: <20170313213405.GX20572@atomide.com>
2017-03-13 22:34 GMT+01:00 Tony Lindgren <tony@atomide.com>:
> * Bartosz Golaszewski <bgolaszewski@baylibre.com> [170313 09:45]:
>> This board has an external oscillator supplying the reference clock
>> signal for SATA. Its rate is fixed at 100Mhz. Add a corresponding
>> device tree node.
>
> Is this the 100MHz clock from PCIe? Just like on dm814x-evm as noted
> in the workaround thread below:
>
> http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/p/181083/671141
>
> Regards,
>
> Tony
>
Hi Tony,
these signals come from a TI CDCM61002 (U30 on the board's
schematics). It's hardwired to 100mHZ output.
Thanks,
Bartosz Golaszewski
^ permalink raw reply
* [RFC PATCH] drivers: ata: Add [save|restore]_initial_config override functions
From: Anurag Kumar Vulisha @ 2017-03-14 11:59 UTC (permalink / raw)
To: Tejun Heo, Hans de Goede
Cc: anirudh, linux-ide, linux-kernel, Anurag Kumar Vulisha
Since there are SATA controllers that configure vendor specific registers
for AXI bus, OOB timing, threshold related settings. These settings may get
reset to the default values on resetting the SATA controller.
So this patch adds the support for adding [save|restore]_initial_config
override functions for saving and restoring controller values from the driver
instead of doing it in AHCI stack
Signed-off-by: Anurag Kumar Vulisha <anuragku@xilinx.com>
---
drivers/ata/ahci.c | 5 ++++-
drivers/ata/ahci.h | 9 +++++++++
drivers/ata/libahci.c | 5 ++++-
drivers/ata/libahci_platform.c | 5 ++++-
drivers/ata/sata_highbank.c | 6 ++++--
5 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 2fc5240..ed76c9e 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -613,7 +613,10 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
}
- ahci_save_initial_config(&pdev->dev, hpriv);
+ if (hpriv->save_initial_config == NULL)
+ ahci_save_initial_config(dev, hpriv);
+ else
+ hpriv->save_initial_config(dev, hpriv);
}
static int ahci_pci_reset_controller(struct ata_host *host)
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 5db6ab2..2929e27 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -363,6 +363,15 @@ struct ahci_host_priv {
/* only required for per-port MSI(-X) support */
int (*get_irq_vector)(struct ata_host *host,
int port);
+
+ /*
+ * Optional ahci_save_initial_config & ahci_restore_initial_config
+ * override, if not set then default ahci_save_initial_config and
+ * ahci_restore_initial_config in libahci.c will be used
+ */
+ void (*save_initial_config)(struct device *dev,
+ struct ahci_host_priv *hpriv);
+ void (*restore_initial_config)(struct ata_host *host);
};
extern int ahci_ignore_sss;
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 3159f9e..fb57525 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -940,7 +940,10 @@ int ahci_reset_controller(struct ata_host *host)
/* Some registers might be cleared on reset. Restore
* initial values.
*/
- ahci_restore_initial_config(host);
+ if (hpriv->restore_initial_config == NULL)
+ ahci_restore_initial_config(host);
+ else
+ hpriv->restore_initial_config(host);
} else
dev_info(host->dev, "skipping global host reset\n");
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index aaa761b..15ba5f8 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -523,7 +523,10 @@ int ahci_platform_init_host(struct platform_device *pdev,
/* prepare host */
pi.private_data = (void *)(unsigned long)hpriv->flags;
- ahci_save_initial_config(dev, hpriv);
+ if (hpriv->save_initial_config == NULL)
+ ahci_save_initial_config(dev, hpriv);
+ else
+ hpriv->save_initial_config(dev, hpriv);
if (hpriv->cap & HOST_CAP_NCQ)
pi.flags |= ATA_FLAG_NCQ;
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index aafb8cc..61af3c6 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -512,8 +512,10 @@ static int ahci_highbank_probe(struct platform_device *pdev)
if (rc)
return rc;
-
- ahci_save_initial_config(dev, hpriv);
+ if (hpriv->save_initial_config == NULL)
+ ahci_save_initial_config(dev, hpriv);
+ else
+ hpriv->save_initial_config(dev, hpriv);
/* prepare host */
if (hpriv->cap & HOST_CAP_NCQ)
--
2.1.1
^ permalink raw reply related
* [PATCH v2 2/4] ARM: dts: dm8168-evm: add the external reference clock for SATA
From: Bartosz Golaszewski @ 2017-03-14 11:14 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Tony Lindgren, Paul Walmsley,
Sergei Shtylyov
Cc: linux-ide, devicetree, linux-kernel, linux-arm-kernel, linux-omap,
Bartosz Golaszewski
In-Reply-To: <1489490055-2318-1-git-send-email-bgolaszewski@baylibre.com>
This board has an external oscillator supplying the reference clock
signal for SATA. Its rate is fixed at 100Mhz. Add a corresponding
device tree node.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/arm/boot/dts/dm8168-evm.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/dm8168-evm.dts b/arch/arm/boot/dts/dm8168-evm.dts
index 0bf55fa..c6fabfc 100644
--- a/arch/arm/boot/dts/dm8168-evm.dts
+++ b/arch/arm/boot/dts/dm8168-evm.dts
@@ -25,6 +25,12 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
+
+ sata_refclk: fixedclock0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
};
&dm816x_pinmux {
--
2.9.3
^ permalink raw reply related
* [PATCH v2 4/4] ARM: omap2plus_defconfig: enable ahci-dm816 module
From: Bartosz Golaszewski @ 2017-03-14 11:14 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Tony Lindgren, Paul Walmsley,
Sergei Shtylyov
Cc: linux-ide, devicetree, linux-kernel, linux-arm-kernel, linux-omap,
Bartosz Golaszewski
In-Reply-To: <1489490055-2318-1-git-send-email-bgolaszewski@baylibre.com>
This is now supported on the dm8168-evm board, so enable it in
the defconfig for omap2+.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/arm/configs/omap2plus_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index f2462a6..3944aa9 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -141,6 +141,7 @@ CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_ATA=y
CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_DM816=m
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
--
2.9.3
^ permalink raw reply related
* [PATCH v2 3/4] ARM: dts: dm8168-evm: add SATA node
From: Bartosz Golaszewski @ 2017-03-14 11:14 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Tony Lindgren, Paul Walmsley,
Sergei Shtylyov
Cc: linux-ide-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-omap-u79uwXL29TY76Z2rM5mHXA, Bartosz Golaszewski
In-Reply-To: <1489490055-2318-1-git-send-email-bgolaszewski-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Add the SATA controller node to the dm8168-evm device tree.
Signed-off-by: Bartosz Golaszewski <bgolaszewski-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
arch/arm/boot/dts/dm8168-evm.dts | 4 ++++
arch/arm/boot/dts/dm816x.dtsi | 7 +++++++
2 files changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/dm8168-evm.dts b/arch/arm/boot/dts/dm8168-evm.dts
index c6fabfc..1865976 100644
--- a/arch/arm/boot/dts/dm8168-evm.dts
+++ b/arch/arm/boot/dts/dm8168-evm.dts
@@ -179,3 +179,7 @@
pinctrl-0 = <&usb1_pins>;
mentor,multipoint = <0>;
};
+
+&sata {
+ clocks = <&sysclk5_ck>, <&sata_refclk>;
+};
diff --git a/arch/arm/boot/dts/dm816x.dtsi b/arch/arm/boot/dts/dm816x.dtsi
index 276211e..59cbf95 100644
--- a/arch/arm/boot/dts/dm816x.dtsi
+++ b/arch/arm/boot/dts/dm816x.dtsi
@@ -293,6 +293,13 @@
phy-handle = <&phy1>;
};
+ sata: sata@4a140000 {
+ compatible = "ti,dm816-ahci";
+ reg = <0x4a140000 0x10000>;
+ interrupts = <16>;
+ ti,hwmods = "sata";
+ };
+
mcspi1: spi@48030000 {
compatible = "ti,omap4-mcspi";
reg = <0x48030000 0x1000>;
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 1/4] ARM: OMAP2+: dm81xx: Add clkdm and hwmod for SATA
From: Bartosz Golaszewski @ 2017-03-14 11:14 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Tony Lindgren, Paul Walmsley,
Sergei Shtylyov
Cc: linux-ide, devicetree, linux-kernel, linux-arm-kernel, linux-omap,
Bartosz Golaszewski
In-Reply-To: <1489490055-2318-1-git-send-email-bgolaszewski@baylibre.com>
From: Kevin Hilman <khilman@baylibre.com>
Add the SATA clockdomain (part of CM_DEFAULT) and a hwmod for the SATA
block on dm81xx.
Tested on DM8168 EVM.
Signed-off-by: Kevin Hilman <khilman@baylibre.com>
[Bartosz: removed an unused define]
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/arm/mach-omap2/clockdomains81xx_data.c | 10 +++++++++
arch/arm/mach-omap2/cm81xx.h | 1 +
arch/arm/mach-omap2/omap_hwmod_81xx_data.c | 34 +++++++++++++++++++++++++++++
3 files changed, 45 insertions(+)
diff --git a/arch/arm/mach-omap2/clockdomains81xx_data.c b/arch/arm/mach-omap2/clockdomains81xx_data.c
index 3b5fb05..65fbd13 100644
--- a/arch/arm/mach-omap2/clockdomains81xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains81xx_data.c
@@ -91,6 +91,14 @@ static struct clockdomain default_l3_slow_81xx_clkdm = {
.flags = CLKDM_CAN_SWSUP,
};
+static struct clockdomain default_sata_81xx_clkdm = {
+ .name = "default_clkdm",
+ .pwrdm = { .name = "default_pwrdm" },
+ .cm_inst = TI81XX_CM_DEFAULT_MOD,
+ .clkdm_offs = TI816X_CM_DEFAULT_SATA_CLKDM,
+ .flags = CLKDM_CAN_SWSUP,
+};
+
/* 816x only */
static struct clockdomain alwon_mpu_816x_clkdm = {
@@ -173,6 +181,7 @@ static struct clockdomain *clockdomains_ti814x[] __initdata = {
&mmu_81xx_clkdm,
&mmu_cfg_81xx_clkdm,
&default_l3_slow_81xx_clkdm,
+ &default_sata_81xx_clkdm,
NULL,
};
@@ -200,6 +209,7 @@ static struct clockdomain *clockdomains_ti816x[] __initdata = {
&default_ducati_816x_clkdm,
&default_pci_816x_clkdm,
&default_l3_slow_81xx_clkdm,
+ &default_sata_81xx_clkdm,
NULL,
};
diff --git a/arch/arm/mach-omap2/cm81xx.h b/arch/arm/mach-omap2/cm81xx.h
index 3a0ccf0..5d73a10 100644
--- a/arch/arm/mach-omap2/cm81xx.h
+++ b/arch/arm/mach-omap2/cm81xx.h
@@ -57,5 +57,6 @@
#define TI816X_CM_DEFAULT_PCI_CLKDM 0x0010
#define TI816X_CM_DEFAULT_L3_SLOW_CLKDM 0x0014
#define TI816X_CM_DEFAULT_DUCATI_CLKDM 0x0018
+#define TI816X_CM_DEFAULT_SATA_CLKDM 0x0060
#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
index b82b77c..310afe4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
@@ -106,6 +106,7 @@
*/
#define DM81XX_CM_DEFAULT_OFFSET 0x500
#define DM81XX_CM_DEFAULT_USB_CLKCTRL (0x558 - DM81XX_CM_DEFAULT_OFFSET)
+#define DM81XX_CM_DEFAULT_SATA_CLKCTRL (0x560 - DM81XX_CM_DEFAULT_OFFSET)
/* L3 Interconnect entries clocked at 125, 250 and 500MHz */
static struct omap_hwmod dm81xx_alwon_l3_slow_hwmod = {
@@ -973,6 +974,38 @@ static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = {
.user = OCP_USER_MPU,
};
+static struct omap_hwmod_class_sysconfig dm81xx_sata_sysc = {
+ .sysc_offs = 0x1100,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = SIDLE_FORCE,
+ .sysc_fields = &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dm81xx_sata_hwmod_class = {
+ .name = "sata",
+ .sysc = &dm81xx_sata_sysc,
+};
+
+static struct omap_hwmod dm81xx_sata_hwmod = {
+ .name = "sata",
+ .clkdm_name = "default_sata_clkdm",
+ .flags = HWMOD_NO_IDLEST,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DM81XX_CM_DEFAULT_SATA_CLKCTRL,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+ .class = &dm81xx_sata_hwmod_class,
+};
+
+static struct omap_hwmod_ocp_if dm81xx_l4_hs__sata = {
+ .master = &dm81xx_l4_hs_hwmod,
+ .slave = &dm81xx_sata_hwmod,
+ .clk = "sysclk5_ck",
+ .user = OCP_USER_MPU,
+};
+
static struct omap_hwmod_class_sysconfig dm81xx_mmc_sysc = {
.rev_offs = 0x0,
.sysc_offs = 0x110,
@@ -1474,6 +1507,7 @@ static struct omap_hwmod_ocp_if *dm816x_hwmod_ocp_ifs[] __initdata = {
&dm81xx_l4_hs__emac0,
&dm81xx_emac0__mdio,
&dm816x_l4_hs__emac1,
+ &dm81xx_l4_hs__sata,
&dm81xx_alwon_l3_fast__tpcc,
&dm81xx_alwon_l3_fast__tptc0,
&dm81xx_alwon_l3_fast__tptc1,
--
2.9.3
^ permalink raw reply related
* [PATCH v2 0/4] ARM: dm8168-evm: add SATA support
From: Bartosz Golaszewski @ 2017-03-14 11:14 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Neil Armstrong, Michael Turquette,
Kevin Hilman, Patrick Titiano, Tony Lindgren, Paul Walmsley,
Sergei Shtylyov
Cc: linux-ide, devicetree, linux-kernel, linux-arm-kernel, linux-omap,
Bartosz Golaszewski
This series implements support for the on-board SATA controller
on the dm8168-evm board.
The first patch adds the clock domain and hwmod entries for the
SATA module.
The second patch models the external reference clock used by SATA.
The third adds the SATA node to the SoC's device tree.
The fourth enables the SATA driver by default in omap2plus_defconfig.
Tested together with the series implementing the driver for
ahci-dm816 on a DM8168-EVM board.
v1 -> v2:
PATCH 1/4:
- removed the unused define from cm81xx.h
PATCH 3/4:
- fixed the size of the mapped register region
Bartosz Golaszewski (3):
ARM: dts: dm8168-evm: add the external reference clock for SATA
ARM: dts: dm8168-evm: add SATA node
ARM: omap2plus_defconfig: enable ahci-dm816 module
Kevin Hilman (1):
ARM: OMAP2+: dm81xx: Add clkdm and hwmod for SATA
arch/arm/boot/dts/dm8168-evm.dts | 10 +++++++++
arch/arm/boot/dts/dm816x.dtsi | 7 ++++++
arch/arm/configs/omap2plus_defconfig | 1 +
arch/arm/mach-omap2/clockdomains81xx_data.c | 10 +++++++++
arch/arm/mach-omap2/cm81xx.h | 1 +
arch/arm/mach-omap2/omap_hwmod_81xx_data.c | 34 +++++++++++++++++++++++++++++
6 files changed, 63 insertions(+)
--
2.9.3
^ permalink raw reply
* [PATCH v2 2/2] ata: ahci: add support for DaVinci DM816 SATA controller
From: Bartosz Golaszewski @ 2017-03-14 11:04 UTC (permalink / raw)
To: Tejun Heo, Rob Herring, Mark Rutland, Neil Armstrong,
Michael Turquette, Kevin Hilman, Patrick Titiano, Tony Lindgren,
Sergei Shtylyov
Cc: linux-ide, devicetree, linux-kernel, Bartosz Golaszewski
In-Reply-To: <1489489491-14195-1-git-send-email-bgolaszewski@baylibre.com>
This SATA controller is quite similar to the one present on the DA850
SoC, but the PHY configuration is different and it supports two HBA
ports.
The IP suffers from the same PMP issue the DA850 does - if we enable
PMP but don't use it - softreset fails. Appropriate workaround was
implemented in this driver as well.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
drivers/ata/Kconfig | 9 +++
drivers/ata/Makefile | 1 +
drivers/ata/ahci_dm816.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
create mode 100644 drivers/ata/ahci_dm816.c
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 70b57d2..7f59a7a 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -118,6 +118,15 @@ config AHCI_DA850
If unsure, say N.
+config AHCI_DM816
+ tristate "DaVinci DM816 AHCI SATA support"
+ depends on ARCH_OMAP2PLUS
+ help
+ This option enables support for the DaVinci DM816 SoC's
+ onboard AHCI SATA controller.
+
+ If unsure, say N.
+
config AHCI_ST
tristate "ST AHCI SATA support"
depends on ARCH_STI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 89a0a19..3052c0a 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
obj-$(CONFIG_AHCI_BRCM) += ahci_brcm.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_CEVA) += ahci_ceva.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_DM816) += ahci_dm816.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_OCTEON) += ahci_octeon.o
diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c
new file mode 100644
index 0000000..fbd827c
--- /dev/null
+++ b/drivers/ata/ahci_dm816.c
@@ -0,0 +1,200 @@
+/*
+ * DaVinci DM816 AHCI SATA platform driver
+ *
+ * Copyright (C) 2017 BayLibre SAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/libata.h>
+#include <linux/ahci_platform.h>
+
+#include "ahci.h"
+
+#define AHCI_DM816_DRV_NAME "ahci-dm816"
+
+#define AHCI_DM816_PHY_ENPLL(x) ((x) << 0)
+#define AHCI_DM816_PHY_MPY(x) ((x) << 1)
+#define AHCI_DM816_PHY_LOS(x) ((x) << 12)
+#define AHCI_DM816_PHY_RXCDR(x) ((x) << 13)
+#define AHCI_DM816_PHY_RXEQ(x) ((x) << 16)
+#define AHCI_DM816_PHY_TXSWING(x) ((x) << 23)
+
+#define AHCI_DM816_P0PHYCR_REG 0x178
+#define AHCI_DM816_P1PHYCR_REG 0x1f8
+
+#define AHCI_DM816_PLL_OUT 1500000000LU
+
+static const unsigned long pll_mpy_table[] = {
+ 400, 500, 600, 800, 825, 1000, 1200,
+ 1250, 1500, 1600, 1650, 2000, 2200, 2500
+};
+
+static int ahci_dm816_get_mpy_bits(unsigned long refclk_rate)
+{
+ unsigned long pll_multiplier;
+ int i;
+
+ /*
+ * We need to determine the value of the multiplier (MPY) bits.
+ * In order to include the 8.25 multiplier we need to first divide
+ * the refclk rate by 100.
+ */
+ pll_multiplier = AHCI_DM816_PLL_OUT / (refclk_rate / 100);
+
+ for (i = 0; i < ARRAY_SIZE(pll_mpy_table); i++) {
+ if (pll_mpy_table[i] == pll_multiplier)
+ return i;
+ }
+
+ /*
+ * We should have divided evenly - if not, return an invalid
+ * value.
+ */
+ return -1;
+}
+
+static int ahci_dm816_phy_init(struct ahci_host_priv *hpriv, struct device *dev)
+{
+ unsigned long refclk_rate;
+ int mpy;
+ u32 val;
+
+ /*
+ * We should have been supplied two clocks: the functional and
+ * keep-alive clock and the external reference clock. We need the
+ * rate of the latter to calculate the correct value of MPY bits.
+ */
+ if (!hpriv->clks[1]) {
+ dev_err(dev, "reference clock not supplied\n");
+ return -EINVAL;
+ }
+
+ refclk_rate = clk_get_rate(hpriv->clks[1]);
+ if ((refclk_rate % 100) != 0) {
+ dev_err(dev, "reference clock rate must be divisible by 100\n");
+ return -EINVAL;
+ }
+
+ mpy = ahci_dm816_get_mpy_bits(refclk_rate);
+ if (mpy < 0) {
+ dev_err(dev, "can't calculate the MPY bits value\n");
+ return -EINVAL;
+ }
+
+ /* Enable the PHY and configure the first HBA port. */
+ val = AHCI_DM816_PHY_MPY(mpy) | AHCI_DM816_PHY_LOS(1) |
+ AHCI_DM816_PHY_RXCDR(4) | AHCI_DM816_PHY_RXEQ(1) |
+ AHCI_DM816_PHY_TXSWING(3) | AHCI_DM816_PHY_ENPLL(1);
+ writel(val, hpriv->mmio + AHCI_DM816_P0PHYCR_REG);
+
+ /* Configure the second HBA port. */
+ val = AHCI_DM816_PHY_LOS(1) | AHCI_DM816_PHY_RXCDR(4) |
+ AHCI_DM816_PHY_RXEQ(1) | AHCI_DM816_PHY_TXSWING(3);
+ writel(val, hpriv->mmio + AHCI_DM816_P1PHYCR_REG);
+
+ return 0;
+}
+
+static int ahci_dm816_softreset(struct ata_link *link,
+ unsigned int *class, unsigned long deadline)
+{
+ int pmp, ret;
+
+ pmp = sata_srst_pmp(link);
+
+ /*
+ * There's an issue with the SATA controller on DM816 SoC: if we
+ * enable Port Multiplier support, but the drive is connected directly
+ * to the board, it can't be detected. As a workaround: if PMP is
+ * enabled, we first call ahci_do_softreset() and pass it the result of
+ * sata_srst_pmp(). If this call fails, we retry with pmp = 0.
+ */
+ ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
+ if (pmp && ret == -EBUSY)
+ return ahci_do_softreset(link, class, 0,
+ deadline, ahci_check_ready);
+
+ return ret;
+}
+
+static struct ata_port_operations ahci_dm816_port_ops = {
+ .inherits = &ahci_platform_ops,
+ .softreset = ahci_dm816_softreset,
+};
+
+static const struct ata_port_info ahci_dm816_port_info = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_dm816_port_ops,
+};
+
+static struct scsi_host_template ahci_dm816_platform_sht = {
+ AHCI_SHT(AHCI_DM816_DRV_NAME),
+};
+
+static int ahci_dm816_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ahci_host_priv *hpriv;
+ int rc;
+
+ hpriv = ahci_platform_get_resources(pdev);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+ rc = ahci_dm816_phy_init(hpriv, dev);
+ if (rc)
+ goto disable_resources;
+
+ rc = ahci_platform_init_host(pdev, hpriv,
+ &ahci_dm816_port_info,
+ &ahci_dm816_platform_sht);
+ if (rc)
+ goto disable_resources;
+
+ return 0;
+
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
+
+ return rc;
+}
+
+static SIMPLE_DEV_PM_OPS(ahci_dm816_pm_ops,
+ ahci_platform_suspend,
+ ahci_platform_resume);
+
+static const struct of_device_id ahci_dm816_of_match[] = {
+ { .compatible = "ti,dm816-ahci", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ahci_dm816_of_match);
+
+static struct platform_driver ahci_dm816_driver = {
+ .probe = ahci_dm816_probe,
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = AHCI_DM816_DRV_NAME,
+ .of_match_table = ahci_dm816_of_match,
+ .pm = &ahci_dm816_pm_ops,
+ },
+};
+module_platform_driver(ahci_dm816_driver);
+
+MODULE_DESCRIPTION("DaVinci DM816 AHCI SATA platform driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL");
--
2.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox