drivers/misc/gehc-achc.c

Source file repositories/reference/linux-study-clean/drivers/misc/gehc-achc.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/gehc-achc.c
Extension
.c
Size
12944 bytes
Lines
567
Domain
Driver Families
Bucket
drivers/misc
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 achc_data {
	struct spi_device *main;
	struct spi_device *ezport;
	struct gpio_desc *reset;

	struct mutex device_lock; /* avoid concurrent device access */
};

#define EZPORT_RESET_DELAY_MS	100
#define EZPORT_STARTUP_DELAY_MS	200
#define EZPORT_WRITE_WAIT_MS	10
#define EZPORT_TRANSFER_SIZE	2048

#define EZPORT_CMD_SP		0x02 /* flash section program */
#define EZPORT_CMD_RDSR		0x05 /* read status register */
#define EZPORT_CMD_WREN		0x06 /* write enable */
#define EZPORT_CMD_FAST_READ	0x0b /* flash read data at high speed */
#define EZPORT_CMD_RESET	0xb9 /* reset chip */
#define EZPORT_CMD_BE		0xc7 /* bulk erase */
#define EZPORT_CMD_SE		0xd8 /* sector erase */

#define EZPORT_SECTOR_SIZE	4096
#define EZPORT_SECTOR_MASK	(EZPORT_SECTOR_SIZE - 1)

#define EZPORT_STATUS_WIP	BIT(0) /* write in progress */
#define EZPORT_STATUS_WEN	BIT(1) /* write enable */
#define EZPORT_STATUS_BEDIS	BIT(2) /* bulk erase disable */
#define EZPORT_STATUS_FLEXRAM	BIT(3) /* FlexRAM mode */
#define EZPORT_STATUS_WEF	BIT(6) /* write error flag */
#define EZPORT_STATUS_FS	BIT(7) /* flash security */

static void ezport_reset(struct gpio_desc *reset)
{
	gpiod_set_value(reset, 1);
	msleep(EZPORT_RESET_DELAY_MS);
	gpiod_set_value(reset, 0);
	msleep(EZPORT_STARTUP_DELAY_MS);
}

static int ezport_start_programming(struct spi_device *spi, struct gpio_desc *reset)
{
	struct spi_message msg;
	struct spi_transfer assert_cs = {
		.cs_change   = 1,
	};
	struct spi_transfer release_cs = { };
	int ret;

	spi_bus_lock(spi->controller);

	/* assert chip select */
	spi_message_init(&msg);
	spi_message_add_tail(&assert_cs, &msg);
	ret = spi_sync_locked(spi, &msg);
	if (ret)
		goto fail;

	msleep(EZPORT_STARTUP_DELAY_MS);

	/* reset with asserted chip select to switch into programming mode */
	ezport_reset(reset);

	/* release chip select */
	spi_message_init(&msg);
	spi_message_add_tail(&release_cs, &msg);
	ret = spi_sync_locked(spi, &msg);

fail:
	spi_bus_unlock(spi->controller);
	return ret;
}

static void ezport_stop_programming(struct spi_device *spi, struct gpio_desc *reset)
{
	/* reset without asserted chip select to return into normal mode */
	spi_bus_lock(spi->controller);
	ezport_reset(reset);
	spi_bus_unlock(spi->controller);
}

static int ezport_get_status_register(struct spi_device *spi)
{
	int ret;

	ret = spi_w8r8(spi, EZPORT_CMD_RDSR);
	if (ret < 0)
		return ret;
	if (ret == 0xff) {
		dev_err(&spi->dev, "Invalid EzPort status, EzPort is not functional!\n");
		return -EINVAL;

Annotation

Implementation Notes