brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 9cccf54 Raw
235 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)2/*3 * Core driver for the Ocelot chip family.4 *5 * The VSC7511, 7512, 7513, and 7514 can be controlled internally via an6 * on-chip MIPS processor, or externally via SPI, I2C, PCIe. This core driver is7 * intended to be the bus-agnostic glue between, for example, the SPI bus and8 * the child devices.9 *10 * Copyright 2021-2022 Innovative Advantage Inc.11 *12 * Author: Colin Foster <colin.foster@in-advantage.com>13 */14 15#include <linux/bits.h>16#include <linux/device.h>17#include <linux/export.h>18#include <linux/iopoll.h>19#include <linux/ioport.h>20#include <linux/kernel.h>21#include <linux/mfd/core.h>22#include <linux/mfd/ocelot.h>23#include <linux/module.h>24#include <linux/regmap.h>25#include <linux/types.h>26 27#include <soc/mscc/ocelot.h>28 29#include "ocelot.h"30 31#define REG_GCB_SOFT_RST		0x000832 33#define BIT_SOFT_CHIP_RST		BIT(0)34 35#define VSC7512_MIIM0_RES_START		0x7107009c36#define VSC7512_MIIM1_RES_START		0x710700c037#define VSC7512_MIIM_RES_SIZE		0x0000002438 39#define VSC7512_PHY_RES_START		0x710700f040#define VSC7512_PHY_RES_SIZE		0x0000000441 42#define VSC7512_GPIO_RES_START		0x7107003443#define VSC7512_GPIO_RES_SIZE		0x0000006c44 45#define VSC7512_SIO_CTRL_RES_START	0x710700f846#define VSC7512_SIO_CTRL_RES_SIZE	0x0000010047 48#define VSC7512_HSIO_RES_START		0x710d000049#define VSC7512_HSIO_RES_SIZE		0x0000012850 51#define VSC7512_ANA_RES_START		0x7188000052#define VSC7512_ANA_RES_SIZE		0x0001000053 54#define VSC7512_QS_RES_START		0x7108000055#define VSC7512_QS_RES_SIZE		0x0000010056 57#define VSC7512_QSYS_RES_START		0x7180000058#define VSC7512_QSYS_RES_SIZE		0x0020000059 60#define VSC7512_REW_RES_START		0x7103000061#define VSC7512_REW_RES_SIZE		0x0001000062 63#define VSC7512_SYS_RES_START		0x7101000064#define VSC7512_SYS_RES_SIZE		0x0001000065 66#define VSC7512_S0_RES_START		0x7104000067#define VSC7512_S1_RES_START		0x7105000068#define VSC7512_S2_RES_START		0x7106000069#define VCAP_RES_SIZE			0x0000040070 71#define VSC7512_PORT_0_RES_START	0x711e000072#define VSC7512_PORT_1_RES_START	0x711f000073#define VSC7512_PORT_2_RES_START	0x7120000074#define VSC7512_PORT_3_RES_START	0x7121000075#define VSC7512_PORT_4_RES_START	0x7122000076#define VSC7512_PORT_5_RES_START	0x7123000077#define VSC7512_PORT_6_RES_START	0x7124000078#define VSC7512_PORT_7_RES_START	0x7125000079#define VSC7512_PORT_8_RES_START	0x7126000080#define VSC7512_PORT_9_RES_START	0x7127000081#define VSC7512_PORT_10_RES_START	0x7128000082#define VSC7512_PORT_RES_SIZE		0x0001000083 84#define VSC7512_GCB_RST_SLEEP_US	10085#define VSC7512_GCB_RST_TIMEOUT_US	10000086 87static int ocelot_gcb_chip_rst_status(struct ocelot_ddata *ddata)88{89	int val, err;90 91	err = regmap_read(ddata->gcb_regmap, REG_GCB_SOFT_RST, &val);92	if (err)93		return err;94 95	return val;96}97 98int ocelot_chip_reset(struct device *dev)99{100	struct ocelot_ddata *ddata = dev_get_drvdata(dev);101	int ret, val;102 103	/*104	 * Reset the entire chip here to put it into a completely known state.105	 * Other drivers may want to reset their own subsystems. The register106	 * self-clears, so one write is all that is needed and wait for it to107	 * clear.108	 */109	ret = regmap_write(ddata->gcb_regmap, REG_GCB_SOFT_RST, BIT_SOFT_CHIP_RST);110	if (ret)111		return ret;112 113	return readx_poll_timeout(ocelot_gcb_chip_rst_status, ddata, val, !val,114				  VSC7512_GCB_RST_SLEEP_US, VSC7512_GCB_RST_TIMEOUT_US);115}116EXPORT_SYMBOL_NS(ocelot_chip_reset, MFD_OCELOT);117 118static const struct resource vsc7512_miim0_resources[] = {119	DEFINE_RES_REG_NAMED(VSC7512_MIIM0_RES_START, VSC7512_MIIM_RES_SIZE, "gcb_miim0"),120	DEFINE_RES_REG_NAMED(VSC7512_PHY_RES_START, VSC7512_PHY_RES_SIZE, "gcb_phy"),121};122 123static const struct resource vsc7512_miim1_resources[] = {124	DEFINE_RES_REG_NAMED(VSC7512_MIIM1_RES_START, VSC7512_MIIM_RES_SIZE, "gcb_miim1"),125};126 127static const struct resource vsc7512_pinctrl_resources[] = {128	DEFINE_RES_REG_NAMED(VSC7512_GPIO_RES_START, VSC7512_GPIO_RES_SIZE, "gcb_gpio"),129};130 131static const struct resource vsc7512_sgpio_resources[] = {132	DEFINE_RES_REG_NAMED(VSC7512_SIO_CTRL_RES_START, VSC7512_SIO_CTRL_RES_SIZE, "gcb_sio"),133};134 135static const struct resource vsc7512_serdes_resources[] = {136	DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"),137};138 139static const struct resource vsc7512_switch_resources[] = {140	DEFINE_RES_REG_NAMED(VSC7512_ANA_RES_START, VSC7512_ANA_RES_SIZE, "ana"),141	DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"),142	DEFINE_RES_REG_NAMED(VSC7512_QS_RES_START, VSC7512_QS_RES_SIZE, "qs"),143	DEFINE_RES_REG_NAMED(VSC7512_QSYS_RES_START, VSC7512_QSYS_RES_SIZE, "qsys"),144	DEFINE_RES_REG_NAMED(VSC7512_REW_RES_START, VSC7512_REW_RES_SIZE, "rew"),145	DEFINE_RES_REG_NAMED(VSC7512_SYS_RES_START, VSC7512_SYS_RES_SIZE, "sys"),146	DEFINE_RES_REG_NAMED(VSC7512_S0_RES_START, VCAP_RES_SIZE, "s0"),147	DEFINE_RES_REG_NAMED(VSC7512_S1_RES_START, VCAP_RES_SIZE, "s1"),148	DEFINE_RES_REG_NAMED(VSC7512_S2_RES_START, VCAP_RES_SIZE, "s2"),149	DEFINE_RES_REG_NAMED(VSC7512_PORT_0_RES_START, VSC7512_PORT_RES_SIZE, "port0"),150	DEFINE_RES_REG_NAMED(VSC7512_PORT_1_RES_START, VSC7512_PORT_RES_SIZE, "port1"),151	DEFINE_RES_REG_NAMED(VSC7512_PORT_2_RES_START, VSC7512_PORT_RES_SIZE, "port2"),152	DEFINE_RES_REG_NAMED(VSC7512_PORT_3_RES_START, VSC7512_PORT_RES_SIZE, "port3"),153	DEFINE_RES_REG_NAMED(VSC7512_PORT_4_RES_START, VSC7512_PORT_RES_SIZE, "port4"),154	DEFINE_RES_REG_NAMED(VSC7512_PORT_5_RES_START, VSC7512_PORT_RES_SIZE, "port5"),155	DEFINE_RES_REG_NAMED(VSC7512_PORT_6_RES_START, VSC7512_PORT_RES_SIZE, "port6"),156	DEFINE_RES_REG_NAMED(VSC7512_PORT_7_RES_START, VSC7512_PORT_RES_SIZE, "port7"),157	DEFINE_RES_REG_NAMED(VSC7512_PORT_8_RES_START, VSC7512_PORT_RES_SIZE, "port8"),158	DEFINE_RES_REG_NAMED(VSC7512_PORT_9_RES_START, VSC7512_PORT_RES_SIZE, "port9"),159	DEFINE_RES_REG_NAMED(VSC7512_PORT_10_RES_START, VSC7512_PORT_RES_SIZE, "port10")160};161 162static const struct mfd_cell vsc7512_devs[] = {163	{164		.name = "ocelot-pinctrl",165		.of_compatible = "mscc,ocelot-pinctrl",166		.num_resources = ARRAY_SIZE(vsc7512_pinctrl_resources),167		.resources = vsc7512_pinctrl_resources,168	}, {169		.name = "ocelot-sgpio",170		.of_compatible = "mscc,ocelot-sgpio",171		.num_resources = ARRAY_SIZE(vsc7512_sgpio_resources),172		.resources = vsc7512_sgpio_resources,173	}, {174		.name = "ocelot-miim0",175		.of_compatible = "mscc,ocelot-miim",176		.of_reg = VSC7512_MIIM0_RES_START,177		.use_of_reg = true,178		.num_resources = ARRAY_SIZE(vsc7512_miim0_resources),179		.resources = vsc7512_miim0_resources,180	}, {181		.name = "ocelot-miim1",182		.of_compatible = "mscc,ocelot-miim",183		.of_reg = VSC7512_MIIM1_RES_START,184		.use_of_reg = true,185		.num_resources = ARRAY_SIZE(vsc7512_miim1_resources),186		.resources = vsc7512_miim1_resources,187	}, {188		.name = "ocelot-serdes",189		.of_compatible = "mscc,vsc7514-serdes",190		.num_resources = ARRAY_SIZE(vsc7512_serdes_resources),191		.resources = vsc7512_serdes_resources,192	}, {193		.name = "ocelot-ext-switch",194		.of_compatible = "mscc,vsc7512-switch",195		.num_resources = ARRAY_SIZE(vsc7512_switch_resources),196		.resources = vsc7512_switch_resources,197	},198};199 200static void ocelot_core_try_add_regmap(struct device *dev,201				       const struct resource *res)202{203	if (dev_get_regmap(dev, res->name))204		return;205 206	ocelot_spi_init_regmap(dev, res);207}208 209static void ocelot_core_try_add_regmaps(struct device *dev,210					const struct mfd_cell *cell)211{212	int i;213 214	for (i = 0; i < cell->num_resources; i++)215		ocelot_core_try_add_regmap(dev, &cell->resources[i]);216}217 218int ocelot_core_init(struct device *dev)219{220	int i, ndevs;221 222	ndevs = ARRAY_SIZE(vsc7512_devs);223 224	for (i = 0; i < ndevs; i++)225		ocelot_core_try_add_regmaps(dev, &vsc7512_devs[i]);226 227	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, vsc7512_devs, ndevs, NULL, 0, NULL);228}229EXPORT_SYMBOL_NS(ocelot_core_init, MFD_OCELOT);230 231MODULE_DESCRIPTION("Externally Controlled Ocelot Chip Driver");232MODULE_AUTHOR("Colin Foster <colin.foster@in-advantage.com>");233MODULE_LICENSE("GPL");234MODULE_IMPORT_NS(MFD_OCELOT_SPI);235