// SPDX-License-Identifier: GPL-2.0-or-later
/*
* drivers/ata/sata_fsl.c
*
* Freescale 3.0Gbps SATA device driver
*
* Author: Ashish Kalra <ashish.kalra@freescale.com>
* Li Yang <leoli@freescale.com>
*
* Copyright (c) 2006-2007, 2011-2012 Freescale Semiconductor, Inc.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
#include <asm/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
static unsigned int intr_coalescing_count;
module_param(intr_coalescing_count, int, S_IRUGO);
MODULE_PARM_DESC(intr_coalescing_count,
"INT coalescing count threshold (1..31)");
static unsigned int intr_coalescing_ticks;
module_param(intr_coalescing_ticks, int, S_IRUGO);
MODULE_PARM_DESC(intr_coalescing_ticks,
"INT coalescing timer threshold in AHB ticks");
/* Controller information */
enum {
SATA_FSL_QUEUE_DEPTH = 16,
SATA_FSL_MAX_PRD = 63,
SATA_FSL_MAX_PRD_USABLE = SATA_FSL_MAX_PRD - 1,
SATA_FSL_MAX_PRD_DIRECT = 16, /* Direct PRDT entries */
SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
ATA_FLAG_PMP | ATA_FLAG_NCQ |
ATA_FLAG_AN | ATA_FLAG_NO_LOG_PAGE),
SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
SATA_FSL_CMD_SLOT_SIZE = (SATA_FSL_MAX_CMDS * SATA_FSL_CMD_HDR_SIZE),
/*
* SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and
* chained indirect PRDEs up to a max count of 63.
* We are allocating an array of 63 PRDEs contiguously, but PRDE#15 will
* be setup as an indirect descriptor, pointing to it's next
* (contiguous) PRDE. Though chained indirect PRDE arrays are
* supported,it will be more efficient to use a direct PRDT and
* a single chain/link to indirect PRDE array/PRDT.
*/
SATA_FSL_CMD_DESC_CFIS_SZ = 32,
SATA_FSL_CMD_DESC_SFIS_SZ = 32,
SATA_FSL_CMD_DESC_ACMD_SZ = 16,
SATA_FSL_CMD_DESC_RSRVD = 16,
SATA_FSL_CMD_DESC_SIZE = (SATA_FSL_CMD_DESC_CFIS_SZ +
SATA_FSL_CMD_DESC_SFIS_SZ +
SATA_FSL_CMD_DESC_ACMD_SZ +
SATA_FSL_CMD_DESC_RSRVD +
SATA_FSL_MAX_PRD * 16),
SATA_FSL_CMD_DESC_OFFSET_TO_PRDT =
(SATA_FSL_CMD_DESC_CFIS_SZ +
SATA_FSL_CMD_DESC_SFIS_SZ +
SATA_FSL_CMD_DESC_ACMD_SZ +
SATA_FSL_CMD_DESC_RSRVD),
SATA_FSL_CMD_DESC_AR_SZ = (SATA_FSL_CMD_DESC_SIZE * SATA_FSL_MAX_CMDS),
SATA_FSL_PORT_PRIV_DMA_SZ = (SATA_FSL_CMD_SLOT_SIZE +
SATA_FSL_CMD_DESC_AR_SZ),
/*
* MPC8315 has two SATA controllers, SATA1 & SATA2
* (one port per controller)
* MPC837x has 2/4 controllers, one port per controller
*/
SATA_FSL_MAX_PORTS = 1,
SATA_FSL_IRQ_FLAG = IRQF_SHARED,
};
/*
* Interrupt Coalescing Control Register bitdefs */
enum {
ICC_MIN_INT_COUNT_THRESHOLD = 1,
ICC_MAX_INT_COUNT_THRESHOLD = ((1 << 5) - 1),
ICC_MIN_INT_TICKS_THRESHOLD = 0,
ICC_MAX_INT_TICKS_THRESHOLD = ((1 << 19) - 1),
ICC_SAFE_INT_TICKS = 1,
};
/*
* Host Controller command register set - per port
*/
enum {
CQ = 0,
CA = 8,
CC = 0x10,
CE = 0x18,
DE = 0x20,
CHBA = 0x24,
HSTATUS = 0x28,
HCONTROL = 0x2C,
CQPMP = 0x30,
SIGNATURE = 0x34,
ICC = 0x38,
/*
* Host Status Register (HStatus) bitdefs
*/
ONLINE = (1 << 31),
GOING_OFFLINE = (1 << 30),
BIST_ERR = (1 << 29),
CLEAR_ERROR = (1 << 27),
FATAL_ERR_HC_MASTER_ERR = (1 << 18),
FATAL_ERR_PARITY_ERR_TX = (1 << 17),
FATAL_ERR_PARITY_ERR_RX = (1 << 16),
FATAL_ERR_DATA_UNDERRUN = (1 << 13),
FATAL_ERR_DATA_OVERRUN = (1 << 12),
FATAL_ERR_CRC_ERR_TX = (1 << 11),
FATAL_ERR_CRC_ERR_RX = (1 << 10),
FATAL_ERR_FIFO_OVRFL_TX = (1 << 9),
FATAL_ERR_FIFO_OVRFL_RX = (1 << 8),
FATAL_ERROR_DECODE = FATAL_ERR_HC_MASTER_ERR |
FATAL_ERR_PARITY_ERR_TX |
FATAL_ERR_PARITY_ERR_RX |
FATAL_ERR_DATA_UNDERRUN |
FATAL_ERR_DATA_OVERRUN |
FATAL_ERR_CRC_ERR_TX |
FATAL_ERR_CRC_ERR_RX |
FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX,
INT_ON_DATA_LENGTH_MISMATCH = (1 << 12),
INT_ON_FATAL_ERR = (1 << 5),
INT_ON_PHYRDY_CHG = (1 << 4),
INT_ON_SIGNATURE_UPDATE = (1 << 3),
INT_ON_SNOTIFY_UPDATE = (1 << 2),
INT_ON_SINGL_DEVICE_ERR = (1 << 1),
INT_ON_CMD_COMPLETE = 1,
INT_ON_ERROR = INT_ON_FATAL_ERR | INT_ON_SNOTIFY_UPDATE |
INT_ON_PHYRDY_CHG | INT_ON_SINGL_DEVICE_ERR,
/*
* Host Control Register (HControl) bitdefs
*/
HCONTROL_ONLINE_PHY_RST = (1 << 31),
HCONTROL_FORCE_OFFLINE = (1 << 30),
HCONTROL_LEGACY = (1 << 28),
HCONTROL_PARITY_PROT_MOD = (1 << 14),
HCONTROL_DPATH
|