drivers/mfd/ocelot-spi.c

Source file repositories/reference/linux-study-clean/drivers/mfd/ocelot-spi.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/ocelot-spi.c
Extension
.c
Size
8370 bytes
Lines
299
Domain
Driver Families
Bucket
drivers/mfd
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
 * SPI core driver for the Ocelot chip family.
 *
 * This driver will handle everything necessary to allow for communication over
 * SPI to the VSC7511, VSC7512, VSC7513 and VSC7514 chips. The main functions
 * are to prepare the chip's SPI interface for a specific bus speed, and a host
 * processor's endianness. This will create and distribute regmaps for any
 * children.
 *
 * Copyright 2021-2022 Innovative Advantage Inc.
 *
 * Author: Colin Foster <colin.foster@in-advantage.com>
 */

#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/ioport.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
#include <linux/units.h>

#include "ocelot.h"

#define REG_DEV_CPUORG_IF_CTRL		0x0000
#define REG_DEV_CPUORG_IF_CFGSTAT	0x0004

#define CFGSTAT_IF_NUM_VCORE		(0 << 24)
#define CFGSTAT_IF_NUM_VRAP		(1 << 24)
#define CFGSTAT_IF_NUM_SI		(2 << 24)
#define CFGSTAT_IF_NUM_MIIM		(3 << 24)

#define VSC7512_DEVCPU_ORG_RES_START	0x71000000
#define VSC7512_DEVCPU_ORG_RES_SIZE	0x38

#define VSC7512_CHIP_REGS_RES_START	0x71070000
#define VSC7512_CHIP_REGS_RES_SIZE	0x14

static const struct resource vsc7512_dev_cpuorg_resource =
	DEFINE_RES_REG_NAMED(VSC7512_DEVCPU_ORG_RES_START,
			     VSC7512_DEVCPU_ORG_RES_SIZE,
			     "devcpu_org");

static const struct resource vsc7512_gcb_resource =
	DEFINE_RES_REG_NAMED(VSC7512_CHIP_REGS_RES_START,
			     VSC7512_CHIP_REGS_RES_SIZE,
			     "devcpu_gcb_chip_regs");

static int ocelot_spi_initialize(struct device *dev)
{
	struct ocelot_ddata *ddata = dev_get_drvdata(dev);
	u32 val, check;
	int err;

	val = OCELOT_SPI_BYTE_ORDER;

	/*
	 * The SPI address must be big-endian, but we want the payload to match
	 * our CPU. These are two bits (0 and 1) but they're repeated such that
	 * the write from any configuration will be valid. The four
	 * configurations are:
	 *
	 * 0b00: little-endian, MSB first
	 * |            111111   | 22221111 | 33222222 |
	 * | 76543210 | 54321098 | 32109876 | 10987654 |
	 *
	 * 0b01: big-endian, MSB first
	 * | 33222222 | 22221111 | 111111   |          |
	 * | 10987654 | 32109876 | 54321098 | 76543210 |
	 *
	 * 0b10: little-endian, LSB first
	 * |              111111 | 11112222 | 22222233 |
	 * | 01234567 | 89012345 | 67890123 | 45678901 |
	 *
	 * 0b11: big-endian, LSB first
	 * | 22222233 | 11112222 |   111111 |          |
	 * | 45678901 | 67890123 | 89012345 | 01234567 |
	 */
	err = regmap_write(ddata->cpuorg_regmap, REG_DEV_CPUORG_IF_CTRL, val);
	if (err)
		return err;

	/*
	 * Apply the number of padding bytes between a read request and the data
	 * payload. Some registers have access times of up to 1us, so if the

Annotation

Implementation Notes