drivers/ata/sata_highbank.c

Source file repositories/reference/linux-study-clean/drivers/ata/sata_highbank.c

File Facts

System
Linux kernel
Corpus path
drivers/ata/sata_highbank.c
Extension
.c
Size
17541 bytes
Lines
633
Domain
Driver Families
Bucket
drivers/ata
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct phy_lane_info {
	void __iomem *phy_base;
	u8 lane_mapping;
	u8 phy_devs;
	u8 tx_atten;
};
static struct phy_lane_info port_data[CPHY_PORT_COUNT];

static DEFINE_SPINLOCK(sgpio_lock);
#define SCLOCK				0
#define SLOAD				1
#define SDATA				2
#define SGPIO_PINS			3
#define SGPIO_PORTS			8

struct ecx_plat_data {
	u32		n_ports;
	/* number of extra clocks that the SGPIO PIC controller expects */
	u32		pre_clocks;
	u32		post_clocks;
	struct gpio_desc *sgpio_gpiod[SGPIO_PINS];
	u32		sgpio_pattern;
	u32		port_to_sgpio[SGPIO_PORTS];
};

#define SGPIO_SIGNALS			3
#define ECX_ACTIVITY_BITS		0x300000
#define ECX_ACTIVITY_SHIFT		0
#define ECX_LOCATE_BITS			0x80000
#define ECX_LOCATE_SHIFT		1
#define ECX_FAULT_BITS			0x400000
#define ECX_FAULT_SHIFT			2
static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port,
				u32 shift)
{
	return 1 << (3 * pdata->port_to_sgpio[port] + shift);
}

static void ecx_parse_sgpio(struct ecx_plat_data *pdata, u32 port, u32 state)
{
	if (state & ECX_ACTIVITY_BITS)
		pdata->sgpio_pattern |= sgpio_bit_shift(pdata, port,
						ECX_ACTIVITY_SHIFT);
	else
		pdata->sgpio_pattern &= ~sgpio_bit_shift(pdata, port,
						ECX_ACTIVITY_SHIFT);
	if (state & ECX_LOCATE_BITS)
		pdata->sgpio_pattern |= sgpio_bit_shift(pdata, port,
						ECX_LOCATE_SHIFT);
	else
		pdata->sgpio_pattern &= ~sgpio_bit_shift(pdata, port,
						ECX_LOCATE_SHIFT);
	if (state & ECX_FAULT_BITS)
		pdata->sgpio_pattern |= sgpio_bit_shift(pdata, port,
						ECX_FAULT_SHIFT);
	else
		pdata->sgpio_pattern &= ~sgpio_bit_shift(pdata, port,
						ECX_FAULT_SHIFT);
}

/*
 * Tell the LED controller that the signal has changed by raising the clock
 * line for 50 uS and then lowering it for 50 uS.
 */
static void ecx_led_cycle_clock(struct ecx_plat_data *pdata)
{
	gpiod_set_value(pdata->sgpio_gpiod[SCLOCK], 1);
	udelay(50);
	gpiod_set_value(pdata->sgpio_gpiod[SCLOCK], 0);
	udelay(50);
}

static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state,
					ssize_t size)
{
	struct ahci_host_priv *hpriv =  ap->host->private_data;
	struct ecx_plat_data *pdata = hpriv->plat_data;
	struct ahci_port_priv *pp = ap->private_data;
	unsigned long flags;
	int pmp, i;
	struct ahci_em_priv *emp;
	u32 sgpio_out;

	/* get the slot number from the message */
	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
	if (pmp < EM_MAX_SLOTS)
		emp = &pp->em_priv[pmp];
	else
		return -EINVAL;

Annotation

Implementation Notes