Skip to content

Commit

Permalink
Merge branch 'for-4.11' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/tj/libata

Pull libata updates from Tejun Heo:

 - Bartlomiej added pata_falcon

 - Christoph is trying to remove use of static 4k buf.  It's still WIP

 - config cleanup around HAS_DMA

 - other fixes and driver-specific changes

* 'for-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: (29 commits)
  ata: pata_of_platform: using of_property_read_u32() helper
  pata_atiixp: Don't use unconnected secondary port on SB600/SB700
  libata-sff: Don't scan disabled ports when checking for legacy mode.
  pata_octeon_cf: remove unused local variables from octeon_cf_set_piomode()
  ahci: qoriq: added ls2088a platforms support
  ahci: qoriq: report error when ecc register address is missing in dts
  ahci: qoriq: added a condition to enable dma coherence
  Revert "libata: switch to dynamic allocation instead of ata_scsi_rbuf"
  ahci: imx: fix building without hwmon or thermal
  ata: add Atari Falcon PATA controller driver
  ata: pass queued command to ->sff_data_xfer method
  ata: allow subsystem to be used on m68k arch
  libata: switch to dynamic allocation instead of ata_scsi_rbuf
  libata: don't call ata_scsi_rbuf_fill for command without a response buffer
  libata: call ->scsi_done from ata_scsi_simulate
  libata: remove the done callback from ata_scsi_args
  libata: move struct ata_scsi_args to libata-scsi.c
  libata: avoid global response buffer in atapi_qc_complete
  libata-eh: Use switch() instead of sparse array for protocol strings
  ata: sata_mv: Convert to devm_ioremap_resource()
  ...
  • Loading branch information
Linus Torvalds committed Feb 22, 2017
2 parents 97a229f + 73b2951 commit 79f4d1d
Show file tree
Hide file tree
Showing 24 changed files with 612 additions and 191 deletions.
19 changes: 18 additions & 1 deletion drivers/ata/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ menuconfig ATA
tristate "Serial ATA and Parallel ATA drivers (libata)"
depends on HAS_IOMEM
depends on BLOCK
depends on !(M32R || M68K || S390) || BROKEN
depends on !(M32R || S390) || BROKEN
select SCSI
select GLOB
---help---
Expand Down Expand Up @@ -80,6 +80,8 @@ config SATA_PMP
This option adds support for SATA Port Multipliers
(the SATA version of an ethernet hub, or SAS expander).

if HAS_DMA

comment "Controllers with non-SFF native interface"

config SATA_AHCI
Expand Down Expand Up @@ -127,6 +129,7 @@ config AHCI_ST
config AHCI_IMX
tristate "Freescale i.MX AHCI SATA support"
depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST)
depends on (HWMON && (THERMAL || !THERMAL_OF)) || !HWMON
help
This option enables support for the Freescale i.MX SoC's
onboard AHCI SATA.
Expand Down Expand Up @@ -232,6 +235,8 @@ config SATA_SIL24

If unsure, say N.

endif # HAS_DMA

config ATA_SFF
bool "ATA SFF support (for legacy IDE and PATA)"
default y
Expand Down Expand Up @@ -289,6 +294,7 @@ config SATA_SX4

config ATA_BMDMA
bool "ATA BMDMA support"
depends on HAS_DMA
default y
help
This option adds support for SFF ATA controllers with BMDMA
Expand Down Expand Up @@ -344,6 +350,7 @@ config SATA_DWC_VDEBUG

config SATA_HIGHBANK
tristate "Calxeda Highbank SATA support"
depends on HAS_DMA
depends on ARCH_HIGHBANK || COMPILE_TEST
help
This option enables support for the Calxeda Highbank SoC's
Expand All @@ -353,6 +360,7 @@ config SATA_HIGHBANK

config SATA_MV
tristate "Marvell SATA support"
depends on HAS_DMA
depends on PCI || ARCH_DOVE || ARCH_MV78XX0 || \
ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST
select GENERIC_PHY
Expand Down Expand Up @@ -895,6 +903,15 @@ config PATA_CMD640_PCI

If unsure, say N.

config PATA_FALCON
tristate "Atari Falcon PATA support"
depends on M68K && ATARI
help
This option enables support for the on-board IDE
interface on the Atari Falcon.

If unsure, say N.

config PATA_ISAPNP
tristate "ISA Plug and Play PATA support"
depends on ISAPNP
Expand Down
1 change: 1 addition & 0 deletions drivers/ata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
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
obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
Expand Down
196 changes: 196 additions & 0 deletions drivers/ata/ahci_imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/libata.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/thermal.h>
#include "ahci.h"

#define DRV_NAME "ahci-imx"
Expand Down Expand Up @@ -214,6 +217,180 @@ static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
return timeout ? 0 : -ETIMEDOUT;
}

enum {
/* SATA PHY Register */
SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
};

static int read_adc_sum(void *dev, u16 rtune_ctl_reg, void __iomem * mmio)
{
u16 adc_out_reg, read_sum;
u32 index, read_attempt;
const u32 attempt_limit = 100;

imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
imx_phy_reg_write(rtune_ctl_reg, mmio);

/* two dummy read */
index = 0;
read_attempt = 0;
adc_out_reg = 0;
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
while (index < 2) {
imx_phy_reg_read(&adc_out_reg, mmio);
/* check if valid */
if (adc_out_reg & 0x400)
index++;

read_attempt++;
if (read_attempt > attempt_limit) {
dev_err(dev, "Read REG more than %d times!\n",
attempt_limit);
break;
}
}

index = 0;
read_attempt = 0;
read_sum = 0;
while (index < 80) {
imx_phy_reg_read(&adc_out_reg, mmio);
if (adc_out_reg & 0x400) {
read_sum = read_sum + (adc_out_reg & 0x3FF);
index++;
}
read_attempt++;
if (read_attempt > attempt_limit) {
dev_err(dev, "Read REG more than %d times!\n",
attempt_limit);
break;
}
}

/* Use the U32 to make 1000 precision */
return (read_sum * 1000) / 80;
}

/* SATA AHCI temperature monitor */
static int sata_ahci_read_temperature(void *dev, int *temp)
{
u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, read_sum;
u32 str1, str2, str3, str4;
int m1, m2, a;
struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
void __iomem *mmio = hpriv->mmio;

/* check rd-wr to reg */
read_sum = 0;
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
imx_phy_reg_write(read_sum, mmio);
imx_phy_reg_read(&read_sum, mmio);
if ((read_sum & 0xffff) != 0)
dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);

imx_phy_reg_write(0x5A5A, mmio);
imx_phy_reg_read(&read_sum, mmio);
if ((read_sum & 0xffff) != 0x5A5A)
dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);

imx_phy_reg_write(0x1234, mmio);
imx_phy_reg_read(&read_sum, mmio);
if ((read_sum & 0xffff) != 0x1234)
dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);

/* start temperature test */
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
imx_phy_reg_read(&mpll_test_reg, mmio);
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
imx_phy_reg_read(&rtune_ctl_reg, mmio);
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
imx_phy_reg_read(&dac_ctl_reg, mmio);

/* mpll_tst.meas_iv ([12:2]) */
str1 = (mpll_test_reg >> 2) & 0x7FF;
/* rtune_ctl.mode ([1:0]) */
str2 = (rtune_ctl_reg) & 0x3;
/* dac_ctl.dac_mode ([14:12]) */
str3 = (dac_ctl_reg >> 12) & 0x7;
/* rtune_ctl.sel_atbp ([4]) */
str4 = (rtune_ctl_reg >> 4);

/* Calculate the m1 */
/* mpll_tst.meas_iv */
mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
/* rtune_ctl.mode */
rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
/* dac_ctl.dac_mode */
dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
/* rtune_ctl.sel_atbp */
rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
imx_phy_reg_write(mpll_test_reg, mmio);
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
imx_phy_reg_write(dac_ctl_reg, mmio);
m1 = read_adc_sum(dev, rtune_ctl_reg, mmio);

/* Calculate the m2 */
/* rtune_ctl.sel_atbp */
rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (1) << 4;
m2 = read_adc_sum(dev, rtune_ctl_reg, mmio);

/* restore the status */
/* mpll_tst.meas_iv */
mpll_test_reg = (mpll_test_reg & 0xE03) | (str1) << 2;
/* rtune_ctl.mode */
rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (str2);
/* dac_ctl.dac_mode */
dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (str3) << 12;
/* rtune_ctl.sel_atbp */
rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (str4) << 4;

imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
imx_phy_reg_write(mpll_test_reg, mmio);
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
imx_phy_reg_write(dac_ctl_reg, mmio);
imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
imx_phy_reg_write(rtune_ctl_reg, mmio);

/* Compute temperature */
if (!(m2 / 1000))
m2 = 1000;
a = (m2 - m1) / (m2/1000);
*temp = ((-559) * a * a) / 1000 + (1379) * a + (-458000);

return 0;
}

static ssize_t sata_ahci_show_temp(struct device *dev,
struct device_attribute *da,
char *buf)
{
unsigned int temp = 0;
int err;

err = sata_ahci_read_temperature(dev, &temp);
if (err < 0)
return err;

return sprintf(buf, "%u\n", temp);
}

static const struct thermal_zone_of_device_ops fsl_sata_ahci_of_thermal_ops = {
.get_temp = sata_ahci_read_temperature,
};

static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sata_ahci_show_temp, NULL, 0);

static struct attribute *fsl_sata_ahci_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL
};
ATTRIBUTE_GROUPS(fsl_sata_ahci);

static int imx_sata_enable(struct ahci_host_priv *hpriv)
{
struct imx_ahci_priv *imxpriv = hpriv->plat_data;
Expand Down Expand Up @@ -597,6 +774,25 @@ static int imx_ahci_probe(struct platform_device *pdev)
if (ret)
return ret;

if (imxpriv->type == AHCI_IMX53 &&
IS_ENABLED(CONFIG_HWMON)) {
/* Add the temperature monitor */
struct device *hwmon_dev;

hwmon_dev =
devm_hwmon_device_register_with_groups(dev,
"sata_ahci",
hpriv,
fsl_sata_ahci_groups);
if (IS_ERR(hwmon_dev)) {
ret = PTR_ERR(hwmon_dev);
goto disable_clk;
}
devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
&fsl_sata_ahci_of_thermal_ops);
dev_info(dev, "%s: sensor 'sata_ahci'\n", dev_name(hwmon_dev));
}

ret = imx_sata_enable(hpriv);
if (ret)
goto disable_clk;
Expand Down
35 changes: 29 additions & 6 deletions drivers/ata/ahci_qoriq.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,29 @@
#define LS1021A_AXICC_ADDR 0xC0

#define SATA_ECC_DISABLE 0x00020000
#define LS1046A_SATA_ECC_DIS 0x80000000
#define ECC_DIS_ARMV8_CH2 0x80000000

enum ahci_qoriq_type {
AHCI_LS1021A,
AHCI_LS1043A,
AHCI_LS2080A,
AHCI_LS1046A,
AHCI_LS2088A,
};

struct ahci_qoriq_priv {
struct ccsr_ahci *reg_base;
enum ahci_qoriq_type type;
void __iomem *ecc_addr;
bool is_dmacoherent;
};

static const struct of_device_id ahci_qoriq_of_match[] = {
{ .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A},
{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
{ .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
{ .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
{ .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A},
{},
};
MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
Expand Down Expand Up @@ -157,33 +160,52 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)

switch (qpriv->type) {
case AHCI_LS1021A:
if (!qpriv->ecc_addr)
return -EINVAL;
writel(SATA_ECC_DISABLE, qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(LS1021A_PORT_PHY2, reg_base + PORT_PHY2);
writel(LS1021A_PORT_PHY3, reg_base + PORT_PHY3);
writel(LS1021A_PORT_PHY4, reg_base + PORT_PHY4);
writel(LS1021A_PORT_PHY5, reg_base + PORT_PHY5);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
writel(AHCI_PORT_AXICC_CFG, reg_base + LS1021A_AXICC_ADDR);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG,
reg_base + LS1021A_AXICC_ADDR);
break;

case AHCI_LS1043A:
if (!qpriv->ecc_addr)
return -EINVAL;
writel(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);
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;

case AHCI_LS2080A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;

case AHCI_LS1046A:
writel(LS1046A_SATA_ECC_DIS, qpriv->ecc_addr);
if (!qpriv->ecc_addr)
return -EINVAL;
writel(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);
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;

case AHCI_LS2088A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;
}

Expand Down Expand Up @@ -221,6 +243,7 @@ static int ahci_qoriq_probe(struct platform_device *pdev)
if (IS_ERR(qoriq_priv->ecc_addr))
return PTR_ERR(qoriq_priv->ecc_addr);
}
qoriq_priv->is_dmacoherent = of_dma_is_coherent(np);

rc = ahci_platform_enable_resources(hpriv);
if (rc)
Expand Down
Loading

0 comments on commit 79f4d1d

Please sign in to comment.