[U-Boot] [PATCH 1/4] sata: sata_mv: Add DM support to enable CONFIG_BLK usage

This patch adds DM support to the Armada XP SATA driver. This is needed to enable CONFIG_BLK on this platform. It adds the SATA controller as AHCI device, which is strictly speaking not correct, as the controller is not AHCI compatible. But the U-Boot AHCI uclass interface enables the usage of this DM driver and the creation of the corresponding BLK devices.
This conversion is done to get rid of the compile warning: ===================== WARNING ====================== This board does not use CONFIG_DM_SCSI. Please update the storage controller to use CONFIG_DM_SCSI before the v2019.07 release. Failure to update by the deadline may result in board removal. See doc/driver-model/MIGRATION.txt for more info. ====================================================
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com --- drivers/ata/Kconfig | 2 + drivers/ata/sata_mv.c | 344 ++++++++++++++++++++++++------------------ 2 files changed, 197 insertions(+), 149 deletions(-)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 49a056e941..7ebee75c0a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -81,7 +81,9 @@ config MVSATA_IDE
config SATA_MV bool "Enable Marvell SATA controller driver support" + select AHCI select LIBATA + depends on BLK help Enable this driver to support the SATA controller found in some Marvell SoCs. diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a168196fd4..d13695d79e 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -3,7 +3,7 @@ * Copyright (C) Excito Elektronik i Skåne AB, 2010. * Author: Tor Krill tor@excito.com * - * Copyright (C) 2015 Stefan Roese sr@denx.de + * Copyright (C) 2015, 2019 Stefan Roese sr@denx.de */
/* @@ -32,6 +32,10 @@ */
#include <common.h> +#include <ahci.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> #include <fis.h> #include <libata.h> #include <malloc.h> @@ -256,6 +260,7 @@ struct mv_priv { u16 pio; u16 mwdma; u16 udma; + int dev_nr;
void *crqb_alloc; struct crqb *request; @@ -278,9 +283,9 @@ static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec) }
/* Cut from sata_mv in linux kernel */ -static int mv_stop_edma_engine(int port) +static int mv_stop_edma_engine(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); int i;
/* Disable eDMA. The disable bit auto clears. */ @@ -299,9 +304,9 @@ static int mv_stop_edma_engine(int port) return -1; }
-static int mv_start_edma_engine(int port) +static int mv_start_edma_engine(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp;
/* Check preconditions */ @@ -351,12 +356,12 @@ static int mv_start_edma_engine(int port) return 0; }
-static int mv_reset_channel(int port) +static int mv_reset_channel(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev);
/* Make sure edma is stopped */ - mv_stop_edma_engine(port); + mv_stop_edma_engine(dev, port);
out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST); udelay(25); /* allow reset propagation */ @@ -366,11 +371,11 @@ static int mv_reset_channel(int port) return 0; }
-static void mv_reset_port(int port) +static void mv_reset_port(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev);
- mv_reset_channel(port); + mv_reset_channel(dev, port);
out_le32(priv->regbase + EDMA_CMD, 0x0); out_le32(priv->regbase + EDMA_CFG, 0x101f); @@ -392,9 +397,9 @@ static void mv_reset_one_hc(void) out_le32(SATAHC_BASE + SATAHC_ICR, 0x00); }
-static int probe_port(int port) +static int probe_port(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); int tries, tries2, set15 = 0; u32 tmp;
@@ -446,7 +451,7 @@ static int probe_port(int port) tmp &= ~SIR_CFG_GEN2EN; out_le32(priv->regbase + SIR_ICFG, tmp);
- mv_reset_channel(port); + mv_reset_channel(dev, port); } }
@@ -455,9 +460,9 @@ static int probe_port(int port) }
/* Get request queue in pointer */ -static int get_reqip(int port) +static int get_reqip(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp;
tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK; @@ -466,9 +471,9 @@ static int get_reqip(int port) return tmp; }
-static void set_reqip(int port, int reqin) +static void set_reqip(struct udevice *dev, int port, int reqin) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp;
tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK; @@ -477,17 +482,17 @@ static void set_reqip(int port, int reqin) }
/* Get next available slot, ignoring possible overwrite */ -static int get_next_reqip(int port) +static int get_next_reqip(struct udevice *dev, int port) { - int slot = get_reqip(port); + int slot = get_reqip(dev, port); slot = (slot + 1) % REQUEST_QUEUE_SIZE; return slot; }
/* Get response queue in pointer */ -static int get_rspip(int port) +static int get_rspip(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp;
tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK; @@ -497,9 +502,9 @@ static int get_rspip(int port) }
/* Get response queue out pointer */ -static int get_rspop(int port) +static int get_rspop(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp;
tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK; @@ -508,15 +513,15 @@ static int get_rspop(int port) }
/* Get next response queue pointer */ -static int get_next_rspop(int port) +static int get_next_rspop(struct udevice *dev, int port) { - return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE; + return (get_rspop(dev, port) + 1) % RESPONSE_QUEUE_SIZE; }
/* Set response queue pointer */ -static void set_rspop(int port, int reqin) +static void set_rspop(struct udevice *dev, int port, int reqin) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp;
tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK; @@ -525,7 +530,8 @@ static void set_rspop(int port, int reqin) out_le32(priv->regbase + EDMA_RSOPR, tmp); }
-static int wait_dma_completion(int port, int index, u32 timeout_msec) +static int wait_dma_completion(struct udevice *dev, int port, int index, + u32 timeout_msec) { u32 tmp, res;
@@ -538,13 +544,13 @@ static int wait_dma_completion(int port, int index, u32 timeout_msec) return res; }
-static void process_responses(int port) +static void process_responses(struct udevice *dev, int port) { #ifdef DEBUG - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); #endif u32 tmp; - u32 outind = get_rspop(port); + u32 outind = get_rspop(dev, port);
/* Ack interrupts */ tmp = in_le32(SATAHC_BASE + SATAHC_ICR); @@ -555,20 +561,21 @@ static void process_responses(int port) tmp &= ~(BIT(4)); out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
- while (get_rspip(port) != outind) { + while (get_rspip(dev, port) != outind) { #ifdef DEBUG debug("Response index %d flags %08x on port %d\n", outind, priv->response[outind].flags, port); #endif - outind = get_next_rspop(port); - set_rspop(port, outind); + outind = get_next_rspop(dev, port); + set_rspop(dev, port, outind); } }
-static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, +static int mv_ata_exec_ata_cmd(struct udevice *dev, int port, + struct sata_fis_h2d *cfis, u8 *buffer, u32 len, u32 iswrite) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); struct crqb *req; int slot; u32 start; @@ -579,7 +586,7 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, }
/* Initialize request */ - slot = get_reqip(port); + slot = get_reqip(dev, port); memset(&priv->request[slot], 0, sizeof(struct crqb)); req = &priv->request[slot];
@@ -633,16 +640,16 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN));
/* Trigger operation */ - slot = get_next_reqip(port); - set_reqip(port, slot); + slot = get_next_reqip(dev, port); + set_reqip(dev, port, slot);
/* Wait for completion */ - if (wait_dma_completion(port, slot, 10000)) { + if (wait_dma_completion(dev, port, slot, 10000)) { printf("ATA operation timed out\n"); return -1; }
- process_responses(port); + process_responses(dev, port);
/* Invalidate data on read */ if (buffer && len) { @@ -654,7 +661,8 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, return len; }
-static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, +static u32 mv_sata_rw_cmd_ext(struct udevice *dev, int port, lbaint_t start, + u32 blkcnt, u8 *buffer, int is_write) { struct sata_fis_h2d cfis; @@ -678,14 +686,14 @@ static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, cfis.sector_count_exp = (blkcnt >> 8) & 0xff; cfis.sector_count = blkcnt & 0xff;
- res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt, - is_write); + res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer, + ATA_SECT_SIZE * blkcnt, is_write);
return res >= 0 ? blkcnt : res; }
-static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer, - int is_write) +static u32 mv_sata_rw_cmd(struct udevice *dev, int port, lbaint_t start, + u32 blkcnt, u8 *buffer, int is_write) { struct sata_fis_h2d cfis; lbaint_t block; @@ -705,15 +713,16 @@ static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer, cfis.lba_low = block & 0xff; cfis.sector_count = (u8)(blkcnt & 0xff);
- res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt, - is_write); + res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer, + ATA_SECT_SIZE * blkcnt, is_write);
return res >= 0 ? blkcnt : res; }
-static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer, int is_write) +static u32 ata_low_level_rw(struct udevice *dev, int port, lbaint_t blknr, + lbaint_t blkcnt, void *buffer, int is_write) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); lbaint_t start, blks; u8 *addr; int max_blks; @@ -727,22 +736,22 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, max_blks = MV_ATA_MAX_SECTORS; do { if (blks > max_blks) { - if (sata_dev_desc[dev].lba48) { - mv_sata_rw_cmd_ext(dev, start, max_blks, addr, - is_write); + if (desc->lba48) { + mv_sata_rw_cmd_ext(dev, port, start, max_blks, + addr, is_write); } else { - mv_sata_rw_cmd(dev, start, max_blks, addr, - is_write); + mv_sata_rw_cmd(dev, port, start, max_blks, + addr, is_write); } start += max_blks; blks -= max_blks; addr += ATA_SECT_SIZE * max_blks; } else { - if (sata_dev_desc[dev].lba48) { - mv_sata_rw_cmd_ext(dev, start, blks, addr, + if (desc->lba48) { + mv_sata_rw_cmd_ext(dev, port, start, blks, addr, is_write); } else { - mv_sata_rw_cmd(dev, start, blks, addr, + mv_sata_rw_cmd(dev, port, start, blks, addr, is_write); } start += blks; @@ -754,11 +763,11 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, return blkcnt; }
-static int mv_ata_exec_ata_cmd_nondma(int port, +static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port, struct sata_fis_h2d *cfis, u8 *buffer, u32 len, u32 iswrite) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); int i; u16 *tp;
@@ -791,7 +800,7 @@ static int mv_ata_exec_ata_cmd_nondma(int port, return len; }
-static int mv_sata_identify(int port, u16 *id) +static int mv_sata_identify(struct udevice *dev, int port, u16 *id) { struct sata_fis_h2d h2d;
@@ -803,13 +812,13 @@ static int mv_sata_identify(int port, u16 *id) /* Give device time to get operational */ mdelay(10);
- return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id, + return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id, ATA_ID_WORDS * 2, READ_CMD); }
-static void mv_sata_xfer_mode(int port, u16 *id) +static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev);
priv->pio = id[ATA_ID_PIO_MODES]; priv->mwdma = id[ATA_ID_MWDMA_MODES]; @@ -818,9 +827,9 @@ static void mv_sata_xfer_mode(int port, u16 *id) priv->udma); }
-static void mv_sata_set_features(int port) +static void mv_sata_set_features(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); struct sata_fis_h2d cfis; u8 udma_cap;
@@ -842,53 +851,7 @@ static void mv_sata_set_features(int port) if (udma_cap == ATA_UDMA3) cfis.sector_count = XFER_UDMA_3;
- mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD); -} - -int mv_sata_spin_down(int dev) -{ - struct sata_fis_h2d cfis; - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv; - - if (priv->link == 0) { - debug("No device on port: %d\n", dev); - return 1; - } - - memset(&cfis, 0, sizeof(struct sata_fis_h2d)); - - cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; - cfis.command = ATA_CMD_STANDBY; - - return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD); -} - -int mv_sata_spin_up(int dev) -{ - struct sata_fis_h2d cfis; - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv; - - if (priv->link == 0) { - debug("No device on port: %d\n", dev); - return 1; - } - - memset(&cfis, 0, sizeof(struct sata_fis_h2d)); - - cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; - cfis.command = ATA_CMD_IDLE; - - return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD); -} - -ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) -{ - return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD); -} - -ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) -{ - return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD); + mv_ata_exec_ata_cmd_nondma(dev, port, &cfis, NULL, 0, READ_CMD); }
/* @@ -916,25 +879,17 @@ static void mvsata_ide_conf_mbus_windows(void) } }
-int init_sata(int dev) +static int sata_mv_init_sata(struct udevice *dev, int port) { - struct mv_priv *priv; + struct mv_priv *priv = dev_get_platdata(dev);
- debug("Initialize sata dev: %d\n", dev); + debug("Initialize sata dev: %d\n", port);
- if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) { - printf("Invalid sata device %d\n", dev); + if (port < 0 || port >= CONFIG_SYS_SATA_MAX_DEVICE) { + printf("Invalid sata device %d\n", port); return -1; }
- priv = (struct mv_priv *)malloc(sizeof(struct mv_priv)); - if (!priv) { - printf("Failed to allocate memory for private sata data\n"); - return -ENOMEM; - } - - memset((void *)priv, 0, sizeof(struct mv_priv)); - /* Allocate and align request buffer */ priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE + CRQB_ALIGN); @@ -959,11 +914,9 @@ int init_sata(int dev) priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) & ~(CRPB_ALIGN - 1));
- sata_dev_desc[dev].priv = (void *)priv; + sprintf(priv->name, "SATA%d", port);
- sprintf(priv->name, "SATA%d", dev); - - priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE; + priv->regbase = port == 0 ? SATA0_BASE : SATA1_BASE;
if (!hw_init) { debug("Initialize sata hw\n"); @@ -972,9 +925,9 @@ int init_sata(int dev) mvsata_ide_conf_mbus_windows(); }
- mv_reset_port(dev); + mv_reset_port(dev, port);
- if (probe_port(dev)) { + if (probe_port(dev, port)) { priv->link = 0; return -ENODEV; } @@ -983,19 +936,15 @@ int init_sata(int dev) return 0; }
-int reset_sata(int dev) -{ - return 0; -} - -int scan_sata(int port) +static int sata_mv_scan_sata(struct udevice *dev, int port) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + struct mv_priv *priv = dev_get_platdata(dev); unsigned char serial[ATA_ID_SERNO_LEN + 1]; unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; unsigned char product[ATA_ID_PROD_LEN + 1]; u64 n_sectors; u16 *id; - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
if (!priv->link) return -ENODEV; @@ -1006,7 +955,7 @@ int scan_sata(int port) return -ENOMEM; }
- mv_sata_identify(port, id); + mv_sata_identify(dev, port, id); ata_swap_buf_le16(id, ATA_ID_WORDS); #ifdef DEBUG ata_dump_id(id); @@ -1014,23 +963,23 @@ int scan_sata(int port)
/* Serial number */ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); - memcpy(sata_dev_desc[port].product, serial, sizeof(serial)); + memcpy(desc->product, serial, sizeof(serial));
/* Firmware version */ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); - memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware)); + memcpy(desc->revision, firmware, sizeof(firmware));
/* Product model */ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); - memcpy(sata_dev_desc[port].vendor, product, sizeof(product)); + memcpy(desc->vendor, product, sizeof(product));
/* Total sectors */ n_sectors = ata_id_n_sectors(id); - sata_dev_desc[port].lba = n_sectors; + desc->lba = n_sectors;
/* Check if support LBA48 */ if (ata_id_has_lba48(id)) { - sata_dev_desc[port].lba48 = 1; + desc->lba48 = 1; debug("Device support LBA48\n"); }
@@ -1038,13 +987,110 @@ int scan_sata(int port) priv->queue_depth = ata_id_queue_depth(id);
/* Get the xfer mode from device */ - mv_sata_xfer_mode(port, id); + mv_sata_xfer_mode(dev, port, id);
/* Set the xfer mode to highest speed */ - mv_sata_set_features(port); + mv_sata_set_features(dev, port);
/* Start up */ - mv_start_edma_engine(port); + mv_start_edma_engine(dev, port);
return 0; } + +static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + struct mv_priv *priv = dev_get_platdata(blk); + + return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt, + buffer, READ_CMD); +} + +static ulong sata_mv_write(struct udevice *blk, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + struct mv_priv *priv = dev_get_platdata(blk); + + return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt, + (void *)buffer, WRITE_CMD); +} + +static const struct blk_ops sata_mv_blk_ops = { + .read = sata_mv_read, + .write = sata_mv_write, +}; + +U_BOOT_DRIVER(sata_mv_driver) = { + .name = "sata_mv_blk", + .id = UCLASS_BLK, + .ops = &sata_mv_blk_ops, + .platdata_auto_alloc_size = sizeof(struct mv_priv), +}; + +static int sata_mv_probe(struct udevice *dev) +{ + const void *blob = gd->fdt_blob; + int node = dev_of_offset(dev); + struct mv_priv *priv; + struct udevice *blk; + int nr_ports; + int ret; + int i; + + /* Get number of ports of this SATA controller */ + nr_ports = min(fdtdec_get_int(blob, node, "nr-ports", -1), + CONFIG_SYS_SATA_MAX_DEVICE); + + for (i = 0; i < nr_ports; i++) { + ret = blk_create_devicef(dev, "sata_mv_blk", "blk", + IF_TYPE_SATA, -1, 512, 0, &blk); + if (ret) { + debug("Can't create device\n"); + return ret; + } + + priv = dev_get_platdata(blk); + priv->dev_nr = i; + + /* Init SATA port */ + ret = sata_mv_init_sata(blk, i); + if (ret) { + debug("%s: Failed to init bus\n", __func__); + return ret; + } + + /* Scan SATA port */ + ret = sata_mv_scan_sata(blk, i); + if (ret) { + debug("%s: Failed to scan bus\n", __func__); + return ret; + } + } + + return 0; +} + +static int sata_mv_scan(struct udevice *dev) +{ + /* Nothing to do here */ + + return 0; +} + +static const struct udevice_id sata_mv_ids[] = { + { .compatible = "marvell,armada-370-sata" }, + { } +}; + +struct ahci_ops sata_mv_ahci_ops = { + .scan = sata_mv_scan, +}; + +U_BOOT_DRIVER(sata_mv_ahci) = { + .name = "sata_mv_ahci", + .id = UCLASS_AHCI, + .of_match = sata_mv_ids, + .ops = &sata_mv_ahci_ops, + .probe = sata_mv_probe, +};

This patch enables CONFIG_BLK as this is now possible with the recent DM conversion of the Armada XP SATA driver.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com --- configs/theadorable_debug_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig index a7d02e957a..1573b5f544 100644 --- a/configs/theadorable_debug_defconfig +++ b/configs/theadorable_debug_defconfig @@ -49,6 +49,7 @@ CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_SATA_MV=y +CONFIG_BLK=y CONFIG_BOOTCOUNT_LIMIT=y CONFIG_BOOTCOUNT_RAM=y CONFIG_FPGA_ALTERA=y

On 11.03.19 13:29, Stefan Roese wrote:
This patch enables CONFIG_BLK as this is now possible with the recent DM conversion of the Armada XP SATA driver.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Applied to u-boot-marvell/master.
Thanks, Stefan

This patch enables CONFIG_BLK as this is now possible with the recent DM conversion of the Armada XP SATA driver.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com --- configs/db-mv784mp-gp_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig index b6c61c3a48..feea5d9f42 100644 --- a/configs/db-mv784mp-gp_defconfig +++ b/configs/db-mv784mp-gp_defconfig @@ -44,6 +44,7 @@ CONFIG_EFI_PARTITION=y CONFIG_DEFAULT_DEVICE_TREE="armada-xp-gp" CONFIG_SPL_OF_TRANSLATE=y CONFIG_SATA_MV=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_NAND=y CONFIG_NAND_PXA3XX=y

On 11.03.19 13:29, Stefan Roese wrote:
This patch enables CONFIG_BLK as this is now possible with the recent DM conversion of the Armada XP SATA driver.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Applied to u-boot-marvell/master.
Thanks, Stefan

When checking for boards that are enabling a SATA driver that isn't converted to DM yet we need to be sure to not also trip over boards that do set CONFIG_AHCI & CONFIG_BLK by itself, as that is not a bug.
This was detected when converting the Armada XP SATA driver sata_mv.c to DM with AHCI & BLK support. This warning is still printed without this patch applied here.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com --- Makefile | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/Makefile b/Makefile index 26db4e7b59..896e0c3350 100644 --- a/Makefile +++ b/Makefile @@ -940,6 +940,7 @@ endif endif ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y) ifneq ($(CONFIG_DM_SCSI),y) +ifneq ($(CONFIG_BLK)$(CONFIG_AHCI),yy) @echo >&2 "===================== WARNING ======================" @echo >&2 "This board does not use CONFIG_DM_SCSI. Please update" @echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release." @@ -948,6 +949,7 @@ ifneq ($(CONFIG_DM_SCSI),y) @echo >&2 "====================================================" endif endif +endif ifeq ($(CONFIG_PCI),y) ifneq ($(CONFIG_DM_PCI),y) @echo >&2 "===================== WARNING ======================"

On Mon, Mar 11, 2019 at 01:29:23PM +0100, Stefan Roese wrote:
When checking for boards that are enabling a SATA driver that isn't converted to DM yet we need to be sure to not also trip over boards that do set CONFIG_AHCI & CONFIG_BLK by itself, as that is not a bug.
This was detected when converting the Armada XP SATA driver sata_mv.c to DM with AHCI & BLK support. This warning is still printed without this patch applied here.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Makefile | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/Makefile b/Makefile index 26db4e7b59..896e0c3350 100644 --- a/Makefile +++ b/Makefile @@ -940,6 +940,7 @@ endif endif ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y) ifneq ($(CONFIG_DM_SCSI),y) +ifneq ($(CONFIG_BLK)$(CONFIG_AHCI),yy) @echo >&2 "===================== WARNING ======================" @echo >&2 "This board does not use CONFIG_DM_SCSI. Please update" @echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release."
OK, I think we need to properly clarify the logic, and perhaps I was being too clever trying to catch all of the cases under drivers/ata that aren't converted yet. We have, after your patches, afaict: - MVSATA_IDE - DWC_AHSATA - FSL_SATA - SATA_SIL - SATA_SIL3114
Of these, MVSATA_IDE has no further deps. Everything else depends on LIBATA. Before SATA_MV was converted, everything that was converted depends on DM_SCSI and AHCI. So I made my messages / logic like the above. But perhaps the right answer really is: 1) MVSATA_IDE alone. 2) LIBATA && !AHCI
So... we can just re-work the second part of the check logic to be what you added, as all converted drivers under drivers/ata will be both BLK&&AHCI enabled.
And also as you note, it's not quite AHCI as the controller in question here isn't AHCI-compatible, but is SATA, so a fixup / rename of some CONFIG checks in code / Kconfig is in order, somewhere, but perhaps after conversion? Also, probably some re-organization of drivers/block, drivers/ide, drivers/ata, drivers/nvme (and common/usb_storage.c) too, to be more consistent.

On 11.03.19 15:09, Tom Rini wrote:
On Mon, Mar 11, 2019 at 01:29:23PM +0100, Stefan Roese wrote:
When checking for boards that are enabling a SATA driver that isn't converted to DM yet we need to be sure to not also trip over boards that do set CONFIG_AHCI & CONFIG_BLK by itself, as that is not a bug.
This was detected when converting the Armada XP SATA driver sata_mv.c to DM with AHCI & BLK support. This warning is still printed without this patch applied here.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Makefile | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/Makefile b/Makefile index 26db4e7b59..896e0c3350 100644 --- a/Makefile +++ b/Makefile @@ -940,6 +940,7 @@ endif endif ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y) ifneq ($(CONFIG_DM_SCSI),y) +ifneq ($(CONFIG_BLK)$(CONFIG_AHCI),yy) @echo >&2 "===================== WARNING ======================" @echo >&2 "This board does not use CONFIG_DM_SCSI. Please update" @echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release."
OK, I think we need to properly clarify the logic, and perhaps I was being too clever trying to catch all of the cases under drivers/ata that aren't converted yet. We have, after your patches, afaict:
- MVSATA_IDE
- DWC_AHSATA
- FSL_SATA
- SATA_SIL
- SATA_SIL3114
Of these, MVSATA_IDE has no further deps. Everything else depends on LIBATA. Before SATA_MV was converted, everything that was converted depends on DM_SCSI and AHCI. So I made my messages / logic like the above. But perhaps the right answer really is:
- MVSATA_IDE alone.
- LIBATA && !AHCI
So... we can just re-work the second part of the check logic to be what you added, as all converted drivers under drivers/ata will be both BLK&&AHCI enabled.
I'll work on a v2 of this patch shortly.
And also as you note, it's not quite AHCI as the controller in question here isn't AHCI-compatible, but is SATA, so a fixup / rename of some CONFIG checks in code / Kconfig is in order, somewhere, but perhaps after conversion?
I agree.
Also, probably some re-organization of drivers/block, drivers/ide, drivers/ata, drivers/nvme (and common/usb_storage.c) too, to be more consistent.
Yes, that could also be helpful.
Thanks, Stefan

When checking for boards that are enabling a SATA driver that isn't converted to DM yet we need to be sure to not also trip over boards that do set CONFIG_AHCI & CONFIG_BLK by itself, as that is not a bug.
This was detected when converting the Armada XP SATA driver sata_mv.c to DM with AHCI & BLK support. This warning is still printed without this patch applied here.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com --- v2: - Rework checks as suggested by Tom
Makefile | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile index 26db4e7b59..4f73d426af 100644 --- a/Makefile +++ b/Makefile @@ -938,11 +938,22 @@ ifneq ($(CONFIG_DM_USB)$(CONFIG_OF_CONTROL)$(CONFIG_BLK),yyy) @echo >&2 "====================================================" endif endif -ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y) -ifneq ($(CONFIG_DM_SCSI),y) +ifeq ($(CONFIG_MVSATA_IDE),y) @echo >&2 "===================== WARNING ======================" - @echo >&2 "This board does not use CONFIG_DM_SCSI. Please update" - @echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release." + @echo >&2 "This board does use CONFIG_MVSATA_IDE which is not" + @echo >&2 "ported to driver-model (DM) yet. Please update the storage" + @echo >&2 "controller driver to use CONFIG_AHCI before the v2019.07" + @echo >&2 "release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +ifeq ($(CONFIG_LIBATA),y) +ifneq ($(CONFIG_AHCI),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does use CONFIG_LIBATA but has CONFIG_AHCI not" + @echo >&2 "enabled. Please update the storage controller driver to use" + @echo >&2 "CONFIG_AHCI before the v2019.07 release." @echo >&2 "Failure to update by the deadline may result in board removal." @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." @echo >&2 "===================================================="

On Tue, Mar 12, 2019 at 07:46:35AM +0100, Stefan Roese wrote:
When checking for boards that are enabling a SATA driver that isn't converted to DM yet we need to be sure to not also trip over boards that do set CONFIG_AHCI & CONFIG_BLK by itself, as that is not a bug.
This was detected when converting the Armada XP SATA driver sata_mv.c to DM with AHCI & BLK support. This warning is still printed without this patch applied here.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Reviewed-by: Tom Rini trini@konsulko.com

On 12.03.19 07:46, Stefan Roese wrote:
When checking for boards that are enabling a SATA driver that isn't converted to DM yet we need to be sure to not also trip over boards that do set CONFIG_AHCI & CONFIG_BLK by itself, as that is not a bug.
This was detected when converting the Armada XP SATA driver sata_mv.c to DM with AHCI & BLK support. This warning is still printed without this patch applied here.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
v2:
- Rework checks as suggested by Tom
Applied to u-boot-marvell/master.
Thanks, Stefan

On Tue, Mar 12, 2019 at 1:30 AM Stefan Roese sr@denx.de wrote:
This patch adds DM support to the Armada XP SATA driver. This is needed to enable CONFIG_BLK on this platform. It adds the SATA controller as AHCI device, which is strictly speaking not correct, as the controller is not AHCI compatible. But the U-Boot AHCI uclass interface enables the usage of this DM driver and the creation of the corresponding BLK devices.
This conversion is done to get rid of the compile warning: ===================== WARNING ====================== This board does not use CONFIG_DM_SCSI. Please update the storage controller to use CONFIG_DM_SCSI before the v2019.07 release. Failure to update by the deadline may result in board removal. See doc/driver-model/MIGRATION.txt for more info. ====================================================
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Reviewed-by: Chris Packham judge.packham@gmail.com
drivers/ata/Kconfig | 2 + drivers/ata/sata_mv.c | 344 ++++++++++++++++++++++++------------------ 2 files changed, 197 insertions(+), 149 deletions(-)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 49a056e941..7ebee75c0a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -81,7 +81,9 @@ config MVSATA_IDE
config SATA_MV bool "Enable Marvell SATA controller driver support"
select AHCI select LIBATA
depends on BLK help Enable this driver to support the SATA controller found in some Marvell SoCs.
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a168196fd4..d13695d79e 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -3,7 +3,7 @@
- Copyright (C) Excito Elektronik i Skåne AB, 2010.
- Author: Tor Krill tor@excito.com
- Copyright (C) 2015 Stefan Roese sr@denx.de
*/
- Copyright (C) 2015, 2019 Stefan Roese sr@denx.de
/* @@ -32,6 +32,10 @@ */
#include <common.h> +#include <ahci.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> #include <fis.h> #include <libata.h> #include <malloc.h> @@ -256,6 +260,7 @@ struct mv_priv { u16 pio; u16 mwdma; u16 udma;
int dev_nr; void *crqb_alloc; struct crqb *request;
@@ -278,9 +283,9 @@ static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec) }
/* Cut from sata_mv in linux kernel */ -static int mv_stop_edma_engine(int port) +static int mv_stop_edma_engine(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); int i; /* Disable eDMA. The disable bit auto clears. */
@@ -299,9 +304,9 @@ static int mv_stop_edma_engine(int port) return -1; }
-static int mv_start_edma_engine(int port) +static int mv_start_edma_engine(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; /* Check preconditions */
@@ -351,12 +356,12 @@ static int mv_start_edma_engine(int port) return 0; }
-static int mv_reset_channel(int port) +static int mv_reset_channel(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); /* Make sure edma is stopped */
mv_stop_edma_engine(port);
mv_stop_edma_engine(dev, port); out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST); udelay(25); /* allow reset propagation */
@@ -366,11 +371,11 @@ static int mv_reset_channel(int port) return 0; }
-static void mv_reset_port(int port) +static void mv_reset_port(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev);
mv_reset_channel(port);
mv_reset_channel(dev, port); out_le32(priv->regbase + EDMA_CMD, 0x0); out_le32(priv->regbase + EDMA_CFG, 0x101f);
@@ -392,9 +397,9 @@ static void mv_reset_one_hc(void) out_le32(SATAHC_BASE + SATAHC_ICR, 0x00); }
-static int probe_port(int port) +static int probe_port(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); int tries, tries2, set15 = 0; u32 tmp;
@@ -446,7 +451,7 @@ static int probe_port(int port) tmp &= ~SIR_CFG_GEN2EN; out_le32(priv->regbase + SIR_ICFG, tmp);
mv_reset_channel(port);
mv_reset_channel(dev, port); } }
@@ -455,9 +460,9 @@ static int probe_port(int port) }
/* Get request queue in pointer */ -static int get_reqip(int port) +static int get_reqip(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK;
@@ -466,9 +471,9 @@ static int get_reqip(int port) return tmp; }
-static void set_reqip(int port, int reqin) +static void set_reqip(struct udevice *dev, int port, int reqin) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK;
@@ -477,17 +482,17 @@ static void set_reqip(int port, int reqin) }
/* Get next available slot, ignoring possible overwrite */ -static int get_next_reqip(int port) +static int get_next_reqip(struct udevice *dev, int port) {
int slot = get_reqip(port);
int slot = get_reqip(dev, port); slot = (slot + 1) % REQUEST_QUEUE_SIZE; return slot;
}
/* Get response queue in pointer */ -static int get_rspip(int port) +static int get_rspip(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK;
@@ -497,9 +502,9 @@ static int get_rspip(int port) }
/* Get response queue out pointer */ -static int get_rspop(int port) +static int get_rspop(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK;
@@ -508,15 +513,15 @@ static int get_rspop(int port) }
/* Get next response queue pointer */ -static int get_next_rspop(int port) +static int get_next_rspop(struct udevice *dev, int port) {
return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE;
return (get_rspop(dev, port) + 1) % RESPONSE_QUEUE_SIZE;
}
/* Set response queue pointer */ -static void set_rspop(int port, int reqin) +static void set_rspop(struct udevice *dev, int port, int reqin) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK;
@@ -525,7 +530,8 @@ static void set_rspop(int port, int reqin) out_le32(priv->regbase + EDMA_RSOPR, tmp); }
-static int wait_dma_completion(int port, int index, u32 timeout_msec) +static int wait_dma_completion(struct udevice *dev, int port, int index,
u32 timeout_msec)
{ u32 tmp, res;
@@ -538,13 +544,13 @@ static int wait_dma_completion(int port, int index, u32 timeout_msec) return res; }
-static void process_responses(int port) +static void process_responses(struct udevice *dev, int port) { #ifdef DEBUG
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev);
#endif u32 tmp;
u32 outind = get_rspop(port);
u32 outind = get_rspop(dev, port); /* Ack interrupts */ tmp = in_le32(SATAHC_BASE + SATAHC_ICR);
@@ -555,20 +561,21 @@ static void process_responses(int port) tmp &= ~(BIT(4)); out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
while (get_rspip(port) != outind) {
while (get_rspip(dev, port) != outind) {
#ifdef DEBUG debug("Response index %d flags %08x on port %d\n", outind, priv->response[outind].flags, port); #endif
outind = get_next_rspop(port);
set_rspop(port, outind);
outind = get_next_rspop(dev, port);
set_rspop(dev, port, outind); }
}
-static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, +static int mv_ata_exec_ata_cmd(struct udevice *dev, int port,
struct sata_fis_h2d *cfis, u8 *buffer, u32 len, u32 iswrite)
{
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); struct crqb *req; int slot; u32 start;
@@ -579,7 +586,7 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, }
/* Initialize request */
slot = get_reqip(port);
slot = get_reqip(dev, port); memset(&priv->request[slot], 0, sizeof(struct crqb)); req = &priv->request[slot];
@@ -633,16 +640,16 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN));
/* Trigger operation */
slot = get_next_reqip(port);
set_reqip(port, slot);
slot = get_next_reqip(dev, port);
set_reqip(dev, port, slot); /* Wait for completion */
if (wait_dma_completion(port, slot, 10000)) {
if (wait_dma_completion(dev, port, slot, 10000)) { printf("ATA operation timed out\n"); return -1; }
process_responses(port);
process_responses(dev, port); /* Invalidate data on read */ if (buffer && len) {
@@ -654,7 +661,8 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, return len; }
-static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, +static u32 mv_sata_rw_cmd_ext(struct udevice *dev, int port, lbaint_t start,
u32 blkcnt, u8 *buffer, int is_write)
{ struct sata_fis_h2d cfis; @@ -678,14 +686,14 @@ static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, cfis.sector_count_exp = (blkcnt >> 8) & 0xff; cfis.sector_count = blkcnt & 0xff;
res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
is_write);
res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer,
ATA_SECT_SIZE * blkcnt, is_write); return res >= 0 ? blkcnt : res;
}
-static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer,
int is_write)
+static u32 mv_sata_rw_cmd(struct udevice *dev, int port, lbaint_t start,
u32 blkcnt, u8 *buffer, int is_write)
{ struct sata_fis_h2d cfis; lbaint_t block; @@ -705,15 +713,16 @@ static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer, cfis.lba_low = block & 0xff; cfis.sector_count = (u8)(blkcnt & 0xff);
res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
is_write);
res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer,
ATA_SECT_SIZE * blkcnt, is_write); return res >= 0 ? blkcnt : res;
}
-static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt,
void *buffer, int is_write)
+static u32 ata_low_level_rw(struct udevice *dev, int port, lbaint_t blknr,
lbaint_t blkcnt, void *buffer, int is_write)
{
struct blk_desc *desc = dev_get_uclass_platdata(dev); lbaint_t start, blks; u8 *addr; int max_blks;
@@ -727,22 +736,22 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, max_blks = MV_ATA_MAX_SECTORS; do { if (blks > max_blks) {
if (sata_dev_desc[dev].lba48) {
mv_sata_rw_cmd_ext(dev, start, max_blks, addr,
is_write);
if (desc->lba48) {
mv_sata_rw_cmd_ext(dev, port, start, max_blks,
addr, is_write); } else {
mv_sata_rw_cmd(dev, start, max_blks, addr,
is_write);
mv_sata_rw_cmd(dev, port, start, max_blks,
addr, is_write); } start += max_blks; blks -= max_blks; addr += ATA_SECT_SIZE * max_blks; } else {
if (sata_dev_desc[dev].lba48) {
mv_sata_rw_cmd_ext(dev, start, blks, addr,
if (desc->lba48) {
mv_sata_rw_cmd_ext(dev, port, start, blks, addr, is_write); } else {
mv_sata_rw_cmd(dev, start, blks, addr,
mv_sata_rw_cmd(dev, port, start, blks, addr, is_write); } start += blks;
@@ -754,11 +763,11 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, return blkcnt; }
-static int mv_ata_exec_ata_cmd_nondma(int port, +static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port, struct sata_fis_h2d *cfis, u8 *buffer, u32 len, u32 iswrite) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); int i; u16 *tp;
@@ -791,7 +800,7 @@ static int mv_ata_exec_ata_cmd_nondma(int port, return len; }
-static int mv_sata_identify(int port, u16 *id) +static int mv_sata_identify(struct udevice *dev, int port, u16 *id) { struct sata_fis_h2d h2d;
@@ -803,13 +812,13 @@ static int mv_sata_identify(int port, u16 *id) /* Give device time to get operational */ mdelay(10);
return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id,
return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id, ATA_ID_WORDS * 2, READ_CMD);
}
-static void mv_sata_xfer_mode(int port, u16 *id) +static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); priv->pio = id[ATA_ID_PIO_MODES]; priv->mwdma = id[ATA_ID_MWDMA_MODES];
@@ -818,9 +827,9 @@ static void mv_sata_xfer_mode(int port, u16 *id) priv->udma); }
-static void mv_sata_set_features(int port) +static void mv_sata_set_features(struct udevice *dev, int port) {
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
struct mv_priv *priv = dev_get_platdata(dev); struct sata_fis_h2d cfis; u8 udma_cap;
@@ -842,53 +851,7 @@ static void mv_sata_set_features(int port) if (udma_cap == ATA_UDMA3) cfis.sector_count = XFER_UDMA_3;
mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD);
-}
-int mv_sata_spin_down(int dev) -{
struct sata_fis_h2d cfis;
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
if (priv->link == 0) {
debug("No device on port: %d\n", dev);
return 1;
}
memset(&cfis, 0, sizeof(struct sata_fis_h2d));
cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
cfis.command = ATA_CMD_STANDBY;
return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
-}
-int mv_sata_spin_up(int dev) -{
struct sata_fis_h2d cfis;
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
if (priv->link == 0) {
debug("No device on port: %d\n", dev);
return 1;
}
memset(&cfis, 0, sizeof(struct sata_fis_h2d));
cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
cfis.command = ATA_CMD_IDLE;
return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
-}
-ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) -{
return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD);
-}
-ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) -{
return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD);
mv_ata_exec_ata_cmd_nondma(dev, port, &cfis, NULL, 0, READ_CMD);
}
/* @@ -916,25 +879,17 @@ static void mvsata_ide_conf_mbus_windows(void) } }
-int init_sata(int dev) +static int sata_mv_init_sata(struct udevice *dev, int port) {
struct mv_priv *priv;
struct mv_priv *priv = dev_get_platdata(dev);
debug("Initialize sata dev: %d\n", dev);
debug("Initialize sata dev: %d\n", port);
if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
printf("Invalid sata device %d\n", dev);
if (port < 0 || port >= CONFIG_SYS_SATA_MAX_DEVICE) {
printf("Invalid sata device %d\n", port); return -1; }
priv = (struct mv_priv *)malloc(sizeof(struct mv_priv));
if (!priv) {
printf("Failed to allocate memory for private sata data\n");
return -ENOMEM;
}
memset((void *)priv, 0, sizeof(struct mv_priv));
/* Allocate and align request buffer */ priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE + CRQB_ALIGN);
@@ -959,11 +914,9 @@ int init_sata(int dev) priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) & ~(CRPB_ALIGN - 1));
sata_dev_desc[dev].priv = (void *)priv;
sprintf(priv->name, "SATA%d", port);
sprintf(priv->name, "SATA%d", dev);
priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE;
priv->regbase = port == 0 ? SATA0_BASE : SATA1_BASE; if (!hw_init) { debug("Initialize sata hw\n");
@@ -972,9 +925,9 @@ int init_sata(int dev) mvsata_ide_conf_mbus_windows(); }
mv_reset_port(dev);
mv_reset_port(dev, port);
if (probe_port(dev)) {
if (probe_port(dev, port)) { priv->link = 0; return -ENODEV; }
@@ -983,19 +936,15 @@ int init_sata(int dev) return 0; }
-int reset_sata(int dev) -{
return 0;
-}
-int scan_sata(int port) +static int sata_mv_scan_sata(struct udevice *dev, int port) {
struct blk_desc *desc = dev_get_uclass_platdata(dev);
struct mv_priv *priv = dev_get_platdata(dev); unsigned char serial[ATA_ID_SERNO_LEN + 1]; unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; unsigned char product[ATA_ID_PROD_LEN + 1]; u64 n_sectors; u16 *id;
struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; if (!priv->link) return -ENODEV;
@@ -1006,7 +955,7 @@ int scan_sata(int port) return -ENOMEM; }
mv_sata_identify(port, id);
mv_sata_identify(dev, port, id); ata_swap_buf_le16(id, ATA_ID_WORDS);
#ifdef DEBUG ata_dump_id(id); @@ -1014,23 +963,23 @@ int scan_sata(int port)
/* Serial number */ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
memcpy(sata_dev_desc[port].product, serial, sizeof(serial));
memcpy(desc->product, serial, sizeof(serial)); /* Firmware version */ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware));
memcpy(desc->revision, firmware, sizeof(firmware)); /* Product model */ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
memcpy(sata_dev_desc[port].vendor, product, sizeof(product));
memcpy(desc->vendor, product, sizeof(product)); /* Total sectors */ n_sectors = ata_id_n_sectors(id);
sata_dev_desc[port].lba = n_sectors;
desc->lba = n_sectors; /* Check if support LBA48 */ if (ata_id_has_lba48(id)) {
sata_dev_desc[port].lba48 = 1;
desc->lba48 = 1; debug("Device support LBA48\n"); }
@@ -1038,13 +987,110 @@ int scan_sata(int port) priv->queue_depth = ata_id_queue_depth(id);
/* Get the xfer mode from device */
mv_sata_xfer_mode(port, id);
mv_sata_xfer_mode(dev, port, id); /* Set the xfer mode to highest speed */
mv_sata_set_features(port);
mv_sata_set_features(dev, port); /* Start up */
mv_start_edma_engine(port);
mv_start_edma_engine(dev, port); return 0;
}
+static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr,
lbaint_t blkcnt, void *buffer)
+{
struct mv_priv *priv = dev_get_platdata(blk);
return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
buffer, READ_CMD);
+}
+static ulong sata_mv_write(struct udevice *blk, lbaint_t blknr,
lbaint_t blkcnt, const void *buffer)
+{
struct mv_priv *priv = dev_get_platdata(blk);
return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
(void *)buffer, WRITE_CMD);
+}
+static const struct blk_ops sata_mv_blk_ops = {
.read = sata_mv_read,
.write = sata_mv_write,
+};
+U_BOOT_DRIVER(sata_mv_driver) = {
.name = "sata_mv_blk",
.id = UCLASS_BLK,
.ops = &sata_mv_blk_ops,
.platdata_auto_alloc_size = sizeof(struct mv_priv),
+};
+static int sata_mv_probe(struct udevice *dev) +{
const void *blob = gd->fdt_blob;
int node = dev_of_offset(dev);
struct mv_priv *priv;
struct udevice *blk;
int nr_ports;
int ret;
int i;
/* Get number of ports of this SATA controller */
nr_ports = min(fdtdec_get_int(blob, node, "nr-ports", -1),
CONFIG_SYS_SATA_MAX_DEVICE);
for (i = 0; i < nr_ports; i++) {
ret = blk_create_devicef(dev, "sata_mv_blk", "blk",
IF_TYPE_SATA, -1, 512, 0, &blk);
if (ret) {
debug("Can't create device\n");
return ret;
}
priv = dev_get_platdata(blk);
priv->dev_nr = i;
/* Init SATA port */
ret = sata_mv_init_sata(blk, i);
if (ret) {
debug("%s: Failed to init bus\n", __func__);
return ret;
}
/* Scan SATA port */
ret = sata_mv_scan_sata(blk, i);
if (ret) {
debug("%s: Failed to scan bus\n", __func__);
return ret;
}
}
return 0;
+}
+static int sata_mv_scan(struct udevice *dev) +{
/* Nothing to do here */
return 0;
+}
+static const struct udevice_id sata_mv_ids[] = {
{ .compatible = "marvell,armada-370-sata" },
{ }
+};
+struct ahci_ops sata_mv_ahci_ops = {
.scan = sata_mv_scan,
+};
+U_BOOT_DRIVER(sata_mv_ahci) = {
.name = "sata_mv_ahci",
.id = UCLASS_AHCI,
.of_match = sata_mv_ids,
.ops = &sata_mv_ahci_ops,
.probe = sata_mv_probe,
+};
2.21.0
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

On 11.03.19 13:29, Stefan Roese wrote:
This patch adds DM support to the Armada XP SATA driver. This is needed to enable CONFIG_BLK on this platform. It adds the SATA controller as AHCI device, which is strictly speaking not correct, as the controller is not AHCI compatible. But the U-Boot AHCI uclass interface enables the usage of this DM driver and the creation of the corresponding BLK devices.
This conversion is done to get rid of the compile warning: ===================== WARNING ====================== This board does not use CONFIG_DM_SCSI. Please update the storage controller to use CONFIG_DM_SCSI before the v2019.07 release. Failure to update by the deadline may result in board removal. See doc/driver-model/MIGRATION.txt for more info. ====================================================
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Applied to u-boot-marvell/master.
Thanks, Stefan
participants (3)
-
Chris Packham
-
Stefan Roese
-
Tom Rini